JavaScript EditorFree JavaScript Editor     Ajax Editor 

Main Page
  Previous Section Next Section

Surface Dynamics

Throughout the book I've mentioned that you can create a number of different types of surfaces, but up to this point you've only seen how to work with primary surfaces. Now I want to talk about offscreen surfaces. Basically, there are two types of offscreen surfaces. The first kind is the back buffer.

Back buffers are surfaces used in an animation chain that have the same geometry and color depth as the primary surface. Back buffer surfaces are unique because you create them as you create the primary surface. They're part of the primary surface's flipping chain. In other words, when you request one or more secondary surfaces to be back buffers, by default DirectDraw assumes that you'll be using them in an animation loop. Figure 7.10 shows the relationship between the primary surface and secondary surfaces that are back buffers.

Figure 7.10. The primary surface and back buffer(s).


The reason you would create a back buffer is to emulate the functionality of double buffering, but in a more DirectDraw kind of way. If you create a DirectDraw back buffer, usually it will be in VRAM and thus will be very fast. Moreover, you'll be able to page flip it with the primary surface, which is much faster than the memory copy needed for a double buffering scheme.

Technically, you can have as many back buffers as you want in a flipping chain. However, at some point you'll run out of VRAM and the surface will have to be created in system memory, which is much slower. In general, if you create an (m x n) mode with a color depth of one byte, the amount of memory for the primary buffer is of course m*n bytes (unless there's memory pitch alignment). Therefore, if you have one extra back buffer secondary surface, you would multiply this by 2 because back buffers have the same geometry and color depth. So 2*m*n bytes would be the memory required. Finally, if the color depth is 16-bit, you would have to scale all the calculations by two bytes, and similarly for 32-bit buffers you would scale by 4. For example, the primary buffer for a 640x480x16-bit mode would take

Width * Height * Number of bytes per pixel

640 * 480 * 2 = 614,400 bytes

And if you want one extra back buffer, you need to multiply that result by 2 so the final number of bytes is

614,400 * 2 = 1,228,800 bytes

Roughly 1.2MB of VRAM! Hence, if you have only a 1MB card, you can forget having a VRAM back buffer in 640x480x16-bit color mode. Most cards have at least 2MB these days, so you're usually safe, but it's always good to test for the amount of memory available on the card. You can do so with a GetCaps class function. We'll cover that at the end of the chapter. Now, most video cards these days have 8–64 megs of VRAM, but lots of value computers have shared memory and you can easily find yourself out of luck with a 2–4 meg card on a value machine.

To create a primary surface that has a back buffer surface attached to it, you have to create what DirectDraw calls a complex surface. Here are the steps:

  1. First, you have to add DDSD_BACKBUFFERCOUNT to the dwFlags flag field to indicate to DirectDraw that the dwBackBufferCount field of the DDSURFACEDESC2 structure will be valid and contain the number of back buffers (one in this case).

  2. Second, you must add the control flags DDSCAPS_COMPLEX and DDSCAPS_FLIP to the capabilities WORD of the DDSURFACEDESC2 structure contained in the ddsCaps.dwCaps field.

  3. Finally, create the primary surface as usual. From it, request the attached back buffer with a call to IDIRECTDRAWSURFACE7::GetAttachedSurface(), shown below, and you're in business.

HRESULT GetAttachedSurface(  LPDDSCAPS2 lpDDSCaps,
  LPDIRECTDRAWSURFACE7 FAR *lplpDDAttachedSurface  );

lpDDSCaps is a DDSCAPS2 structure containing the requested surface capabilities. In your case, you're requesting a back buffer, so you'll set it like this:


Or just use the DDSCAPS2 field of the DDSURFACEDESC2 structure to save another variable, like this:

ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

Here's the code to create a primary surface and a single back buffer flipping chain:

// assume we already have the directdraw object etc...

DDSURFACEDESC2 ddsd; // directdraw surface description
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // primary surface
LPDIRECTDRAWSURFACE7 lpddsback    = NULL; // back buffer

// clear ddsd and set size

// enable valid fields

// set the backbuffer count field to 1
ddsd.dwBackBufferCount = 1;

// request a complex, flippable
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                      DDSCAPS_COMPLEX | DDSCAPS_FLIP;

// create the primary surface
if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))

// now query for attached surface from the primary surface

// this line is needed by the call
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))


At this point, lpddsprimary points to the primary surface, which is currently visible, and lpddsback points to the back buffer surface, which is not. Take a look at Figure 7.11 to see this graphically. To access the back buffer, you can lock/unlock it just like the primary surface.

Figure 7.11. A true complex surface.


So, if you wanted to manipulate the information in the back buffer, you could do this:

// copy the double buffer into the primary buffer

// lock the back buffer surface

// now ddsd.lpSurface and ddsd.lPitch are valid
// do whatever...

// unlock the back buffer, so hardware can work with it

Now, the only problem is that you don't know how to flip the pages, or, in other words, make the back buffer surface the primary surface and hence animate the two pages. Let me show you how that's done!

      Previous Section Next Section

    JavaScript EditorAjax Editor     JavaScript Editor