From 37eaa4b5db8f42462d32820ddcbf50f97ace8eb7 Mon Sep 17 00:00:00 2001 From: Gregor Brunmar Date: Sun, 2 Mar 2008 12:29:35 +0000 Subject: [PATCH] Implemented IDirect3D:CheckDeviceFormat() svn path=/trunk/; revision=32541 --- reactos/dll/directx/d3d9/d3d9_impl.c | 189 ++++++++++++++++++- reactos/dll/directx/d3d9/d3d9_private.h | 8 +- reactos/dll/directx/d3d9/format.c | 234 +++++++++++++++++++++++- reactos/dll/directx/d3d9/format.h | 15 +- reactos/include/psdk/d3d9types.h | 3 + 5 files changed, 439 insertions(+), 10 deletions(-) diff --git a/reactos/dll/directx/d3d9/d3d9_impl.c b/reactos/dll/directx/d3d9/d3d9_impl.c index 1497995a6d7..338b506ace4 100644 --- a/reactos/dll/directx/d3d9/d3d9_impl.c +++ b/reactos/dll/directx/d3d9/d3d9_impl.c @@ -363,7 +363,7 @@ static HRESULT WINAPI IDirect3D9Impl_GetAdapterDisplayMode(LPDIRECT3D9 iface, UI * One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be checked. * * @param D3DFORMAT BackBufferFormat -* One of the D3DFORMAT enum membersfor the render target mode to be checked. D3DFMT_UNKNOWN is only allowed in windowed mode. +* One of the D3DFORMAT enum members for the render target mode to be checked. D3DFMT_UNKNOWN is only allowed in windowed mode. * * @param BOOL Windowed * If this value is TRUE, the D3DFORMAT check will be done for windowed mode and FALSE equals fullscreen mode. @@ -426,19 +426,200 @@ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceType(LPDIRECT3D9 iface, UINT Ada return D3DERR_NOTAVAILABLE; } - hResult = CheckDeviceFormat(&This->DisplayAdapters[Adapter].DriverCaps, DisplayFormat, BackBufferFormat, Windowed); + hResult = CheckDeviceType(&This->DisplayAdapters[Adapter].DriverCaps, DisplayFormat, BackBufferFormat, Windowed); UNLOCK_D3D9(); return hResult; } + +/*++ +* @name IDirect3D9::CheckDeviceFormat +* @implemented +* +* The function IDirect3D9Impl_CheckDeviceFormat checks if a specific D3DFORMAT +* can be used for a specific purpose like texture, depth/stencil buffer or as a render target +* on the specified display adapter. +* +* @param LPDIRECT3D iface +* Pointer to the IDirect3D object returned from Direct3DCreate9() +* +* @param UINT Adapter +* Adapter index to get information about. D3DADAPTER_DEFAULT is the primary display. +* The maximum value for this is the value returned by IDirect3D::GetAdapterCount(). +* +* @param D3DDEVTYPE DeviceType +* One of the D3DDEVTYPE enum members. +* +* @param D3DFORMAT AdapterFormat +* One of the D3DFORMAT enum members except D3DFMT_UNKNOWN for the display adapter mode to be checked. +* +* @param DWORD Usage +* Valid values are any of the D3DUSAGE_QUERY constants or any of these D3DUSAGE constants: +* D3DUSAGE_AUTOGENMIPMAP, D3DUSAGE_DEPTHSTENCIL, D3DUSAGE_DMAP, D3DUSAGE_DYNAMIC, +* D3DUSAGE_NONSECURE, D3DUSAGE_RENDERTARGET and D3DUSAGE_SOFTWAREPROCESSING. +* +* @param D3DRESOURCETYPE RType +* One of the D3DRESOURCETYPE enum members. Specifies what format will be used for. +* +* @param D3DFORMAT CheckFormat +* One of the D3DFORMAT enum members for the surface format to be checked. +* +* @return HRESULT +* If the format is compatible with the specified usage and resource type, the method returns D3D_OK. +* If the format isn't compatible with the specified usage and resource type - the return value will be D3DERR_NOTAVAILABLE. +* If Adapter is out of range, DeviceType is invalid, AdapterFormat or CheckFormat is invalid, +* Usage and RType isn't compatible - the return value will be D3DERR_INVALIDCALL. +* +*/ static HRESULT WINAPI IDirect3D9Impl_CheckDeviceFormat(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) { - UNIMPLEMENTED + LPD3D9_DRIVERCAPS pDriverCaps; + BOOL bIsTextureRType = FALSE; + HRESULT hResult; - return D3D_OK; + LPDIRECT3D9_INT This = impl_from_IDirect3D9(iface); + LOCK_D3D9(); + + if (Adapter >= This->NumDisplayAdapters) + { + DPRINT1("Invalid Adapter number specified"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + if (DeviceType != D3DDEVTYPE_HAL && + DeviceType != D3DDEVTYPE_REF && + DeviceType != D3DDEVTYPE_SW) + { + DPRINT1("Invalid DeviceType specified"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + if (AdapterFormat == D3DFMT_UNKNOWN || + CheckFormat == D3DFMT_UNKNOWN) + { + DPRINT1("Invalid D3DFORMAT specified"); + UNLOCK_D3D9(); + return D3DERR_NOTAVAILABLE; + } + + if ((Usage & (D3DUSAGE_DONOTCLIP | D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_TEXTAPI | D3DUSAGE_WRITEONLY)) != 0) + { + DPRINT1("Invalid Usage specified"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + if (RType == D3DRTYPE_TEXTURE || + RType == D3DRTYPE_VOLUMETEXTURE || + RType == D3DRTYPE_CUBETEXTURE) + { + bIsTextureRType = TRUE; + } + else if (RType == D3DRTYPE_SURFACE && + (Usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) == 0 && + Usage != 0) + { + DPRINT1("When RType is set to D3DRTYPE_SURFACE, Usage must be 0 or have set D3DUSAGE_DEPTHSTENCIL or D3DUSAGE_RENDERTARGET"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + if ((Usage & D3DUSAGE_DEPTHSTENCIL) != 0) + { + if (FALSE == IsZBufferFormat(CheckFormat)) + { + DPRINT1("Invalid CheckFormat Z-Buffer format"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + if ((Usage & D3DUSAGE_AUTOGENMIPMAP) != 0) + { + DPRINT1("Invalid Usage specified, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_AUTOGENMIPMAP can't be combined."); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + } + + if (FALSE == bIsTextureRType && + RType != D3DRTYPE_SURFACE && + RType != D3DRTYPE_VOLUME) + { + DPRINT1("Invalid RType specified"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + if ((Usage & (D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) != 0) + { + if (RType == D3DRTYPE_VOLUME || RType == D3DRTYPE_VOLUMETEXTURE) + { + DPRINT1("Invalid Usage specified, D3DUSAGE_AUTOGENMIPMAP, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_RENDERTARGET can't be combined with RType D3DRTYPE_VOLUME or D3DRTYPE_VOLUMETEXTURE"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + } + + if (FALSE == bIsTextureRType && + (Usage & D3DUSAGE_QUERY_VERTEXTEXTURE) != 0) + { + DPRINT1("Invalid Usage specified, D3DUSAGE_QUERY_VERTEXTEXTURE can only be used with a texture RType"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + if ((Usage & D3DUSAGE_AUTOGENMIPMAP) != 0 && + TRUE == IsMultiElementFormat(CheckFormat)) + { + DPRINT1("Invalid Usage specified, D3DUSAGE_AUTOGENMIPMAP can't be used with a multi-element format"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + + pDriverCaps = &This->DisplayAdapters[Adapter].DriverCaps; + if ((Usage & D3DUSAGE_DYNAMIC) != 0 && bIsTextureRType == TRUE) + { + if ((pDriverCaps->DriverCaps9.Caps2 & D3DCAPS2_DYNAMICTEXTURES) == 0) + { + DPRINT1("Driver doesn't support dynamic textures"); + UNLOCK_D3D9(); + return D3DERR_NOTAVAILABLE; + } + + if ((Usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)) != 0) + { + DPRINT1("Invalid Usage specified, D3DUSAGE_DEPTHSTENCIL and D3DUSAGE_RENDERTARGET can't be combined with D3DUSAGE_DYNAMIC and a texture RType"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + } + + if ((Usage & D3DUSAGE_DMAP) != 0) + { + if ((pDriverCaps->DriverCaps9.DevCaps2 & (D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH | D3DDEVCAPS2_DMAPNPATCH)) == 0) + { + DPRINT1("Driver doesn't support displacement mapping"); + UNLOCK_D3D9(); + return D3DERR_NOTAVAILABLE; + } + + if (RType != D3DRTYPE_TEXTURE) + { + DPRINT1("Invalid Usage speficied, D3DUSAGE_DMAP must be combined with RType D3DRTYPE_TEXTURE"); + UNLOCK_D3D9(); + return D3DERR_INVALIDCALL; + } + } + + hResult = CheckDeviceFormat(pDriverCaps, AdapterFormat, Usage, RType, CheckFormat); + + UNLOCK_D3D9(); + return hResult; } static HRESULT WINAPI IDirect3D9Impl_CheckDeviceMultiSampleType(LPDIRECT3D9 iface, UINT Adapter, D3DDEVTYPE DeviceType, diff --git a/reactos/dll/directx/d3d9/d3d9_private.h b/reactos/dll/directx/d3d9/d3d9_private.h index e2f2d843034..60b914ac29b 100644 --- a/reactos/dll/directx/d3d9/d3d9_private.h +++ b/reactos/dll/directx/d3d9/d3d9_private.h @@ -222,8 +222,8 @@ typedef struct _tagDIRECT3D9_INT_ /* 0x227c */ DWORD unknown002207; /* 0x2280 */ DWORD unknown002208; /* 0x2284 */ DWORD unknown002209; -/* 0x2288 */ DWORD unknown002210; -/* 0x228c */ DWORD unknown002211; +/* 0x2288 */ DWORD NumSupportedRefFormatOps; +/* 0x228c */ LPDDSURFACEDESC pSupportedRefFormatOps; /* 0x2290 */ DWORD unknown002212; /* 0x2294 */ DWORD unknown002213; /* 0x2298 */ DWORD unknown002214; @@ -1286,8 +1286,8 @@ typedef struct _tagDIRECT3D9_INT_ /* 0x331c */ DWORD unknown003271; /* 0x3320 */ DWORD unknown003272; /* 0x3324 */ DWORD unknown003273; -/* 0x3328 */ DWORD unknown003274; -/* 0x332c */ DWORD unknown003275; +/* 0x3328 */ DWORD NumSupportedSoftwareFormatOps; +/* 0x332c */ LPDDSURFACEDESC pSupportedSoftwareFormatOps; /* 0x3330 */ DWORD unknown003276; /* 0x3334 */ DWORD unknown003277; /* 0x3338 */ DWORD unknown003278; diff --git a/reactos/dll/directx/d3d9/format.c b/reactos/dll/directx/d3d9/format.c index 2b6890a51f3..cd943971899 100644 --- a/reactos/dll/directx/d3d9/format.c +++ b/reactos/dll/directx/d3d9/format.c @@ -8,6 +8,7 @@ #include "format.h" #include +#include BOOL IsBackBufferFormat(D3DFORMAT Format) { @@ -20,6 +21,18 @@ BOOL IsExtendedFormat(D3DFORMAT Format) return (Format == D3DFMT_A2R10G10B10); } +BOOL IsZBufferFormat(D3DFORMAT Format) +{ + UNIMPLEMENTED + + return TRUE; +} + +BOOL IsMultiElementFormat(D3DFORMAT Format) +{ + return (Format == D3DFMT_MULTI2_ARGB8); +} + BOOL IsSupportedFormatOp(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat, DWORD FormatOp) { const DWORD NumFormatOps = pDriverCaps->NumSupportedFormatOps; @@ -38,7 +51,7 @@ BOOL IsSupportedFormatOp(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat, return FALSE; } -HRESULT CheckDeviceFormat(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) +HRESULT CheckDeviceType(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed) { if (FALSE == IsSupportedFormatOp(pDriverCaps, DisplayFormat, D3DFORMAT_OP_DISPLAYMODE | D3DFORMAT_OP_3DACCELERATION)) { @@ -89,3 +102,222 @@ HRESULT CheckDeviceFormat(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat return D3D_OK; } + +static D3DFORMAT GetStencilFormat(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT CheckFormat) +{ + switch (CheckFormat) + { + case D3DFMT_D15S1: + case D3DFMT_D24S8: + case D3DFMT_D24X8: + case D3DFMT_D24X4S4: + if (IsSupportedFormatOp(pDriverCaps, CheckFormat - 1, 0)) + return CheckFormat - 1; + break; + + case D3DFMT_D16: + if (IsSupportedFormatOp(pDriverCaps, CheckFormat, 0)) + return CheckFormat; + else + return D3DFMT_D16_LOCKABLE; + + default: + /* StencilFormat same as CheckFormat */ + break; + } + + return CheckFormat; +} + +static D3DFORMAT RemoveAlphaChannel(D3DFORMAT CheckFormat) +{ + switch (CheckFormat) + { + case D3DFMT_A8R8G8B8: + return D3DFMT_X8R8G8B8; + + case D3DFMT_A1R5G5B5: + return D3DFMT_X1R5G5B5; + + case D3DFMT_A4R4G4B4: + return D3DFMT_X4R4G4B4; + + case D3DFMT_A8B8G8R8: + return D3DFMT_X8B8G8R8; + + default: + /* CheckFormat has not relevant alpha channel */ + break; + } + + return CheckFormat; +} + +HRESULT CheckDeviceFormat(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) +{ + const DWORD NumFormatOps = pDriverCaps->NumSupportedFormatOps; + DWORD NonCompatibleOperations = 0, MustSupportOperations = 0; + BOOL bSupportedWithAutogen = FALSE; + DWORD FormatOpIndex; + + if (FALSE == IsSupportedFormatOp(pDriverCaps, AdapterFormat, D3DFORMAT_OP_DISPLAYMODE | D3DFORMAT_OP_3DACCELERATION)) + { + return D3DERR_NOTAVAILABLE; + } + + /* Check for driver auto generated mip map support if requested */ + if ((Usage & (D3DUSAGE_AUTOGENMIPMAP)) != 0) + { + switch (RType) + { + case D3DRTYPE_TEXTURE: + if ((pDriverCaps->DriverCaps9.TextureCaps & D3DPTEXTURECAPS_MIPMAP) == 0) + return D3DERR_NOTAVAILABLE; + + break; + + case D3DRTYPE_VOLUME: + case D3DRTYPE_VOLUMETEXTURE: + if ((pDriverCaps->DriverCaps9.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP) == 0) + return D3DERR_NOTAVAILABLE; + + break; + + case D3DRTYPE_CUBETEXTURE: + if ((pDriverCaps->DriverCaps9.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP) == 0) + return D3DERR_NOTAVAILABLE; + + break; + + default: + /* Do nothing */ + break; + } + + MustSupportOperations |= D3DFORMAT_OP_AUTOGENMIPMAP; + } + + /* Translate from RType and Usage parameters to FormatOps */ + switch (RType) + { + case D3DRTYPE_TEXTURE: + MustSupportOperations |= D3DFORMAT_OP_TEXTURE; + break; + + case D3DRTYPE_VOLUME: + case D3DRTYPE_VOLUMETEXTURE: + MustSupportOperations |= D3DFORMAT_OP_VOLUMETEXTURE; + break; + + case D3DRTYPE_CUBETEXTURE: + MustSupportOperations |= D3DFORMAT_OP_CUBETEXTURE; + break; + + default: + /* Do nothing */ + break; + } + + if (Usage == 0 && RType == D3DRTYPE_SURFACE) + { + MustSupportOperations |= D3DFORMAT_OP_OFFSCREENPLAIN; + } + + if ((Usage & D3DUSAGE_DEPTHSTENCIL) != 0) + { + MustSupportOperations |= D3DFORMAT_OP_ZSTENCIL; + } + + if ((Usage & D3DUSAGE_DMAP) != 0) + { + MustSupportOperations |= D3DFORMAT_OP_DMAP; + } + + if ((Usage & D3DUSAGE_QUERY_LEGACYBUMPMAP) != 0) + { + MustSupportOperations |= D3DFORMAT_OP_BUMPMAP; + } + + if ((Usage & D3DUSAGE_QUERY_SRGBREAD) != 0) + { + MustSupportOperations |= D3DFORMAT_OP_SRGBREAD; + } + + if ((Usage & D3DUSAGE_QUERY_SRGBWRITE) != 0) + { + MustSupportOperations |= D3DFORMAT_OP_SRGBWRITE; + } + + if ((Usage & D3DUSAGE_QUERY_VERTEXTEXTURE) != 0) + { + MustSupportOperations |= D3DFORMAT_OP_VERTEXTEXTURE; + } + + CheckFormat = GetStencilFormat(pDriverCaps, CheckFormat); + + if ((Usage & D3DUSAGE_RENDERTARGET) != 0) + { + if (AdapterFormat == CheckFormat) + { + MustSupportOperations |= D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET; + } + else + { + D3DFORMAT NonAlphaAdapterFormat; + D3DFORMAT NonAlphaCheckFormat; + + NonAlphaAdapterFormat = RemoveAlphaChannel(AdapterFormat); + NonAlphaCheckFormat = RemoveAlphaChannel(CheckFormat); + + if (NonAlphaAdapterFormat == NonAlphaCheckFormat && + NonAlphaCheckFormat != D3DFMT_UNKNOWN) + { + MustSupportOperations |= D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET; + } + else + { + MustSupportOperations |= D3DFORMAT_OP_OFFSCREEN_RENDERTARGET; + } + } + } + + if ((Usage & D3DUSAGE_QUERY_FILTER) != 0) + { + NonCompatibleOperations |= D3DFORMAT_OP_OFFSCREENPLAIN; + } + + if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) != 0) + { + NonCompatibleOperations |= D3DFORMAT_OP_NOALPHABLEND; + } + + if ((Usage & D3DUSAGE_QUERY_WRAPANDMIP) != 0) + { + NonCompatibleOperations |= D3DFORMAT_OP_NOTEXCOORDWRAPNORMIP; + } + + for (FormatOpIndex = 0; FormatOpIndex < NumFormatOps; FormatOpIndex++) + { + DWORD dwOperations; + LPDDSURFACEDESC pSurfaceDesc = &pDriverCaps->pSupportedFormatOps[FormatOpIndex]; + + if (pSurfaceDesc->ddpfPixelFormat.dwFourCC != CheckFormat) + continue; + + dwOperations = pSurfaceDesc->ddpfPixelFormat.dwOperations; + + if ((dwOperations & NonCompatibleOperations) != 0) + continue; + + if ((dwOperations & MustSupportOperations) == MustSupportOperations) + return D3D_OK; + + if (((dwOperations & MustSupportOperations) | D3DFORMAT_OP_AUTOGENMIPMAP) == MustSupportOperations) + bSupportedWithAutogen = TRUE; + } + + if (TRUE == bSupportedWithAutogen) + return D3DOK_NOAUTOGEN; + + return D3DERR_NOTAVAILABLE; +} diff --git a/reactos/dll/directx/d3d9/format.h b/reactos/dll/directx/d3d9/format.h index 7c4e814bde6..cd6eec38f28 100644 --- a/reactos/dll/directx/d3d9/format.h +++ b/reactos/dll/directx/d3d9/format.h @@ -12,12 +12,25 @@ #include #include "d3d9_private.h" +#define D3DFORMAT_OP_DMAP 0x00020000L + +/* MSVC compile fix */ +#ifndef D3DFORMAT_OP_NOTEXCOORDWRAPNORMIP +#define D3DFORMAT_OP_NOTEXCOORDWRAPNORMIP 0x01000000L +#endif + BOOL IsBackBufferFormat(D3DFORMAT Format); BOOL IsExtendedFormat(D3DFORMAT Format); +BOOL IsZBufferFormat(D3DFORMAT Format); + +BOOL IsMultiElementFormat(D3DFORMAT Format); + BOOL IsSupportedFormatOp(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat, DWORD FormatOp); -HRESULT CheckDeviceFormat(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed); +HRESULT CheckDeviceType(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL Windowed); + +HRESULT CheckDeviceFormat(LPD3D9_DRIVERCAPS pDriverCaps, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat); #endif // _FORMAT_H_ diff --git a/reactos/include/psdk/d3d9types.h b/reactos/include/psdk/d3d9types.h index 638fa021af0..4aae6f0b801 100644 --- a/reactos/include/psdk/d3d9types.h +++ b/reactos/include/psdk/d3d9types.h @@ -110,6 +110,9 @@ #define D3DUSAGE_DYNAMIC 0x00000200L #define D3DUSAGE_AUTOGENMIPMAP 0x00000400L #define D3DUSAGE_DMAP 0x00004000L +#ifndef D3D_DISABLE_9EX +#define D3DUSAGE_TEXTAPI 0x10000000L +#endif #define D3DUSAGE_QUERY_FILTER 0x00020000L #define D3DUSAGE_QUERY_LEGACYBUMPMAP 0x00008000L