Tricks of the Windows Game Programming Gurus:Advanced DirectDraw and Bitmapped Graphics

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

### Page Flipping

Once you’ve created a complex surface with a primary surface and a back buffer surface, you’re ready to page flip. The standard animation loop requires these steps (see Figure 7.12):

  1. Clear back buffer.
  2. Render scene to back buffer.
  3. Flip primary surface with back buffer surface.
  4. Lock to frame rate (30 fps, for example).
  5. Repeat step 1.

Figure 7.12 A page flipped animation system.

There are a few details that may confuse you. First, if the back buffer is flipped with the primary buffer, won’t the back buffer become the primary buffer, and vice versa? If so, won’t you need to draw on the primary surface every other frame? Although this may seem to make sense, it’s not what really happens. In reality, pointers to VRAM are switched by the hardware, and from your point of view and DirectDraw’s, the back buffer surface is always offscreen and the primary is always onscreen. Therefore, you always draw to the back buffer and flip with the primary surface each frame.

To flip the primary surface with the next attached surface in the flipping chain, you use the function `IDIRECTDRAWSURFACE4::Flip()`, shown here:

    HRESULT Flip(LPDIRECTDRAWSURFACE4 lpDDSurfaceTargetOverride,  // override

    surface

                 DWORD dwFlags); // control flags

This returns `DD_OK` if successful and an error code if not.

The parameters are simple. `lpDDSurfaceTargetOverride` is basically an advanced parameter used to override the flipping chain and flip to another surface other than the back buffer attached to the primary surface; just send `NULL` here. The `dwFlags` parameter, however, might be of interest to you. Table 7.2 contains the various settings for it.

Table 7.2 Control Flags for `Flip()`

Value | Description
--- | ---

`DDFLIP_INTERVAL2` | Flip after two vertical retraces.
`DDFLIP_INTERVAL3` | Flip after three vertical retraces.
`DDFLIP_INTERVAL4` | Flip after four vertical retraces.

(Note that the default is one vertical retrace.)

These flags indicate how many vertical retraces to wait between each flip. The default is one. DirectDraw will return `DERR_WASSTILLDRAWING` for each surface involved in the flip until the specified number of vertical retraces has occurred. If `DDFLIP_INTERVAL2` is set, DirectDraw will flip on every second vertical sync; if `DDFLIP_INTERVAL3`, on every third sync; and if `DDFLIP_INTERVAL4`, on every fourth sync.

These flags are effective only if `DDCAPS2_FLIPINTERVAL` is set in the `DDCAPS` structure returned for the device.

`DDFLIP_NOVSYNC`—This flag causes DirectDraw to perform the physical flip as close as possible to the next scan line.

`DDFLIP_WAIT`—This flag forces the hardware to wait until a flip is possible rather than returning back immediately if there’s a problem.

It’s possible to create a complex surface with two back buffers or a flipping chain that has a total of three surfaces, including the primary surface. This is called triple buffering, and it gives the ultimate in performance. The reason is obvious: If you have a single back buffer, the video hardware may be bottlenecked by your accessing it along with the video hardware and so on. But with two extra surfaces in the flipping chain, the hardware never has to wait. The beauty of triple buffering with DirectDraw is that you simply use `Flip()` and the hardware flips the surfaces in a cyclic manner, but you still only render to a single back buffer, so it’s transparent to you.

Typically, you’ll set the flags for `DDFLIP_WAIT` and that’s it. Also, you must call `Flip()` as a method from the primary surface, not the back buffer. This should make sense because the primary surface is the “parent” of the back buffer surface, and the back buffer is part of the parent’s flipping chain. Anyway, here’s how you would make the call to flip pages:

    lpddsprimary->Flip(NULL, DDFLIP_WAIT);

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.