Stefan Dösinger : ddraw: Emulate a 24 bit depth format without stencil or padding.

Alexandre Julliard julliard at winehq.org
Mon Aug 29 11:28:39 CDT 2011


Module: wine
Branch: master
Commit: 899b2785581d3ba2cc48d5c9abdccf6bb63943ca
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=899b2785581d3ba2cc48d5c9abdccf6bb63943ca

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Fri Aug 26 13:40:04 2011 +0200

ddraw: Emulate a 24 bit depth format without stencil or padding.

---

 dlls/ddraw/ddraw.c     |   18 ++++++++
 dlls/ddraw/tests/d3d.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/utils.c     |    3 +-
 3 files changed, 125 insertions(+), 1 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index d1754ec..a404d4f 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -5120,6 +5120,24 @@ static HRESULT WINAPI d3d7_EnumZBufferFormats(IDirect3D7 *iface, REFCLSID device
             }
         }
     }
+
+    /* Historically some windows drivers used dwZBufferBitDepth=24 for WINED3DFMT_X8D24_UNORM,
+     * while others used dwZBufferBitDepth=32. In either case the pitch matches a 32 bits per
+     * pixel format, so we use dwZBufferBitDepth=32. Some games expect 24. Windows Vista and
+     * newer enumerate both versions, so we do the same(bug 22434) */
+    hr = wined3d_check_device_format(This->wineD3D, WINED3DADAPTER_DEFAULT, type, d3ddm.Format,
+            WINED3DUSAGE_DEPTHSTENCIL, WINED3DRTYPE_SURFACE, WINED3DFMT_X8D24_UNORM, SURFACE_OPENGL);
+    if (SUCCEEDED(hr))
+    {
+        DDPIXELFORMAT x8d24 =
+        {
+            sizeof(x8d24), DDPF_ZBUFFER, 0,
+            {24}, {0x00000000}, {0x00ffffff}, {0x00000000}
+        };
+        TRACE("Enumerating WINED3DFMT_X8D24_UNORM, dwZBufferBitDepth=24 version\n");
+        callback(&x8d24, context);
+    }
+
     TRACE("End of enumeration.\n");
 
     LeaveCriticalSection(&ddraw_cs);
diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c
index 8946d48..a916f29 100644
--- a/dlls/ddraw/tests/d3d.c
+++ b/dlls/ddraw/tests/d3d.c
@@ -4361,6 +4361,110 @@ done:
     UnregisterClassA("d3d7_test_wndproc_wc", GetModuleHandleA(NULL));
 }
 
+static void dump_format(const DDPIXELFORMAT *fmt)
+{
+    trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %08x\n", fmt->dwFlags, fmt->dwFourCC,
+            fmt->dwZBufferBitDepth, fmt->dwStencilBitDepth);
+    trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", fmt->dwZBitMask,
+            fmt->dwStencilBitMask, fmt->dwRGBZBitMask);
+}
+
+HRESULT WINAPI enum_z_fmt_cb(DDPIXELFORMAT *fmt, void *ctx)
+{
+    static const DDPIXELFORMAT formats[] =
+    {
+        {
+            sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
+            {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000}
+        },
+        {
+            sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
+            {32}, {0}, {0xffffff00}, {0x00000000}, {0x00000000}
+        },
+        {
+            sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
+            {32}, {8}, {0xffffff00}, {0x000000ff}, {0x00000000}
+        },
+        {
+            sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
+            {32}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
+        },
+        {
+            sizeof(DDPIXELFORMAT), DDPF_ZBUFFER | DDPF_STENCILBUFFER, 0,
+            {32}, {8}, {0x00ffffff}, {0xff000000}, {0x00000000}
+        },
+        {
+            sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
+            {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000}
+        },
+        {
+            sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0,
+            {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000}
+        },
+    };
+    unsigned int *count = ctx, i, expected_pitch;
+    DDSURFACEDESC2 ddsd;
+    IDirectDrawSurface7 *surface;
+    HRESULT hr;
+    (*count)++;
+
+    memset(&ddsd, 0, sizeof(ddsd));
+    ddsd.dwSize = sizeof(ddsd);
+    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+    ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
+    ddsd.ddpfPixelFormat = *fmt;
+    ddsd.dwWidth = 1024;
+    ddsd.dwHeight = 1024;
+    hr = IDirectDraw7_CreateSurface(lpDD, &ddsd, &surface, NULL);
+    ok(SUCCEEDED(hr), "IDirectDraw7_CreateSurface failed, hr %#x.\n", hr);
+    memset(&ddsd, 0, sizeof(ddsd));
+    ddsd.dwSize = sizeof(ddsd);
+    hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd);
+    ok(SUCCEEDED(hr), "IDirectDrawSurface7_GetSurfaceDesc failed, hr %#x.\n", hr);
+    IDirectDrawSurface7_Release(surface);
+
+    ok(ddsd.dwFlags & DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT is not set\n");
+    ok(!(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH), "DDSD_ZBUFFERBITDEPTH is set\n");
+
+    /* 24 bit unpadded depth buffers are actually padded(Geforce 9600, Win7,
+     * Radeon 9000M WinXP) */
+    if (fmt->dwZBufferBitDepth == 24) expected_pitch = ddsd.dwWidth * 4;
+    else expected_pitch = ddsd.dwWidth * fmt->dwZBufferBitDepth / 8;
+
+    /* Some formats(16 bit depth without stencil) return pitch 0 */
+    if (ddsd.lPitch != 0 && ddsd.lPitch != expected_pitch)
+    {
+        ok(0, "Z buffer pitch is %u, expected %u\n", ddsd.lPitch, expected_pitch);
+        dump_format(fmt);
+    }
+
+    for (i = 0; i < (sizeof(formats)/sizeof(*formats)); i++)
+    {
+        if (memcmp(&formats[i], fmt, fmt->dwSize) == 0) return DDENUMRET_OK;
+    }
+
+    ok(0, "Unexpected Z format enumerated\n");
+    dump_format(fmt);
+
+    return DDENUMRET_OK;
+}
+
+static void z_format_test(void)
+{
+    unsigned int count = 0;
+    HRESULT hr;
+
+    hr = IDirect3D7_EnumZBufferFormats(lpD3D, &IID_IDirect3DHALDevice, enum_z_fmt_cb, &count);
+    if (hr == DDERR_NOZBUFFERHW)
+    {
+        skip("Z buffers not supported, skipping Z buffer format test\n");
+        return;
+    }
+
+    ok(SUCCEEDED(hr), "IDirect3D7_EnumZBufferFormats failed, hr %#x.\n", hr);
+    ok(count, "Expected at least one supported Z Buffer format\n");
+}
+
 START_TEST(d3d)
 {
     init_function_pointers();
@@ -4387,6 +4491,7 @@ START_TEST(d3d)
         DeviceLoadTest();
         SetRenderTargetTest();
         VertexBufferLockRest();
+        z_format_test();
         ReleaseDirect3D();
     }
 
diff --git a/dlls/ddraw/utils.c b/dlls/ddraw/utils.c
index 94e4ac0..0bd1ee4 100644
--- a/dlls/ddraw/utils.c
+++ b/dlls/ddraw/utils.c
@@ -559,7 +559,8 @@ enum wined3d_format_id PixelFormat_DD2WineD3D(const DDPIXELFORMAT *DDPixelFormat
                     return WINED3DFMT_D16_UNORM;
 
                 case 24:
-                    FIXME("24 Bit depth buffer, treating like a 32 bit one\n");
+                    return WINED3DFMT_X8D24_UNORM;
+
                 case 32:
                     if(DDPixelFormat->u3.dwZBitMask == 0x00FFFFFF) {
                         return WINED3DFMT_X8D24_UNORM;




More information about the wine-cvs mailing list