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

### 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×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 640×480×16-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 640×480×16-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.

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 `IDIRECTDRAWSURFACE4::GetAttachedSurface()`, shown below, and you’re in business.

         HRESULT GetAttachedSurface(  LPDDSCAPS2 lpDDSCaps,

           LPDIRECTDRAWSURFACE4 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:

    DDSCAPS2 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

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

    LPDIRECTDRAWSURFACE4 lpddsprimary = NULL; // primary surface

    LPDIRECTDRAWSURFACE4 lpddsback    = NULL; // back buffer

    // clear ddsd and set size

    DDRAW_INIT_STRUCT(ddsd);

    // enable valid fields

    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

    // 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(lpdd4->CreateSurface(&ddsd, &lpddsprimary, NULL)))

       return(0);

    // 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

    DDRAW_INIT_STRUCT(ddsd);

    // lock the back buffer surface

    lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);

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

    // do whatever...

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

    lpddsback->Unlock(NULL);

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 | 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.