Step 4: Creating Flipping Surfaces
After you have set the display mode, you must create the surfaces on which to place your application. Because the DDEX1 example is using the IDirectDraw::SetCooperativeLevel method to set the mode to exclusive (full-screen) mode, you can create surfaces that flip between the surfaces. If you were using IDirectDraw::SetCooperativeLevel to set the mode to DDSCL_NORMAL, you could create only surfaces that blit between the surfaces. Creating flipping surfaces requires the following steps:
·Defining the surface requirements
·Creating the surfaces
Defining the Surface Requirements
The first step in creating flipping surfaces is to define the surface requirements in a DDSURFACEDESC structure. The following example shows the structure definitions and flags needed to create a flipping surface.
// Create the primary surface with one back buffer.
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
In this example, the dwSize member is set to the size of the DDSURFACEDESC structure. This is to prevent any DirectDraw method call you use from returning with an invalid member error. (The dwSize member was provided for future expansion of the DDSURFACEDESC structure.)
The dwFlags member determines which members in the DDSURFACEDESC structure will be filled with valid information. For the DDEX1 example, dwFlags is set to specify that you want to use the DDSCAPS structure (DDSD_CAPS) and that you want to create a back buffer (DDSD_BACKBUFFERCOUNT).
The dwCaps member in the example indicates the flags that will be used in the DDSCAPS structure. In this case, it specifies a primary surface (DDSCAPS_PRIMARYSURFACE), a flipping surface (DDSCAPS_FLIP), and a complex surface (DDSCAPS_COMPLEX).
Finally, the example specifies one back buffer. The back buffer is where the backgrounds and sprites will actually be written. The back buffer is then flipped to the primary surface. In the DDEX1 example, the number of back buffers is set to 1. You can, however, create as many back buffers as the amount of display memory allows. For more information on creating more than one back buffer, see Triple Buffering.
Surface memory can be either display memory or system memory. DirectDraw uses system memory if the application runs out of display memory (for example, if you specify more than one back buffer on a display adapter with only 1 MB of RAM). You can also specify whether to use only system memory or only display memory by setting the dwCaps member in the DDSCAPS structure to DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY. (If you specify DDSCAPS_VIDEOMEMORY, but not enough memory is available to create the surface, IDirectDraw::CreateSurface returns with a DDERR_OUTOFVIDEOMEMORY error.)
Creating the Surfaces
After the DDSURFACEDESC structure is filled, you can use it and lpDD, the pointer to the DirectDraw object that was created by the DirectDrawCreate function, to call the IDirectDraw::CreateSurface method, as shown in the following example:
ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
if(ddrval == DD_OK)
{
// lpDDSPrimary points to the new surface.
}
else
{
// The surface was not created.s
return FALSE;
}
The lpDDSPrimary parameter will point to the primary surface returned by IDirectDraw::CreateSurface if the call succeeds.
After the pointer to the primary surface is available, you can use the IDirectDrawSurface::GetAttachedSurface method to retrieve a pointer to the back buffer, as shown in the following example:
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
ddrval = lpDDSPrimary->GetAttachedSurface(&ddcaps, &lpDDSBack);
if(ddrval == DD_OK)
{
// lpDDSBack points to the back buffer.
}
else
{
return FALSE;
}
By supplying the address of the surface's primary surface and by setting the capabilities value with the DDSCAPS_BACKBUFFER flag, the lpDDSBack parameter will point to the back buffer if the IDirectDrawSurface::GetAttachedSurface call succeeds.