Creating Surfaces

The DirectDrawSurface object represents a surface (pixel memory) that usually resides in the display memory, but the surface can exist in system memory if display memory is exhausted or if it is explicitly requested. If the hardware cannot support the capabilities requested or if it previously allocated those resources to another DirectDrawSurface object, a call to IDirectDraw2::CreateSurface will fail.

The IDirectDraw2::CreateSurface method usually creates one DirectDrawSurface object. If the DDSCAPS_FLIP flag in the dwCaps member of the DDSCAPS structure is set, the IDirectDraw2::CreateSurface method creates several DirectDrawSurface objects, referred to collectively as a complex surface. The additional surfaces created are also referred to as implicit surfaces. Implicit surfaces cannot be detached. For more information, see IDirectDrawSurface2::DeleteAttachedSurface.

DirectDraw does not permit the creation of display memory surfaces wider than the primary surface.

The following are examples of valid surface creation scenarios:

Scenario 1

The primary surface is the surface currently visible to the user. When you create a primary surface, you are actually creating a DirectDrawSurface object to access an already existing surface being used by GDI. Consequently, while all other types of surfaces require values for the dwHeight and dwWidth member of the DDSURFACEDESC structure, a primary surface must not have them specified, even if you know they are the same dimensions as the existing surface.

The members of the DDSURFACEDESC structure (ddsd below) relevant to the creation of the primary surface are then filled.

DDSURFACEDESC ddsd;

ddsd.dwSize = sizeof(ddsd);

// Tell DirectDraw which members are valid.

ddsd.dwFlags = DDSD_CAPS;

// Request a primary surface.

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

Scenario 2

Create a simple off-screen surface of the type that might be used to cache bitmaps that will later be composed with the blitter. A height and width are required for all surfaces except primary surfaces. The members of the DDSURFACEDESC structure (ddsd below) relevant to the creation of a simple off-screen surface are then filled.

DDSURFACEDESC ddsd;

ddsd.dwSize = sizeof(ddsd);

// Tell DirectDraw which members are valid.

ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;

// Request a simple off-screen surface, sized

// 100 by 100 pixels.

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

dwHeight = 100;

dwWidth = 100;

DirectDraw creates this surface in display memory unless it will not fit, in which case the surface is created in system memory. If the surface must be created in one or the other, use the DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY flags in dwCaps member of the DDSCAPS structure to specify system memory or display memory, respectively. An error is returned if the surface cannot be created in the specified location.

DirectDraw also allows for the creation of complex surfaces. A complex surface is a set of surfaces created with a single call to the IDirectDraw2::CreateSurface method. If the DDSCAPS_COMPLEX flag is set in the IDirectDraw2::CreateSurface call, one or more implicit surfaces will be created by DirectDraw in addition to the surface explicitly specified. Complex surfaces are managed as a single surface—a single call to the IDirectDraw::Release method releases all surfaces in the structure, and a single call to the IDirectDrawSurface2::Restore method restores them.

Scenario 3

One of the most useful complex surfaces you can specify is composed of a primary surface and one or more back buffers that form a surface flipping environment. The members of the DDSURFACEDESC structure (ddsd below) relevant to complex surface creation are filled in to describe a flipping surface that has one back buffer.

DDSURFACEDESC ddsd;

ddsd.dwSize = sizeof(ddsd);

// Tell DirectDraw which members are valid.

ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

// Request a primary surface with a single

// back buffer

ddsd.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP |

DDSCAPS_PRIMARYSURFACE;

ddsd.dwBackBufferCount = 1;

The previous statements construct a double-buffered flipping environment—a single call to the IDirectDrawSurface2::Flip method exchanges the surface memory of the primary surface and the back buffer. If you specify 2 for the value of the BackBufferCount member of the DDSURFACEDESC structure, two back buffers are created, and each call to IDirectDrawSurface2::Flip rotates the surfaces in a circular pattern, providing a triple-buffered flipping environment.