PDD_CREATESURFACEEX コールバック関数 (ddrawint.h)
D3dCreateSurfaceEx 関数は、Direct3D レンダリング用にサーフェスを設定できるように、Microsoft DirectDraw サーフェスと Microsoft Direct3D ハンドル値の関連付けに関する通知を行います。
構文
PDD_CREATESURFACEEX PddCreatesurfaceex;
DWORD PddCreatesurfaceex(
PDD_CREATESURFACEEXDATA unnamedParam1
)
{...}
パラメーター
unnamedParam1
ドライバー がサーフェス を作成するために必要な情報を含むDD_CREATESURFACEEXDATA構造体を指します。
戻り値
D3dCreateSurfaceEx は 、次のいずれかのコールバック コードを返します。
解説
すべての Direct3D ドライバーは 、D3dCreateSurfaceEx をサポートする必要があります。
D3dCreateSurfaceEx は、DirectDraw サーフェスと小さな整数サーフェス ハンドルの間に関連付けを作成します。 ハンドルと DirectDraw サーフェスの間にこれらの関連付けを作成することで、 D3dCreateSurfaceEx を使用すると、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 構造体の関連付けについて通知されると、ディスプレイ ドライバーは、DD_SURFACE_GLOBAL の dwReserved1 メンバーに任意のデータ (たとえば、プライベートに割り当てられたメモリへのポインター) を格納でき、これらのメンバーはディスプレイ ドライバーによってプライベートに使用するために予約されているため、DD_SURFACE_LOCAL。
システム メモリ サーフェイスが解放されることをディスプレイ ドライバーに通知するために、ランタイムは、システム メモリ サーフェイスのDD_SURFACE_GLOBAL構造体の fpVidMem ポインター メンバーを 0 に設定し、ディスプレイ ドライバーの D3dCreateSurfaceEx コールバックを呼び出します。 ディスプレイ ドライバーは、この画面に関連付けられているすべてのリソースを解放するだけでなく、 dwReserved1 メンバーに以前に格納されていたデータをクリアする必要があります。 ビデオ メモリサーフェイスの fpVidMem ポインター メンバーを 0 に設定できるため、ディスプレイ ドライバーは、 D3dCreateSurfaceEx の呼び出しが dwSurfaceHandle とのビデオ メモリ サーフェスの関連付けについて通知するか、 dwSurfaceHandle からのシステム メモリ サーフェスの関連付け解除について通知するかを判断するために、画面がビデオ メモリまたはシステム メモリ内にあるかどうかを確認する必要があります。
D3dCreateSurfaceEx は、 dwSurfaceHandle からのビデオ メモリ サーフェスの関連付け解除について通知するために呼び出されません。ディスプレイ ドライバーの DdDestroySurface コールバックは、ローカルおよびローカル以外のビデオ メモリ サーフェスの削除を処理し、 dwReserved1 メンバーに以前に格納されていたデータをクリアする必要があります。
ドライバーには、サーフェスを使用するときに必要なサーフェス関連の情報も格納する必要があります。 ドライバーは、新しい lpDDLcl ごとに新しいサーフェス テーブルを作成し、必要に応じてテーブルを暗黙的に拡大して、より多くのサーフェスに対応する必要があります。 通常、これは指数関数的な増加アルゴリズムを使用して行われるので、テーブルをあまり頻繁に拡大する必要はありません。 実装の詳細については、Microsoft Windows Driver Development Kit (DDK) に含まれていた Perm3 サンプル ドライバーを参照してください。 (DDK は、Windows ドライバー キット [WDK] の前に置かれた。
D3dCreateSurfaceEx は、システム メモリサーフェイスに対して無効な PDEV でのみ呼び出すことができます。 PDEV は、ディスプレイ ドライバーの DrvAssertMode 関数を呼び出すことによって無効または有効になります。 詳細については、「 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);
}
}
要件
対象プラットフォーム | デスクトップ |
Header | ddrawint.h (Winddi.h を含む) |