[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