Share via


D3dCreateSurfaceEx

This function creates a Direct3D surface from a DirectDraw surface and associates a requested handle value to it.

DWORD (APIENTRY *PDD_CREATESURFACEEX)(
  PDD_CREATESURFACEEXDATA pcsxd
);

Parameters

  • pcsxd
    [in] Points to a DD_CREATESURFACEEXDATA structure that contains the information required for the driver to create the surface. This information is described in the Return Values section.

Return Values

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 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 run time generates a valid handle that uniquely identifies the surface, and then places it in pcsxd->lpDDSLcl->lpSurfMore->dwSurfaceHandle. dwSurfaceHandle is a member of the DDRAWI_DDRAWSURFACE_MORE structure. 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.

Upon the destruction of a surface with a dwSurfaceHandle, the driver will be notified by a D3dCreateSurfaceEx callback. The fpVidMem pointer, which is a member of the DDRAWI_DDRAWSURFACE_GBL structure, for the surface is cleared to zero. The driver should then invalidate and free any driver-private data associated to this surface.

The driver should also store any surface-related information that it will need when using the surface. The driver must create a new surface table for each new lpDDLcl and 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. For more information about implementation, see the Permedia3 sample driver in %_WINCEROOT%\Public\Common\OAK\Drivers\Display\Perm3.

Direct3D calls D3dCreateSurfaceEx after DirectDraw creates the surface by request of the Direct3D run time or the application.

The following code sample shows a typical 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
// time 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;

        //Otherwise, this is a system memory surface, so this is a notice 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 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 it is a cube map, there cannot be any other 
        // attachments.
        //
        return; 
    }

    //
    // At this point:
    //      If it is a cubemap, the above is returned.
    //      If it is a mipmap, all cases above were handled.
    // The only other complex surface possibility is a primary flipping chain.
    // Since a primary flipping chain cannot be mipmapped, simply return
    // here if this surface is a mipmap.
    //

    if (pLcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
        return;

    //
    // The only important system memory surfaces are textures (mipmaps)
    // and cube maps. Any other kind of system memory surface is not interesting 
    // , and a return occurs. Do not propagate an error code for system memory surfaces with unknown formats.
    // This could cause an error code to 
    // be propagated to the application when it was trying to use system memory surfaces
    // on an unknown format. It could be 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
    // surface 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.
    // Watch for this circular ring and be sure it exits 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 system memory was excluded above.
        // The next surface in the ring is the attached video memory surface
        // that is not a z buffer or 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

OS Versions: Windows CE .NET 4.0 and later.
Header: Proto.h.
Link Library: Developer implemented.

See Also

DDHAL_DRIVER_HANDLED | DDHAL_DRIVER_NOTHANDLED | D3DDP2OP_TEXBLT | D3dDrawPrimitives2 | DDRAWI_DDRAWSURFACE_MORE | D3DDP2OP_SETRENDERTARGET | D3DDP2OP_CLEAR | DDRAWI_DDRAWSURFACE_GBL | Direct3D Driver Functions

 Last updated on Tuesday, May 18, 2004

© 1992-2003 Microsoft Corporation. All rights reserved.