Platform SDK: DirectX

Creating Client Memory Surfaces

Client memory surfaces are simply DirectDrawSurface objects that use system memory that your application has previously allocated to hold image data. Creating such a surface isn't common, but it isn't difficult to do and it can be useful for applications that need to use DirectDraw surface features on existing memory buffers.

[C++]

When creating surfaces, DirectDraw needs information about the dimensions of the surface (measured in pixels) and the surface pitch (measured in bytes), as well as the surface's pixel format. However, unlike creating other types of surfaces, this information for client memory surfaces doesn't tell DirectDraw how you want the surface to be created, it tells DirectDraw how you've already created it. You set these characteristics, plus the memory address of the buffer you've allocated, in the DDSURFACEDESC2 structure you pass to the IDirectDraw7::CreateSurface method.

A client memory surfaces works just like a normal system-memory surface, with the exception that DirectDraw does not attempt to free the surface memory when it's no longer needed; freeing client allocated memory is the application's responsibility.

The following example shows how you might allocate memory and create a DirectDrawSurface object for a 64×64 pixel 24-bit RGB surface.

// For this example, g_lpDD is a valid IDirectDraw7 interface pointer.
 
#define WIDTH  64 // in pixels
#define HEIGHT 64
#define DEPTH  3  // in bytes (3bytes == 24 bits)
 
    HRESULT hr;
    LPVOID  lpSurface  = NULL;
    HLOCAL  hMemHandle = NULL;
    DDSURFACEDESC2 ddsd2;
    LPDIRECTDRAWSURFACE7 lpDDS;
 
    // Allocate memory for a 64 by 64, 24-bit per pixel buffer.
    // REMEMBER: The application is responsible for freeing this
    //           buffer when it is no longer needed.
    if (lpSurface = malloc((size_t)WIDTH*HEIGHT*DEPTH))
        ZeroMemory(lpSurface, (DWORD)WIDTH*HEIGHT*DEPTH);
    else
        return DDERR_OUTOFMEMORY;
 
    // Initialize the surface description.
    ZeroMemory(&ddsd2, sizeof(DDSURFACEDESC2));
    ZeroMemory(&ddsd2.ddpfPixelFormat, sizeof(DDPIXELFORMAT));
    ddsd2.dwSize = sizeof(ddsd2);
    ddsd2.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_LPSURFACE |
                    DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_CAPS;
    ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
                           DDSCAPS_SYSTEMMEMORY;
    ddsd2.dwWidth = WIDTH;
    ddsd2.dwHeight= HEIGHT;
    ddsd2.lPitch  = (LONG)DEPTH * WIDTH;
    ddsd2.lpSurface = lpSurface;
 
    // Set up the pixel format for 24-bit RGB (8-8-8).
    ddsd2.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
    ddsd2.ddpfPixelFormat.dwFlags= DDPF_RGB;
    ddsd2.ddpfPixelFormat.dwRGBBitCount = (DWORD)DEPTH*8;
    ddsd2.ddpfPixelFormat.dwRBitMask    = 0x00FF0000;
    ddsd2.ddpfPixelFormat.dwGBitMask    = 0x0000FF00;
    ddsd2.ddpfPixelFormat.dwBBitMask    = 0x000000FF;
 
    // Create the surface
    hr = g_lpDD->CreateSurface(&ddsd2, &lpDDS, NULL);
    return hr;
[Visual Basic]

When creating surfaces, DirectDraw needs information about the dimensions of the surface (measured in pixels) and the surface pitch (measured in bytes), as well as the surface's pixel format. However, unlike creating other types of surfaces, this information for client memory surfaces doesn't tell DirectDraw how you want the surface to be created, it tells DirectDraw how you've already created it. You set these characteristics, plus the memory address of the buffer you've allocated, in the DDSURFACEDESC2 type you pass to the DirectDraw7.CreateSurface method.

A client memory surfaces works just like a normal system-memory surface, with the exception that DirectDraw does not attempt to free the surface memory when it's no longer needed; freeing client allocated memory is the application's responsibility.

The following example shows how you might allocate memory and create a DirectDrawSurface object for a 64×64 pixel 24-bit RGB surface.

'For this example, dd is a valid DirectDraw7 object.

Const cWIDTH = 64 'in pixels
Const cHEIGHT = 64
Const cDEPTH = 3 'in bytes (3 bytes = 24 bits)

Dim ddsd2 As DDSURFACEDESC2
Dim dds As DirectDrawSurface7
Private Sub Form_Load()
    
'Initialize the surface description.
With ddsd2
    .lFlags = DDSD_WIDTH Or DDSD_HEIGHT Or DDSD_PITCH Or DDSD_PIXELFORMAT Or DDSD_CAPS
    .ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or DDSCAPS_SYSTEMMEMORY
    .lWidth = cWIDTH
    .lHeight = cHEIGHT
    .lPitch = cDEPTH * cWIDTH
    'Set up the pixel format for 24-bit RGB (8-8-8).
    With .ddpfPixelFormat
        .lFlags = DDPF_RGB
        .lRGBBitCount = cDEPTH * 8
        .lRBitMask = &HFF0000
        .lGBitMask = &HFF00&
        .lBBitMask = &HFF&
    End With
End With

'Create the surface.
Set dds = dd.CreateSurface(ddsd2)

End Sub