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 中私下配置記憶體) 的指標DD_SURFACE_GLOBAL和DD_SURFACE_LOCAL的成員,因為這些成員會保留供顯示驅動程式私用使用。
若要通知顯示驅動程式要釋放系統記憶體表面,執行時間會將系統記憶體表面DD_SURFACE_GLOBAL結構的 fpVidMem 指標成員設定為零,並呼叫顯示器驅動程式的 D3dCreateSurfaceEx 回呼。 除了釋放與此表面相關聯的所有資源之外,顯示驅動程式還必須清除先前儲存在 dwReserved1 成員中的資料。 請注意,因為視訊記憶體表面的 fpVidMem 指標成員可以設定為零,所以顯示驅動程式必須確認介面是否位於視訊或系統記憶體中,以判斷 對 D3dCreateSurfaceEx 的呼叫是否要通知與 dwSurfaceHandle 的視訊記憶體介面關聯,或通知系統記憶體表面與 dwSurfaceHandle的關聯。
不會呼叫 D3dCreateSurfaceEx 來通知與 dwSurfaceHandle解除視訊記憶體表面的關聯;顯示驅動程式的 DdDestroySurface 回呼必須處理本機和非本機視訊記憶體表面刪除,而且必須清除先前儲存在 dwReserved1 成員中的資料。
驅動程式也應該儲存使用表面時所需的任何表面相關資訊。 驅動程式必須為每個新的 lpDDLcl 建立新的表面資料表,並在必要時隱含放大資料表以容納更多表面。 一般而言,這是使用指數成長演算法來完成,因此您不需要太常放大資料表。 如需實作詳細資料,請參閱 Microsoft Windows 驅動程式開發工具組隨附的 Perm3 範例驅動程式 (DDK) 。 (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) |