Enumerating Surfaces

By calling the IDirectDraw4::EnumSurfaces method you can request that DirectDraw enumerate surfaces in various ways. The EnumSurfaces method enables you to look for surfaces that fit, or don't fit, a provided surface description. DirectDraw calls a EnumSurfacesCallback that you include with the call for each enumerated surface.

There are two general ways to search—you can search for surfaces that the DirectDraw object has already created, or for surfaces that the DirectDraw object is capable of creating at the time (given the surface description and available memory). You specify what type of search you want by combining flags in the method's dwFlags parameter.

Enumerating existing surfaces

This is the most common type of enumeration. You enumerate existing surfaces by calling EnumSurfaces, specifying a combination of the DDENUMSURFACES_DOESEXIST search-type flag and one of the matching flags (DDENUMSURFACES_MATCH, DDENUMSURFACES_NOMATCH, or DDENUMSURFACES_ALL) in the dwFlags parameter. If you're enumerating all existing surfaces, you can set the lpDDSD parameter to NULL, otherwise set it to the address of an initialized DDSURFACEDESC2 structure that describes the surface for which you're looking. You can set the third parameter, lpContext, to an address that will be passed to the enumeration function you specify in the fourth parameter, lpEnumSurfacesCallback.

The following code fragment shows what this call might look like to enumerate all of a DirectDraw object's existing surfaces.

    HRESULT ddrval;
    ddrval = lpDD->EnumSurfaces(DDENUMSURFACES_DOESEXIST |
                                DDENUMSURFACES_ALL, NULL, NULL,
                                EnumCallback);
    if (FAILED(ddrval))
        return FALSE;
 

When searching for existing surfaces that fit a specific description, DirectDraw determines a match by comparing each member of the provided surface description to those of the existing surfaces. Only exact matches are enumerated. DirectDraw increments the reference counts of the enumerated surfaces, so make sure to release a surface if you don't plan to use it (or when you're done with it).

Enumerating possible surfaces

This type of enumeration is less common than enumerating existing surfaces, but it can be helpful to determine if a surface is supported before you attempt to create it. To perform this search, combine the DDENUMSURFACES_CANBECREATED and DDENUMSURFACES_MATCH flags when you call IDirectDraw4::EnumSurfaces (no other flag combinations are valid). The DDSURFACEDESC2 structure you use with the call must be initialized to contain information about the surface characteristics that DirectDraw will use.

To enumerate surfaces that use a particular pixel format, include the DDSD_PIXELFORMAT flag in the dwFlags member of the DDSURFACEDESC2 structure. Additionally, initialize the DDPIXELFORMAT structure in the surface description and set its dwFlags member to contain the desired pixel format flags—DDPF_RGB, DDPF_YUV, or both. You need not set any other pixel format values.

If you include the DDSD_HEIGHT and DDSD_WIDTH flags in the DDSURFACEDESC2 structure, you can specify the desired dimensions in the dwHeight and dwWidth members. If you exclude these flags, DirectDraw uses the dimensions of the primary surface.

The following code fragment shows what this call could look like to enumerate all valid surface characteristics for 96×96 RGB or YUV surfaces:

    DDSURFACEDESC2 ddsd;
    HRESULT        ddrval;
    ZeroMemory(&ddsd, sizeof(ddsd));
 
    ddsd.dwSize  = sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | 
                   DDSD_HEIGHT | DDSD_WIDTH;
    ddsd.ddpfPixelFormat.dwFlags = DDPF_YUV | DDPF_RGB;
    ddsd.dwHeight = 96;
    ddsd.dwWidth  = 96;
 
    ddrval = lpDD->EnumSurfaces(
                     DDENUMSURFACES_CANBECREATED | DDENUMSURFACES_MATCH,
                     &ddsd, NULL, EnumCallback);
    if (ddrval != DD_OK)
        return FALSE;
 

When DirectDraw enumerates possible surfaces, it actually attempts to create a temporary surface that has the desired characteristics. If the attempt succeeds, then DirectDraw calls the provided EnumSurfacesCallback function with only the characteristics that worked; it does not provide the callback function with pointer to the temporary surface. Do not assume that a surface isn't supported if it isn't enumerated. DirectDraw's attempt to create a temporary surface could fail due to memory constraints that exist at the time of the call, resulting in those characteristics not being enumerated, even if the driver actually supports them.