Jump to content
  • Advertisement
Sign in to follow this  
Maverick89

Blinking black, while the backbuffer stay filled

This topic is 4806 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!