[PATCH] This is a rewrite of CheckDeviceType. The previous version didn't check if formats were actually valid display/backbuffer formats. This one takes that into account. Further it lets CheckDeviceFormat handle the backbufferformat validation. CheckDeviceFormat can use some improvements in that area but that is something for a different patch, second it already works a lot better than before.
Roderick Colenbrander
thunderbird2k at gmx.net
Tue Feb 26 03:47:30 CST 2008
---
dlls/d3d9/tests/device.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/wined3d/directx.c | 79 ++++++++++++++++++++++++-------
2 files changed, 182 insertions(+), 17 deletions(-)
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 0d2f53b..eb82a63 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -1867,6 +1867,125 @@ cleanup:
if(d3d9) IDirect3D9_Release(d3d9);
}
+struct formats {
+ D3DFORMAT DisplayFormat;
+ D3DFORMAT BackBufferFormat;
+ BOOL shouldPass;
+};
+
+struct formats r5g6b5_format_list[] =
+{
+ { D3DFMT_R5G6B5, D3DFMT_R5G6B5, TRUE },
+ { D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, FALSE },
+ { D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, FALSE },
+ { D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, FALSE },
+ { D3DFMT_R5G6B5, D3DFMT_A8R8G8B8, FALSE },
+ { 0, 0, 0}
+};
+
+struct formats x1r5g5b5_format_list[] =
+{
+ { D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, FALSE },
+ { D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, TRUE },
+ { D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE },
+ { D3DFMT_X1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
+ { D3DFMT_X1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
+
+ /* A1R5G5B5 should not be usable as a display format, it is backbuffer-only */
+ { D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, FALSE },
+ { D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, FALSE },
+ { D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE },
+ { D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
+ { D3DFMT_A1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
+ { 0, 0, 0}
+};
+
+struct formats x8r8g8b8_format_list[] =
+{
+ { D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, FALSE },
+ { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
+ { D3DFMT_X8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
+ { D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, TRUE },
+ { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE },
+
+ /* A1R8G8B8 should not be usable as a display format, it is backbuffer-only */
+ { D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, FALSE },
+ { D3DFMT_A8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
+ { D3DFMT_A8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
+ { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, FALSE },
+ { D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE },
+ { 0, 0, 0}
+};
+
+static void test_display_formats()
+{
+ /* Direct3D9 offers 4 display formats R5G6B5, X1R5G5B5, X8R8G8B8 and A2R10G10B10.
+ * Next to these there are 6 different backbuffer formats. Only a fixed number of
+ * mixings are possible in FULLSCREEN mode. In windowed mode more combinations are
+ * allowed due to depth conversion and this is likely driver dependent.
+ * This test checks which combinations are possible in fullscreen mode and this should not be driver dependent.
+ * TODO: handle A2R10G10B10 but what hardware supports it? Parhelia? It is very rare. */
+
+ UINT Adapter = D3DADAPTER_DEFAULT;
+ D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
+ int i, nmodes;
+ HRESULT hr;
+
+ IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
+ ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
+ if(!d3d9) return;
+
+ nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_R5G6B5);
+ if(!nmodes) {
+ skip("Display format R5G6B5 not supported, skipping\n");
+ } else {
+ trace("Testing display format R5G6B5\n");
+ for(i=0; r5g6b5_format_list[i].DisplayFormat != 0; i++)
+ {
+ hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, FALSE);
+
+ if(r5g6b5_format_list[i].shouldPass)
+ ok(hr == D3D_OK, "format %d %d didn't pass with hr=%#08x\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, hr);
+ else
+ ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat);
+ }
+ }
+
+ nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X1R5G5B5);
+ if(!nmodes) {
+ skip("Display format X1R5G5B5 not supported, skipping\n");
+ } else {
+ trace("Testing display format X1R5G5B5\n");
+ for(i=0; x1r5g5b5_format_list[i].DisplayFormat != 0; i++)
+ {
+ hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, FALSE);
+
+ if(x1r5g5b5_format_list[i].shouldPass)
+ ok(hr == D3D_OK, "format %d %d didn't pass with hr=%#08x\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, hr);
+ else
+ ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat);
+ }
+ }
+
+ nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
+ if(!nmodes) {
+ skip("Display format X8R8G8B8 not supported, skipping\n");
+ } else {
+ trace("Testing display format X8R8G8B8\n");
+ for(i=0; x8r8g8b8_format_list[i].DisplayFormat != 0; i++)
+ {
+ hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, FALSE);
+
+ if(x8r8g8b8_format_list[i].shouldPass)
+ ok(hr == D3D_OK, "format %d %d didn't pass with hr=%#08x\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr);
+ else
+ ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat);
+ }
+ }
+
+ if(d3d9) IDirect3D9_Release(d3d9);
+}
+
START_TEST(device)
{
HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
@@ -1880,6 +1999,7 @@ START_TEST(device)
ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
if (pDirect3DCreate9)
{
+ test_display_formats();
test_display_modes();
test_swapchain();
test_refcount();
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 58a2781..e3158a7 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -139,6 +139,8 @@ static const struct {
static int numAdapters = 0;
static struct WineD3DAdapter Adapters[1];
+static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat);
+
/* lookup tables */
int minLookup[MAX_LOOKUPS];
int maxLookup[MAX_LOOKUPS];
@@ -1690,19 +1692,17 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, U
return WINED3DERR_NOTAVAILABLE;
}
-static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
+static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
- int nCfgs = 0;
- WineD3D_PixelFormat *cfgs;
- int it;
HRESULT hr = WINED3DERR_NOTAVAILABLE;
+ UINT nmodes;
TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
This,
Adapter,
- CheckType, debug_d3ddevicetype(CheckType),
+ DeviceType, debug_d3ddevicetype(DeviceType),
DisplayFormat, debug_d3dformat(DisplayFormat),
BackBufferFormat, debug_d3dformat(BackBufferFormat),
Windowed);
@@ -1712,21 +1712,66 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter
return WINED3DERR_INVALIDCALL;
}
- cfgs = Adapters[Adapter].cfgs;
- nCfgs = Adapters[Adapter].nCfgs;
- for (it = 0; it < nCfgs; ++it) {
- if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
- hr = WINED3D_OK;
- TRACE_(d3d_caps)("OK\n");
- break ;
- }
+ /* The task of this function is to check whether a certain display / backbuffer format
+ * combination is available on the given adapter. In fullscreen mode microsoft specified
+ * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
+ * and display format should match exactly.
+ * In windowed mode format conversion can occur and this depends on the driver. When format
+ * conversion is done, this function should nevertheless fail and applications need to use
+ * CheckDeviceFormatConversion.
+ * At the moment we assume that fullscreen and windowed have the same capabilities */
+
+ /* There are only 4 display formats */
+ if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
+ (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
+ (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
+ (DisplayFormat == WINED3DFMT_A2R10G10B10)))
+ {
+ TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
+ return WINED3DERR_NOTAVAILABLE;
}
- if(hr != WINED3D_OK)
- ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
+ /* If the requested DisplayFormat is not available, don't continue */
+ nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
+ if(!nmodes) {
+ TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
+ if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
+ TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
+ if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
+ if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
+ if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
+ if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
+ }
- if(hr != WINED3D_OK)
- TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
+ /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
+ hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat);
+ if(FAILED(hr))
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
return hr;
}
--
1.5.3.4
--========GMX17841204019246617827--
More information about the wine-patches
mailing list