You can update the characteristics of an existing surface by using the IDirectDrawSurface4::SetSurfaceDesc method. With this method, you can change the pixel format and location of a DirectDrawSurface object's surface memory to system memory that your application has explicitly allocated. This is useful as it allows a surface to use data from a previously allocated buffer without copying. The new surface memory is allocated by the client application and, as such, the client application must also deallocate it.
When calling the IDirectDrawSurface4::SetSurfaceDesc method, the lpddsd parameter must be the address of a DDSURFACEDESC2 structure that describes the new surface memory as well as a pointer to that memory. Within the structure, you can only set the dwFlags member to reflect valid members for the location of the surface memory, dimensions, pitch, and pixel format. Therefore, dwFlags can only contain combinations of the DDSD_WIDTH, DDSD_HEIGHT, DDSD_PITCH, DDSD_LPSURFACE, and DDSD_PIXELFORMAT flags, which you set to indicate valid structure members.
Before you set the values in the structure, you must allocate memory to hold the surface. The size of the memory you allocate is important. Not only do you need to allocate enough memory to accommodate the surface's width and height, but you need to have enough to make room for the surface pitch, which must be a QWORD (8 byte) multiple. Remember, pitch is measured in bytes, not pixels.
When setting surface values in the structure, the lpSurface member is a pointer to the memory you allocated and the dwHeight and dwWidth members describe the surface dimensions in pixels. If you specify surface dimensions, you must fill the lPitch member to reflect the surface pitch as well. Pitch must be a DWORD multiple. Likewise, if you specify pitch, you must also specify a width value. Lastly, the ddpfPixelFormat member describes the pixel format for the surface. With the exception of the lpSurface member, if you don't specify a value for these members, the method defaults to using the value from the current surface.
There are some restrictions you must be aware of when using IDirectDrawSurface4::SetSurfaceDesc, some of which are common sense. For example, the lpSurface member of the DDSURFACEDESC2 structure must be a valid pointer to a system memory (the method doesn't support video memory pointers at this time). Also, the dwWidth and dwHeight members must be nonzero values. Lastly, you cannot reassign the primary surface or any surfaces within the primary's flipping chain.
You can set the same memory for multiple DirectDrawSurface objects, but you must take care that the memory is not deallocated while it is assigned to any surface object.
Using the SetSurfaceDesc method incorrectly will cause unpredictable behavior. The DirectDrawSurface object will not deallocate surface memory that it didn't allocate. Therefore, when the surface memory is no longer needed, it is your responsibility to deallocate it. However, when SetSurfaceDesc is called, DirectDraw frees the original surface memory that it implicitly allocated when creating the surface.