PDD_CREATESURFACEEX callback function (ddrawint.h)
The D3dCreateSurfaceEx function notifies about the association of a Microsoft DirectDraw surface and a Microsoft Direct3D handle value to enable setting up the surface for Direct3D rendering.
Syntax
PDD_CREATESURFACEEX PddCreatesurfaceex;
DWORD PddCreatesurfaceex(
PDD_CREATESURFACEEXDATA unnamedParam1
)
{...}
Parameters
unnamedParam1
Points to a DD_CREATESURFACEEXDATA structure that contains the information required for the driver to create the surface.
Return value
D3dCreateSurfaceEx returns one of the following callback codes:
Remarks
All Direct3D drivers must support D3dCreateSurfaceEx.
D3dCreateSurfaceEx creates an association between a DirectDraw surface and a small integer surface handle. By creating these associations between a handle and a DirectDraw surface, D3dCreateSurfaceEx allows a surface handle to be embedded in the Direct3D command stream. For example, when the D3DDP2OP_TEXBLT command token is sent to the driver's D3dDrawPrimitives2 function to load a texture map, it uses a source handle and destination handle that were associated with a DirectDraw surface through D3dCreateSurfaceEx.
For every DirectDraw surface created under the local DirectDraw object, the runtime generates a valid handle that uniquely identifies the surface and places the handle in the dwSurfaceHandle member of a DD_SURFACE_MORE structure. The lpDDSLcl member of the DD_CREATESURFACEEXDATA structure at pcsxd points to a DD_SURFACE_LOCAL structure that contains a lpSurfMore member that points to this DD_SURFACE_MORE. This handle value is also used with the D3DRENDERSTATE_TEXTUREHANDLE render state to enable texturing, and with the D3DDP2OP_SETRENDERTARGET and D3DDP2OP_CLEAR commands to set and clear new rendering and depth buffers. The driver should fail the call and return DDHAL_DRIVER_HANDLED if it cannot create the Direct3D surface.
For either a system memory surface or video memory surface, when D3dCreateSurfaceEx is called to notify about the association of dwSurfaceHandle with the surface's DD_SURFACE_GLOBAL and DD_SURFACE_LOCAL structures, the display driver can store any data (for example, a pointer to privately allocated memory) in the dwReserved1 members of DD_SURFACE_GLOBAL and DD_SURFACE_LOCAL because these members are reserved for private use by the display driver.
To notify the display driver that a system memory surface is to be released, the runtime sets the fpVidMem pointer member of the system memory surface's DD_SURFACE_GLOBAL structure to zero and calls the display driver's D3dCreateSurfaceEx callback. In addition to releasing all resources associated with this surface, the display driver must clear out the data that was previously stored in the dwReserved1 members. Note that because the fpVidMem pointer member for a video memory surface can be set to zero, the display driver must verify whether the surface is in video or system memory to determine if the call to D3dCreateSurfaceEx is meant to notify about the association of a video memory surface with dwSurfaceHandle or to notify about the disassociation of a system memory surface from dwSurfaceHandle.
D3dCreateSurfaceEx is not called to notify about the disassociation of a video memory surface from dwSurfaceHandle; the display driver's DdDestroySurface callback must handle local and nonlocal video memory surface deletion and must clear out data that was previously stored in the dwReserved1 members.
The driver should also store any surface-related information that it needs when using the surface. The driver must create a new surface table for each new lpDDLcl and implicitly enlarge the table when necessary to accommodate more surfaces. Typically, this is done with an exponential growth algorithm so that you do not have to enlarge the table too often. See the Perm3 sample driver that was included with the Microsoft Windows Driver Development Kit (DDK) for implementation details. (The DDK preceded the Windows Driver Kit [WDK].)
D3dCreateSurfaceEx can only be called with a disabled PDEV for a system memory surface. A PDEV is disabled or enabled by calling the display driver's DrvAssertMode function. See Managing PDEVs for more information.
Sample implementation of D3dCreateSurfaceEx
LPDDRAWI_DDRAWSURFACE_LCL GetAttachedSurface(
LPDDRAWI_DDRAWSURFACE_LCL pLcl,
DDSCAPS2 * pddsCaps2)
{
LPATTACHLIST pAl;
pAl = pLcl->lpAttachList;
while (pAl) {
LPDDRAWI_DDRAWSURFACE_LCL pLclAttached = pAl->lpAttached;
LPATTACHLIST pAlAttached = pLclAttached->lpAttachList;
if ((pLclAttached->lpSurfMore->ddsCapsEx.dwCaps2 & pddsCaps2->dwCaps2) ||
(pLclAttached->lpSurfMore->ddsCapsEx.dwCaps3 & pddsCaps2->dwCaps3) ||
(pLclAttached->lpSurfMore->ddsCapsEx.dwCaps4 & pddsCaps2->dwCaps4) ||
(pLclAttached->ddsCaps.dwCaps & pddsCaps2->dwCaps)
)
{
return pLclAttached;
}
pAl = pAl->lpLink;
}
return NULL;
}
void CSExProcessPossibleMipmap(LPDDRAWI_DDRAWSURFACE_LCL pLcl)
{
//
// A more likely scenario would be to build a list of surfaces
// so that the driver can create one structure that represents the
// entire mipmap, rather than creating an object to represent each
// level as depicted here.
//
DDSCAPS2 ddsCaps2 = {0,DDSCAPS2_MIPMAPSUBLEVEL,0,0};
while (pLcl) {
//Call the private driver routine that creates a driver-side surface structure
CreateMyRepresentation(pLcl);
pLcl = GetAttachedSurface(pLcl,&ddsCaps2);
}
}
//
// The actual return type should reflect the fact that the only
// way this routine should fail is with DDERR_OUTOFMEMORY
//
void MyCreateSurfaceExHelper(LPDDRAWI_DDRAWSURFACE_LCL pLcl)
{
LPATTACHLIST pAl;
DDSCAPS2 ddsCaps2 = {0,0,0,0};
LPDDRAWI_DDRAWSURFACE_LCL pLclAttached;
LPDDRAWI_DDRAWSURFACE_LCL pLclStart;
if (pLcl->lpGbl->fpVidMem == 0) {
//A required check against bad surfaces
if (pLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
return;
//Else, this is a system memory surface, so we are being informed of
// its destruction
DestroyMyRepresentation(pLcl->lpSurfMore->dwSurfaceHandle);
return;
}
CSExProcessPossibleMipmap(pLcl);
if (pLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP) {
int i;
//
// The root surface is always positive X, so we check for the
// other five face types.
//
DWORD dw[5] = {
DDSCAPS2_CUBEMAP_NEGATIVEX,
DDSCAPS2_CUBEMAP_POSITIVEY,
DDSCAPS2_CUBEMAP_NEGATIVEY,
DDSCAPS2_CUBEMAP_POSITIVEZ,
DDSCAPS2_CUBEMAP_NEGATIVEZ};
for(i=0;i< sizeof(dw)/sizeof(dw[0]);i++) {
ddsCaps2.dwCaps2 = dw[i];
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
if (pLclAttached)
CSExProcessPossibleMipmap(pLclAttached);
}
//
// Once we know it's a cube map, we know there cannot be any other
// attachments.
//
return;
}
//
// At this point:
// If it's a cubemap, we returned above.
// If it's a mipmap, we handled all cases above.
// The only other complex surface possibility is a primary flipping chain.
// Because a primary flipping chain cannot be mipmapped, we will simply return
// here if this surface is a mipmap.
//
if (pLcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
return;
//
// The only system memory surfaces we'll ever be interested in are textures (mipmaps)
// and cube maps. We do not propagate an error code for system memory
// surfaces whose format we do not understand. This could cause an error code to
// be propagated to the application when it was trying to use system memory surfaces
// of a format we do not understand, but is valid for the reference rasterizer, for example.
//
if (pLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
return;
//
// Now walk around a flipping chain. A flipping chain is a ring of
// surfaces attached to each other (each surface is attached to the next
// and to the previous surface in the ring, but not to any other surface
// in the ring).
// We need to watch out for this circular ring and make sure we exit appropriately.
// There is also the possibility of a z buffer attached to one of the surfaces
// in the ring, which may or may not have been CreateSurfaceEx'ed already.
//
pLclStart = pLcl;
while (pLcl && pLcl != pLclStart) {
//Check for Z buffer attached to this surface in the ring.
ddsCaps2.dwCaps = DDSCAPS_ZBUFFER;
ddsCaps2.dwCaps2 = 0;
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
if (pLclAttached)
CreateMyRepresentation(pLclAttached);
//Check for stereo left surface attached to this surface in the ring
ddsCaps2.dwCaps = 0;
ddsCaps2.dwCaps2 = DDSCAPS2_STEREOSURFACELEFT;
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
if (pLclAttached)
CreateMyRepresentation(pLclAttached);
// Move to next surface in the primary flipping ring. The next surface is
// definitely in video memory (all surfaces in an attachment structure have
// to be in the same memory type, and we excluded system memory above).
// The next surface in the ring is thus the attached video memory surface
// that is NOT a z buffer NOR a stereo left surface.
ddsCaps2.dwCaps = DDSCAPS_VIDEOMEMORY;
ddsCaps2.dwCaps2 = 0;
do {
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
}
while (
pLclAttached->ddsCaps.dwCaps & DDSCAPS_ZBUFFER ||
pLclAttached->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT
);
pLcl = pLclAttached;
if (pLcl != pLclStart)
CreateMyRepresentation(pLcl);
}
}
Requirements
Requirement | Value |
---|---|
Target Platform | Desktop |
Header | ddrawint.h (include Winddi.h) |