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