PDD_CREATESURFACEEX回调函数 (ddrawint.h)
D3dCreateSurfaceEx 函数通知 Microsoft DirectDraw 图面和 Microsoft Direct3D 句柄值的关联,以便为 Direct3D 呈现设置图面。
语法
PDD_CREATESURFACEEX PddCreatesurfaceex;
DWORD PddCreatesurfaceex(
PDD_CREATESURFACEEXDATA unnamedParam1
)
{...}
参数
unnamedParam1
指向 DD_CREATESURFACEEXDATA 结构,该结构包含驱动程序创建图面所需的信息。
返回值
D3dCreateSurfaceEx 返回以下回调代码之一:
备注
所有 Direct3D 驱动程序都必须支持 D3dCreateSurfaceEx。
D3dCreateSurfaceEx 在 DirectDraw 图面和小整数图面图柄之间创建关联。 通过在句柄和 DirectDraw 图面之间创建这些关联, D3dCreateSurfaceEx 允许 Surface 句柄嵌入到 Direct3D 命令流中。 例如,将 D3DDP2OP_TEXBLT 命令令牌发送到驱动程序的 D3dDrawPrimitives2 函数以加载纹理贴图时,它将使用通过 D3dCreateSurfaceEx 与 DirectDraw 图面关联的源句柄和目标句柄。
对于在本地 DirectDraw 对象下创建的每个 DirectDraw 图面,运行时都会生成一个有效句柄,该句柄唯一标识图面并将该图柄置于DD_SURFACE_MORE结构的 dwSurfaceHandle 成员中。 位于 pcsxd 的 DD_CREATESURFACEEXDATA 结构的 lpDDSLcl 成员指向包含指向此DD_SURFACE_MORE的 lpSurfMore 成员的DD_SURFACE_LOCAL结构。 此句柄值还用于D3DRENDERSTATE_TEXTUREHANDLE呈现状态以启用纹理,并与 D3DDP2OP_SETRENDERTARGET 和 D3DDP2OP_CLEAR 命令一起使用,以设置和清除新的呈现缓冲区和深度缓冲区。 如果驱动程序无法创建 Direct3D 图面,则驱动程序应使调用失败并返回DDHAL_DRIVER_HANDLED。
对于系统内存图面或视频内存图面,当调用 D3dCreateSurfaceEx 来通知 dwSurfaceHandle 与图面 DD_SURFACE_GLOBAL 和 DD_SURFACE_LOCAL 结构的关联时,显示驱动程序可以存储任何数据 (例如,指向 dwReserved1 中专用分配的内存) 的指针1DD_SURFACE_GLOBAL 和 DD_SURFACE_LOCAL 的成员,因为这些成员保留供显示驱动程序专用。
为了通知显示驱动程序要释放系统内存图面,运行时将系统内存图面DD_SURFACE_GLOBAL结构的 fpVidMem 指针成员设置为零,并调用显示驱动程序的 D3dCreateSurfaceEx 回调。 除了释放与此图面关联的所有资源外,显示驱动程序还必须清除以前存储在 dwReserved1 成员中的数据。 请注意,由于视频内存图面的 fpVidMem 指针成员可以设置为零,因此显示驱动程序必须验证图面是否在视频内存中或系统内存中,以确定对 D3dCreateSurfaceEx 的 调用是否旨在通知视频内存图面与 dwSurfaceHandle 的关联,或者通知系统内存图面与 dwSurfaceHandle 的取消关联。
不调用 D3dCreateSurfaceEx 来通知视频内存图面与 dwSurfaceHandle 的取消关联;显示驱动程序的 DdDestroySurface 回调必须处理本地和非本地视频内存表面删除,并且必须清除以前存储在 dwReserved1 成员中的数据。
驱动程序还应存储使用 Surface 时所需的任何与图面相关的信息。 驱动程序必须为每个新的 lpDDLcl 创建新的图面表,并在必要时隐式放大表以容纳更多图面。 通常,这是使用指数增长算法完成的,这样就不必过于频繁地放大表。 有关实现详细信息,请参阅 Microsoft Windows 驱动程序开发工具包 (DDK) 附带的 Perm3 示例驱动程序。 (DDK 位于 Windows 驱动程序工具包 [WDK].)
D3dCreateSurfaceEx 只能使用系统内存图面的已禁用 PDEV 调用。 通过调用显示驱动程序的 DrvAssertMode 函数禁用或启用 PDEV。 有关详细信息 ,请参阅管理 PDEV 。
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);
}
}
要求
目标平台 | 桌面 |
标头 | ddrawint.h (包括 Winddi.h) |