Blinking black, while the backbuffer stay filled

Started by
2 comments, last by Maverick89 18 years, 10 months ago
OK, here is my next noob question: I use D3D9. My "game" starts, by creatng d3d device, and showing an image as loadscreen. I loaded the image into a offscreen-surface. Then i used stretchrect to put the image into backbuffer and finally present(). then the application should just load all it needs to start befor entering the main loop with more drawing. Running: the image get shown, but after some seconds it was black again... So, I got interested and just added the present() function to the main loop. I didnt redraw the backbuffer coz it still holds the loaded image. So, what I get is the image BLINKING - black lines blink all over the screen. Looks like the frontbuffer get filled, presented, then cleared (but i dont do that!) and presented again many times per monitor's frame. The question is: why? here are some of my functions: Main unit
program engine;

uses
  Forms,
  dxmgr in 'dxmgr.pas',
  xform in 'xform.pas',
  constants in 'constants.pas',
  windows, messages, dialogs, sysutils;

{$R *.res}

var wc: TWndClass;
    WindowHandle: integer;
    Msg: TMsg;


function WndProc(hwnd, uMsg, wParam, lParam: integer): integer; stdcall;
begin
  if uMsg = WM_DESTROY then begin
    game.ReleaseEngine;
    postquitmessage(0);
  end;
  Result:= DefWindowProc(hwnd, uMsg, wParam, lParam);
end;


begin       //Entry point!!!!
   
  game := cgame.create;
  game.apppath := extractfilepath(application.ExeName);
  chdir(game.apppath);
  getgameopts;
    // Register the window class for the main window.
  ZeroMemory(@wc, sizeof(wc));
  wc.style:= 0;
  wc.lpfnWndProc:= @WndProc;
  wc.cbClsExtra:= 0;
  wc.cbWndExtra:= 0;
  wc.hInstance:= hInstance;
  wc.hIcon:= 0;
  wc.hCursor:= 0;
  wc.hbrBackground:= GetStockObject(BLACK_BRUSH);
  wc.lpszMenuName:= nil;
  wc.lpszClassName:= APP_NAME;

  if RegisterClass(wc) = 0 then begin
    messagedlg('Window Registration failed', mterror, [mbok], 0);
    Halt(1);
  end;

  // Create the main window.
  WindowHandle := CreateWindow(  //WS_EX_TOPMOST
                               APP_NAME,
                               APP_NAME,
                               WS_EX_TOPMOST or WS_POPUP or WS_VISIBLE,
                               Integer(CW_USEDEFAULT),
                               Integer(CW_USEDEFAULT),
                               GameOpts.WWidth,
                               gameopts.WHeight,
                               GetDesktopWindow,
                               0,
                               hInstance,
                               nil);

  //ShowWindow(WindowHandle, SW_SHOWDEFAULT);
  UpdateWindow(WindowHandle);
  game.WindowHandle := windowhandle;

  game.startgame;

    // Now we're ready to recieve and process Windows messages.
    
  repeat
    if PeekMessage( msg, WindowHandle, 0, 0, PM_REMOVE ) then
    begin
       TranslateMessage ( msg );
       DispatchMessage ( msg );
    end
    else
       game.main( );

  until msg.message =WM_QUIT;




  game.ReleaseEngine;
D3D Initialization:

  function CD3DMgr.init():boolean;
  var d3dpp: D3DPRESENT_PARAMETERS;
      VPtmp: cardinal;
      res: hresult;
  begin
    result := false;
    pD3D := Direct3DCreate9( D3D_SDK_VERSION );
    if pD3D = nil then begin
      messagedlg('DirectX9 not found', mterror, [mbok],0);
      exit;
    end;

    ZeroMemory(@d3dpp, sizeof(d3dpp));
    with d3dpp do begin
      windowed := false;
      SwapEffect := D3DSWAPEFFECT_DISCARD;
      BackBufferFormat := D3DFMT_X8R8G8B8;
      BackBufferCount := 1;
      BackBufferHeight := GameOpts.WHeight;
      BackBufferWidth := GameOpts.WWidth;
      hDeviceWindow := Game.WindowHandle;
      MultiSampleType := D3DMULTISAMPLE_NONE;
      MultiSampleQuality := 0;
      EnableAutoDepthStencil := true;
      d3dpp.AutoDepthStencilFormat :=D3DFMT_D16;
      FullScreen_RefreshRateInHz := GameOpts.RefreshRate;
      PresentationInterval := D3DPRESENT_INTERVAL_DEFAULT;
      Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    end;

    if GameOpts.VertexProcessing  = VPSoftware then
      VPtmp := D3DCREATE_SOFTWARE_VERTEXPROCESSING
    else if GameOpts.VertexProcessing  = VPHardware then
      VPtmp := D3DCREATE_HARDWARE_VERTEXPROCESSING
    else if GameOpts.VertexProcessing = VPMixed then
      VPtmp := D3DCREATE_MIXED_VERTEXPROCESSING;

    //SetFocus(game.WindowHandle);

    res := pD3D.CreateDevice( D3DADAPTER_DEFAULT,
                                   D3DDEVTYPE_HAL,
                                   game.WindowHandle,
                                   VPtmp,
                                   @d3dpp,
                                   pd3dDevice );

    if not(res=D3D_OK) then begin
      //messagedlg(d3derrorstring(res), mterror, [mbOk], 0);
      case res of
        D3DERR_INVALIDCALL: showmessage('D3DERR_INVALIDCALL');
        D3DERR_NOTAVAILABLE: showmessage('D3DERR_NOTAVAILABLE');
        D3DERR_OUTOFVIDEOMEMORY: showmessage('D3DERR_OUTOFVIDEOMEMORY');
      end;
      exit;
    end;

    result := true;
  end;
the simple looped function:
procedure cgame.main();
begin
  fpstimer.updateFPS;
  d3dmgr.pD3DDevice.Present(nil, nil, 0, nil);
end;
--------------------------if freedom is outlawed, only outlaws will have freedom
Advertisement
The purpose of Present() is to flip the D3D backbuffer chain. D3D does double bufferign by default. In other words, even when you're loading, you need to blast your image to screen all the time.

I didn't read all the code, but I think it has to do with you blitting it only once. Just use stretchrect() every frame when you're loading.

Toolmaker

You need to realize how present() works: It doesn't copy the back buffer to the front buffer. This would be far to slow. What it does is change the pointer that tells the monitor where to draw from so that it points to the back buffer. The effect is that the backbuffer becomes the front buffer, and the front buffer becomes the back buffer. So that explains the blinking, half the frames your drawing garbage (because D3DSWAPEFFECT_DISCARD discards what was in the front buffer when the flip occurs).

Why the front buffer is cleared if you don't call present I can't explain. Sure its not because its entering the main loop and starts presenting or something?
Quote:Original post by Hesterumpe
You need to realize how present() works: It doesn't copy the back buffer to the front buffer. This would be far to slow. What it does is change the pointer that tells the monitor where to draw from so that it points to the back buffer. The effect is that the backbuffer becomes the front buffer, and the front buffer becomes the back buffer. So that explains the blinking, half the frames your drawing garbage (because D3DSWAPEFFECT_DISCARD discards what was in the front buffer when the flip occurs).

Why the front buffer is cleared if you don't call present I can't explain. Sure its not because its entering the main loop and starts presenting or something?


OK, now I understand what happens.

About the screen clearing after some seconds after the game start - it looks like a problem of my NVIDIA ForceWare, coz i can see a little slow down on the first seconds of every DX-game running.

Thanx!
--------------------------if freedom is outlawed, only outlaws will have freedom

This topic is closed to new replies.

Advertisement