diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index c23b8bf1b54..f1d7b37a50b 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -3074,31 +3074,7 @@ static HRESULT CreateSurface(IDirectDrawImpl *ddraw, DDSURFACEDESC2 *DDSD, desc2.dwFlags |= DDSD_PIXELFORMAT; desc2.u4.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT); - /* Wait: It could be a Z buffer */ - if(desc2.ddsCaps.dwCaps & DDSCAPS_ZBUFFER) - { - switch(desc2.u2.dwMipMapCount) /* Who had this glorious idea? */ - { - case 15: - PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_S1_UINT_D15_UNORM); - break; - case 16: - PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D16_UNORM); - break; - case 24: - PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_X8D24_UNORM); - break; - case 32: - PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, WINED3DFMT_D32_UNORM); - break; - default: - ERR("Unknown Z buffer bit depth\n"); - } - } - else - { - PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, Mode.Format); - } + PixelFormat_WineD3DtoDD(&desc2.u4.ddpfPixelFormat, Mode.Format); } /* No Width or no Height? Use the original screen size diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c index a257878ccd9..e06956e8fee 100644 --- a/dlls/ddraw/tests/dsurface.c +++ b/dlls/ddraw/tests/dsurface.c @@ -3845,6 +3845,188 @@ static void no_ddsd_caps_test(void) ok(hr == DDERR_INVALIDCAPS, "IDirectDraw_CreateSurface returned %#x, expected DDERR_INVALIDCAPS.\n", hr); } +static void dump_format(const DDPIXELFORMAT *fmt) +{ + trace("dwFlags %08x, FourCC %08x, dwZBufferBitDepth %u, stencil %u\n", fmt->dwFlags, fmt->dwFourCC, + fmt->dwZBufferBitDepth, fmt->dwStencilBitDepth); + trace("dwZBitMask %08x, dwStencilBitMask %08x, dwRGBZBitMask %08x\n", fmt->dwZBitMask, + fmt->dwStencilBitMask, fmt->dwRGBZBitMask); +} + +static void zbufferbitdepth_test(void) +{ + enum zfmt_succeed + { + ZFMT_SUPPORTED_ALWAYS, + ZFMT_SUPPORTED_NEVER, + ZFMT_SUPPORTED_HWDEPENDENT + }; + struct + { + DWORD depth; + enum zfmt_succeed supported; + DDPIXELFORMAT pf; + } + test_data[] = + { + { + 16, ZFMT_SUPPORTED_ALWAYS, + { + sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0, + {16}, {0}, {0x0000ffff}, {0x00000000}, {0x00000000} + } + }, + { + 24, ZFMT_SUPPORTED_ALWAYS, + { + sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0, + {24}, {0}, {0x00ffffff}, {0x00000000}, {0x00000000} + } + }, + { + 32, ZFMT_SUPPORTED_HWDEPENDENT, + { + sizeof(DDPIXELFORMAT), DDPF_ZBUFFER, 0, + {32}, {0}, {0xffffffff}, {0x00000000}, {0x00000000} + } + }, + /* Returns DDERR_INVALIDPARAMS instead of DDERR_INVALIDPIXELFORMAT. + * Disabled for now + { + 0, ZFMT_SUPPORTED_NEVER + }, + */ + { + 15, ZFMT_SUPPORTED_NEVER + }, + { + 28, ZFMT_SUPPORTED_NEVER + }, + { + 40, ZFMT_SUPPORTED_NEVER + }, + }; + + DDSURFACEDESC ddsd; + IDirectDrawSurface *surface; + HRESULT hr; + unsigned int i; + DDCAPS caps; + + memset(&caps, 0, sizeof(caps)); + caps.dwSize = sizeof(caps); + hr = IDirectDraw_GetCaps(lpDD, &caps, NULL); + ok(SUCCEEDED(hr), "IDirectDraw_GetCaps failed, hr %#x.\n", hr); + if (!(caps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) + { + skip("Z buffers not supported, skipping DDSD_ZBUFFERBITDEPTH test\n"); + return; + } + + for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); i++) + { + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; + ddsd.dwWidth = 256; + ddsd.dwHeight = 256; + ddsd.dwZBufferBitDepth = test_data[i].depth; + + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL); + if (test_data[i].supported == ZFMT_SUPPORTED_ALWAYS) + { + ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr); + } + else if (test_data[i].supported == ZFMT_SUPPORTED_NEVER) + { + ok(hr == DDERR_INVALIDPIXELFORMAT, "IDirectDraw_CreateSurface returned %#x, expected %x.\n", + hr, DDERR_INVALIDPIXELFORMAT); + } + if (!surface) continue; + + reset_ddsd(&ddsd); + hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd); + ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr); + IDirectDrawSurface_Release(surface); + + ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n"); + todo_wine ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n"); + /* Yet the ddpfPixelFormat member contains valid data */ + if (memcmp(&ddsd.ddpfPixelFormat, &test_data[i].pf, ddsd.ddpfPixelFormat.dwSize)) + { + ok(0, "Unexpected format for depth %u\n", test_data[i].depth); + dump_format(&ddsd.ddpfPixelFormat); + } + } + + /* DDSD_ZBUFFERBITDEPTH vs DDSD_PIXELFORMAT? */ + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_ZBUFFERBITDEPTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; + ddsd.dwWidth = 256; + ddsd.dwHeight = 256; + ddsd.dwZBufferBitDepth = 24; + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER; + ddsd.ddpfPixelFormat.dwZBufferBitDepth = 16; + ddsd.ddpfPixelFormat.dwZBitMask = 0x0000ffff; + + surface = NULL; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL); + ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr); + if (!surface) return; + reset_ddsd(&ddsd); + hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd); + ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr); + IDirectDrawSurface_Release(surface); + ok(ddsd.ddpfPixelFormat.dwZBufferBitDepth == 16, "Expected a 16bpp depth buffer, got %ubpp\n", + ddsd.ddpfPixelFormat.dwZBufferBitDepth); + ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n"); + todo_wine ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n"); + todo_wine ok(ddsd.dwZBufferBitDepth == 16, "Expected dwZBufferBitDepth=16, got %u\n", + ddsd.dwZBufferBitDepth); + + /* DDSD_PIXELFORMAT vs invalid ZBUFFERBITDEPTH */ + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; + ddsd.dwWidth = 256; + ddsd.dwHeight = 256; + ddsd.dwZBufferBitDepth = 40; + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER; + ddsd.ddpfPixelFormat.dwZBufferBitDepth = 16; + ddsd.ddpfPixelFormat.dwZBitMask = 0x0000ffff; + surface = NULL; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL); + ok(SUCCEEDED(hr), "IDirectDraw_CreateSurface failed, hr %#x.\n", hr); + if (surface) IDirectDrawSurface_Release(surface); + + /* Create a PIXELFORMAT-only surface, see if ZBUFFERBITDEPTH is set */ + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; + ddsd.dwWidth = 256; + ddsd.dwHeight = 256; + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER; + ddsd.ddpfPixelFormat.dwZBufferBitDepth = 16; + ddsd.ddpfPixelFormat.dwZBitMask = 0x0000ffff; + surface = NULL; + hr = IDirectDraw_CreateSurface(lpDD, &ddsd, &surface, NULL); + ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr); + reset_ddsd(&ddsd); + hr = IDirectDrawSurface_GetSurfaceDesc(surface, &ddsd); + ok(SUCCEEDED(hr), "IDirectDrawSurface_GetSurfaceDesc failed, hr %#x.\n", hr); + IDirectDrawSurface_Release(surface); + ok(ddsd.ddpfPixelFormat.dwZBufferBitDepth == 16, "Expected a 16bpp depth buffer, got %ubpp\n", + ddsd.ddpfPixelFormat.dwZBufferBitDepth); + todo_wine ok(ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH is not set\n"); + todo_wine ok(!(ddsd.dwFlags & DDSD_PIXELFORMAT), "DDSD_PIXELFORMAT is set\n"); + todo_wine ok(ddsd.dwZBufferBitDepth == 16, "Expected dwZBufferBitDepth=16, got %u\n", + ddsd.dwZBufferBitDepth); +} + START_TEST(dsurface) { HRESULT ret; @@ -3902,5 +4084,6 @@ START_TEST(dsurface) BackBufferAttachmentFlipTest(); CreateSurfaceBadCapsSizeTest(); no_ddsd_caps_test(); + zbufferbitdepth_test(); ReleaseDirectDraw(); } diff --git a/dlls/ddraw/utils.c b/dlls/ddraw/utils.c index 962a62fef4e..fce00eb8cab 100644 --- a/dlls/ddraw/utils.c +++ b/dlls/ddraw/utils.c @@ -1196,15 +1196,21 @@ void DDSD_to_DDSD2(const DDSURFACEDESC *in, DDSURFACEDESC2 *out) if (in->dwFlags & DDSD_WIDTH) out->dwWidth = in->dwWidth; if (in->dwFlags & DDSD_HEIGHT) out->dwHeight = in->dwHeight; if (in->dwFlags & DDSD_PIXELFORMAT) out->u4.ddpfPixelFormat = in->ddpfPixelFormat; + else if(in->dwFlags & DDSD_ZBUFFERBITDEPTH) + { + out->dwFlags |= DDSD_PIXELFORMAT; + memset(&out->u4.ddpfPixelFormat, 0, sizeof(out->u4.ddpfPixelFormat)); + out->u4.ddpfPixelFormat.dwSize = sizeof(out->u4.ddpfPixelFormat); + out->u4.ddpfPixelFormat.dwFlags = DDPF_ZBUFFER; + out->u4.ddpfPixelFormat.u1.dwZBufferBitDepth = in->u2.dwZBufferBitDepth; + /* 0 is not a valid DDSURFACEDESC / DDPIXELFORMAT on either side of the + * conversion */ + out->u4.ddpfPixelFormat.u3.dwZBitMask = ~0U >> (32 - in->u2.dwZBufferBitDepth); + } /* ddsCaps is read even without DDSD_CAPS set. See dsurface:no_ddsd_caps_test */ out->ddsCaps.dwCaps = in->ddsCaps.dwCaps; if (in->dwFlags & DDSD_PITCH) out->u1.lPitch = in->u1.lPitch; if (in->dwFlags & DDSD_BACKBUFFERCOUNT) out->dwBackBufferCount = in->dwBackBufferCount; - if (in->dwFlags & DDSD_ZBUFFERBITDEPTH) - { - /* FIXME: Convert into a DDPIXELFORMAT */ - out->u2.dwMipMapCount = in->u2.dwZBufferBitDepth; /* same union */ - } if (in->dwFlags & DDSD_ALPHABITDEPTH) out->dwAlphaBitDepth = in->dwAlphaBitDepth; /* DDraw(native, and wine) does not set the DDSD_LPSURFACE, so always copy */ out->lpSurface = in->lpSurface;