Implemented IDirect3D:CheckDeviceFormat()

svn path=/trunk/; revision=32541
This commit is contained in:
Gregor Brunmar 2008-03-02 12:29:35 +00:00
parent c5d9b2c282
commit 37eaa4b5db
5 changed files with 439 additions and 10 deletions

View file

@ -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,

View file

@ -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;

View file

@ -8,6 +8,7 @@
#include "format.h"
#include <ddrawi.h>
#include <debug.h>
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;
}

View file

@ -12,12 +12,25 @@
#include <d3d9.h>
#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_

View file

@ -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