다음을 통해 공유


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 를 사용하면 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_SETRENDERTARGETD3DDP2OP_CLEAR 명령을 사용하여 새 렌더링 및 깊이 버퍼를 설정하고 지웁니다. 드라이버는 Direct3D 화면을 만들 수 없는 경우 호출에 실패하고 DDHAL_DRIVER_HANDLED 반환해야 합니다.

시스템 메모리 표면 또는 비디오 메모리 표면의 경우 D3dCreateSurfaceEx가 표면의 DD_SURFACE_GLOBALDD_SURFACE_LOCAL 구조와 dwSurfaceHandle의 연결에 대해 알리기 위해 호출되면 디스플레이 드라이버는 이러한 멤버가 디스플레이 드라이버에서 개인적으로 사용하도록 예약되어 있기 때문에 DD_SURFACE_GLOBAL 및 DD_SURFACE_LOCAL dwReserved1 멤버에 모든 데이터(예: 개인적으로 할당된 메모리에 대한 포인터)를 저장할 수 있습니다.

시스템 메모리 표면이 해제될 것임을 디스플레이 드라이버에 알리기 위해 런타임은 시스템 메모리 표면의 DD_SURFACE_GLOBAL 구조체의 fpVidMem 포인터 멤버를 0으로 설정하고 디스플레이 드라이버의 D3dCreateSurfaceEx 콜백을 호출합니다. 디스플레이 드라이버는 이 표면과 연결된 모든 리소스를 해제하는 것 외에도 이전에 dwReserved1 멤버에 저장된 데이터를 지워야 합니다. 비디오 메모리 표면의 fpVidMem 포인터 멤버를 0으로 설정할 수 있으므로 디스플레이 드라이버는 화면이 비디오 또는 시스템 메모리에 있는지 확인하여 D3dCreateSurfaceEx 호출이 dwSurfaceHandle과 비디오 메모리 표면의 연결에 대해 알리거나 dwSurfaceHandle에서 시스템 메모리 표면의 연결 해제에 대해 알리기 위한 것인지 확인해야 합니다.

D3dCreateSurfaceExdwSurfaceHandle에서 비디오 메모리 표면의 연결 해제에 대해 알리기 위해 호출되지 않습니다. 디스플레이 드라이버의 DdDestroySurface 콜백은 로컬 및 비로컬 비디오 메모리 표면 삭제를 처리해야 하며 이전에 dwReserved1 멤버에 저장된 데이터를 지워야 합니다.

또한 드라이버는 표면을 사용할 때 필요한 모든 표면 관련 정보를 저장해야 합니다. 드라이버는 각 새 lpDDLcl 에 대한 새 표면 테이블을 만들고 더 많은 표면을 수용하기 위해 필요한 경우 테이블을 암시적으로 확대해야 합니다. 일반적으로 이 작업은 지수 증가 알고리즘을 사용하여 수행되므로 테이블을 너무 자주 확대할 필요가 없습니다. 구현 세부 정보는 Microsoft DDK(Windows 드라이버 개발 키트)에 포함된 Perm3 샘플 드라이버를 참조하세요. (DDK는 Windows 드라이버 키트 [WDK]보다 앞섰습니다.)

참고 Microsoft WDK(Windows 드라이버 키트)에는 3Dlabs Permedia3(Perm3.htm) 샘플 디스플레이 드라이버가 포함되어 있지 않습니다. WDHC 웹 사이트의 DDK - Windows 드라이버 개발 키트 페이지에서 다운로드할 수 있는 Windows Server 2003 SP1 DDK에서 이 샘플 드라이버를 가져올 수 있습니다.
 
Direct3D는 Direct3D 런타임 또는 애플리케이션의 요청에 의해 DirectDraw에서 표면을 만든 후 D3dCreateSurfaceEx 를 호출합니다.

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);
    }
}

요구 사항

   
대상 플랫폼 데스크톱
머리글 ddrawint.h(Winddi.h 포함)

추가 정보

D3DDP2OP_CLEAR

D3DDP2OP_SETRENDERTARGET

D3DDP2OP_TEXBLT

D3dDestroyDDLocal

D3dDrawPrimitives2

DD_CREATESURFACEEXDATA

DD_SURFACE_GLOBAL

DD_SURFACE_LOCAL

DD_SURFACE_MORE

DdDestroySurface