[PATCH 4/4] ddraw/tests: Test color keying precision.
Stefan Dösinger
stefan at codeweavers.com
Thu Aug 20 03:03:35 CDT 2015
This brute force tests all values in 4, 5, 6 and 8 bit channels.
---
dlls/ddraw/tests/ddraw1.c | 335 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw2.c | 308 ++++++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw4.c | 318 +++++++++++++++++++++++++++++++++++++++++++
dlls/ddraw/tests/ddraw7.c | 302 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 1263 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index f97b964..676d357 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -7279,6 +7279,340 @@ done:
DestroyWindow(window);
}
+static void test_colorkey_precision(void)
+{
+ static D3DTLVERTEX quad[] =
+ {
+ {{ 0.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {1.0f}},
+ {{ 0.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {0.0f}, {0.0f}},
+ {{640.0f}, {480.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {1.0f}},
+ {{640.0f}, { 0.0f}, {0.0f}, {1.0f}, {0x00000000}, {0x00000000}, {1.0f}, {0.0f}},
+ };
+ static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
+ IDirect3DDevice *device;
+ IDirectDraw *ddraw;
+ IDirectDrawSurface *rt;
+ IDirect3DViewport *viewport;
+ IDirect3DExecuteBuffer *execute_buffer;
+ D3DEXECUTEBUFFERDESC exec_desc;
+ UINT inst_length;
+ void *ptr;
+ HWND window;
+ HRESULT hr;
+ IDirectDrawSurface *src, *dst, *texture;
+ D3DTEXTUREHANDLE handle;
+ IDirect3DTexture *d3d_texture;
+ IDirect3DMaterial *green;
+ DDSURFACEDESC surface_desc, lock_desc;
+ ULONG refcount;
+ D3DCOLOR color;
+ unsigned int t, c;
+ DDCOLORKEY ckey;
+ DDBLTFX fx;
+ DWORD data[4] = {0}, color_mask;
+ D3DDEVICEDESC device_desc, hel_desc;
+ BOOL warp;
+ static const struct
+ {
+ unsigned int max, shift, bpp, clear;
+ const char *name;
+ DDPIXELFORMAT fmt;
+ }
+ tests[] =
+ {
+ {
+ 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
+ }
+
+ },
+ {
+ 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
+ {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
+ }
+
+ },
+ };
+
+ window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, 0, 0, 0, 0);
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device, skipping test.\n");
+ DestroyWindow(window);
+ IDirectDraw_Release(ddraw);
+ return;
+ }
+ hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
+ ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+ /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
+ * (color key doesn't match although the values are equal), and a false
+ * positive when the color key is 0 and the texture contains the value 1.
+ * I don't want to mark this broken unconditionally since this would
+ * essentially disable the test on Windows. Try to detect WARP (and I
+ * guess mismatch other SW renderers) by its ability to texture from
+ * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
+ memset(&device_desc, 0, sizeof(device_desc));
+ device_desc.dwSize = sizeof(device_desc);
+ memset(&hel_desc, 0, sizeof(hel_desc));
+ hel_desc.dwSize = sizeof(hel_desc);
+ hr = IDirect3DDevice_GetCaps(device, &device_desc, &hel_desc);
+ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
+ warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
+
+ green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
+ viewport = create_viewport(device, 0, 0, 640, 480);
+ viewport_set_background(device, viewport, green);
+
+ memset(&exec_desc, 0, sizeof(exec_desc));
+ exec_desc.dwSize = sizeof(exec_desc);
+ exec_desc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
+ exec_desc.dwBufferSize = 1024;
+ exec_desc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
+ hr = IDirect3DDevice_CreateExecuteBuffer(device, &exec_desc, &execute_buffer, NULL);
+ ok(SUCCEEDED(hr), "Failed to create execute buffer, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ memset(&lock_desc, 0, sizeof(lock_desc));
+ lock_desc.dwSize = sizeof(lock_desc);
+
+ for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
+ {
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ surface_desc.dwWidth = 4;
+ surface_desc.dwHeight = 1;
+ surface_desc.ddpfPixelFormat = tests[t].fmt;
+ /* Windows XP (at least with the r200 driver, other drivers untested) produces
+ * garbage when doing color keyed texture->texture blits. */
+ hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &src, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &dst, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ fx.dwFillColor = tests[t].clear;
+ /* On the w8 testbot (WARP driver) the blit result has different values in the
+ * X channel. */
+ color_mask = U2(tests[t].fmt).dwRBitMask
+ | U3(tests[t].fmt).dwGBitMask
+ | U4(tests[t].fmt).dwBBitMask;
+
+ for (c = 0; c <= tests[t].max; ++c)
+ {
+ /* The idiotic Nvidia Windows driver can't change the color key on a d3d
+ * texture after it has been set once... */
+ surface_desc.dwFlags |= DDSD_CKSRCBLT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_QueryInterface(texture, &IID_IDirect3DTexture, (void **)&d3d_texture);
+ ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
+ hr = IDirect3DTexture_GetHandle(d3d_texture, device, &handle);
+ ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
+ IDirect3DTexture_Release(d3d_texture);
+
+ hr = IDirect3DExecuteBuffer_Lock(execute_buffer, &exec_desc);
+ ok(SUCCEEDED(hr), "Failed to lock execute buffer, hr %#x.\n", hr);
+
+ memcpy(exec_desc.lpData, quad, sizeof(quad));
+
+ ptr = ((BYTE *)exec_desc.lpData) + sizeof(quad);
+ emit_process_vertices(&ptr, D3DPROCESSVERTICES_COPY, 0, 8);
+ emit_set_rs(&ptr, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
+ emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, handle);
+ emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
+ /* D3DRENDERSTATE_COLORKEYENABLE is supposed to be on by default on version
+ * 1 devices, but for some reason it randomly defaults to FALSE on the W8
+ * testbot. This is either the fault of Windows 8 or the WARP driver.
+ * Also D3DRENDERSTATE_COLORKEYENABLE was introduced in D3D 5 aka version 2
+ * devices only, which might imply this doesn't actually do anything on
+ * WARP. */
+ emit_set_rs(&ptr, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
+
+ emit_tquad(&ptr, 0);
+ emit_tquad(&ptr, 4);
+ emit_set_rs(&ptr, D3DRENDERSTATE_TEXTUREHANDLE, 0);
+ emit_end(&ptr);
+
+ inst_length = (BYTE *)ptr - (BYTE *)exec_desc.lpData;
+ inst_length -= sizeof(quad);
+ hr = IDirect3DExecuteBuffer_Unlock(execute_buffer);
+ ok(SUCCEEDED(hr), "Failed to unlock execute buffer, hr %#x.\n", hr);
+ set_execute_data(execute_buffer, 8, sizeof(quad), inst_length);
+
+ hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
+ break;
+
+ case 2:
+ ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
+ break;
+ }
+ hr = IDirectDrawSurface_Unlock(src, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ ckey.dwColorSpaceLowValue = c << tests[t].shift;
+ ckey.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
+ ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
+ hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+
+ case 2:
+ data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+ }
+ hr = IDirectDrawSurface_Unlock(dst, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+
+ if (!c)
+ {
+ ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[0], tests[t].name, c);
+
+ if (data[3] == tests[t].clear)
+ {
+ /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
+ * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
+ * even when a different surface is used. The blit itself doesn't draw anything,
+ * so we can detect the bug by looking at the otherwise unused 4th texel. It should
+ * never be masked out by the key.
+ *
+ * Also appears to affect the testbot in some way with R5G6B5. Color keying is
+ * terrible on WARP. */
+ skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
+ IDirectDrawSurface_Release(texture);
+ IDirectDrawSurface_Release(src);
+ IDirectDrawSurface_Release(dst);
+ goto done;
+ }
+ }
+ else
+ ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c - 1) << tests[t].shift, data[0], tests[t].name, c);
+
+ ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[1], tests[t].name, c);
+
+ if (c == tests[t].max)
+ ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[2], tests[t].name, c);
+ else
+ ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c + 1) << tests[t].shift, data[2], tests[t].name, c);
+
+ hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
+ ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice_BeginScene(device);
+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice_Execute(device, execute_buffer, viewport, D3DEXECUTE_UNCLIPPED);
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice_EndScene(device);
+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+ color = get_surface_color(rt, 80, 240);
+ if (!c)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 240, 240);
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 400, 240);
+ if (c == tests[t].max)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ IDirectDrawSurface_Release(texture);
+ }
+ IDirectDrawSurface_Release(src);
+ IDirectDrawSurface_Release(dst);
+ }
+done:
+
+ destroy_viewport(device, viewport);
+ destroy_material(green);
+ IDirectDrawSurface_Release(rt);
+ IDirect3DExecuteBuffer_Release(execute_buffer);
+ IDirect3DDevice_Release(device);
+ refcount = IDirectDraw_Release(ddraw);
+ ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw1)
{
IDirectDraw *ddraw;
@@ -7348,4 +7682,5 @@ START_TEST(ddraw1)
test_texturemapblend();
test_viewport_clear_rect();
test_color_fill();
+ test_colorkey_precision();
}
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 0cb1ca4..d1f94fc 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -8435,6 +8435,313 @@ done:
DestroyWindow(window);
}
+static void test_colorkey_precision(void)
+{
+ static D3DLVERTEX quad[] =
+ {
+ {{-1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {0.0f}},
+ {{-1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {0.0f}, {1.0f}},
+ {{ 1.0f}, {-1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {0.0f}},
+ {{ 1.0f}, { 1.0f}, {0.0f}, 0, {0xff000000}, {0}, {1.0f}, {1.0f}},
+ };
+ static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
+ IDirect3DDevice2 *device;
+ IDirectDraw2 *ddraw;
+ IDirectDrawSurface *rt;
+ IDirect3DViewport2 *viewport;
+ HWND window;
+ HRESULT hr;
+ IDirectDrawSurface *src, *dst, *texture;
+ D3DTEXTUREHANDLE handle;
+ IDirect3DTexture2 *d3d_texture;
+ IDirect3DMaterial2 *green;
+ DDSURFACEDESC surface_desc, lock_desc;
+ ULONG refcount;
+ D3DCOLOR color;
+ unsigned int t, c;
+ DDCOLORKEY ckey;
+ DDBLTFX fx;
+ DWORD data[4] = {0}, color_mask;
+ D3DDEVICEDESC device_desc, hel_desc;
+ BOOL warp;
+ static const struct
+ {
+ unsigned int max, shift, bpp, clear;
+ const char *name;
+ DDPIXELFORMAT fmt;
+ }
+ tests[] =
+ {
+ {
+ 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
+ }
+
+ },
+ {
+ 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
+ {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
+ }
+
+ },
+ };
+
+ window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, 0, 0, 0, 0);
+ ddraw = create_ddraw();
+ ok(!!ddraw, "Failed to create a ddraw object.\n");
+ if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device, skipping test.\n");
+ DestroyWindow(window);
+ IDirectDraw2_Release(ddraw);
+ return;
+ }
+ hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
+ ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+ /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
+ * (color key doesn't match although the values are equal), and a false
+ * positive when the color key is 0 and the texture contains the value 1.
+ * I don't want to mark this broken unconditionally since this would
+ * essentially disable the test on Windows. Try to detect WARP (and I
+ * guess mismatch other SW renderers) by its ability to texture from
+ * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
+ memset(&device_desc, 0, sizeof(device_desc));
+ device_desc.dwSize = sizeof(device_desc);
+ memset(&hel_desc, 0, sizeof(hel_desc));
+ hel_desc.dwSize = sizeof(hel_desc);
+ hr = IDirect3DDevice2_GetCaps(device, &device_desc, &hel_desc);
+ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
+ warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
+
+ green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 0.0f);
+ viewport = create_viewport(device, 0, 0, 640, 480);
+ viewport_set_background(device, viewport, green);
+ hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
+ ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
+ ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
+ hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
+ ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
+ /* There's no way to ignore the texture color in d3d2, so multiply the texture color
+ * with a black vertex color. */
+ hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATEALPHA);
+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ memset(&lock_desc, 0, sizeof(lock_desc));
+ lock_desc.dwSize = sizeof(lock_desc);
+
+ for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
+ {
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ surface_desc.dwWidth = 4;
+ surface_desc.dwHeight = 1;
+ surface_desc.ddpfPixelFormat = tests[t].fmt;
+ /* Windows XP (at least with the r200 driver, other drivers untested) produces
+ * garbage when doing color keyed texture->texture blits. */
+ hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &src, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &dst, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ fx.dwFillColor = tests[t].clear;
+ /* On the w8 testbot (WARP driver) the blit result has different values in the
+ * X channel. */
+ color_mask = U2(tests[t].fmt).dwRBitMask
+ | U3(tests[t].fmt).dwGBitMask
+ | U4(tests[t].fmt).dwBBitMask;
+
+ for (c = 0; c <= tests[t].max; ++c)
+ {
+ /* The idiotic Nvidia Windows driver can't change the color key on a d3d
+ * texture after it has been set once... */
+ surface_desc.dwFlags |= DDSD_CKSRCBLT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
+ ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
+ hr = IDirect3DTexture2_GetHandle(d3d_texture, device, &handle);
+ ok(SUCCEEDED(hr), "Failed to get texture handle, hr %#x.\n", hr);
+ hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, handle);
+ ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
+ IDirect3DTexture2_Release(d3d_texture);
+
+ hr = IDirectDrawSurface_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
+ break;
+
+ case 2:
+ ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
+ break;
+ }
+ hr = IDirectDrawSurface_Unlock(src, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ ckey.dwColorSpaceLowValue = c << tests[t].shift;
+ ckey.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDrawSurface_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
+ ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
+ hr = IDirectDrawSurface_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+
+ case 2:
+ data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+ }
+ hr = IDirectDrawSurface_Unlock(dst, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+
+ if (!c)
+ {
+ ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[0], tests[t].name, c);
+
+ if (data[3] == tests[t].clear)
+ {
+ /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
+ * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
+ * even when a different surface is used. The blit itself doesn't draw anything,
+ * so we can detect the bug by looking at the otherwise unused 4th texel. It should
+ * never be masked out by the key.
+ *
+ * Also appears to affect the testbot in some way with R5G6B5. Color keying is
+ * terrible on WARP. */
+ skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
+ IDirectDrawSurface_Release(texture);
+ IDirectDrawSurface_Release(src);
+ IDirectDrawSurface_Release(dst);
+ goto done;
+ }
+ }
+ else
+ ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c - 1) << tests[t].shift, data[0], tests[t].name, c);
+
+ ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[1], tests[t].name, c);
+
+ if (c == tests[t].max)
+ ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[2], tests[t].name, c);
+ else
+ ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c + 1) << tests[t].shift, data[2], tests[t].name, c);
+
+ hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
+ ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice2_BeginScene(device);
+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice2_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DVT_LVERTEX, quad, 4, 0);
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice2_EndScene(device);
+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+ color = get_surface_color(rt, 80, 240);
+ if (!c)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 240, 240);
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 400, 240);
+ if (c == tests[t].max)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_TEXTUREHANDLE, 0);
+ ok(SUCCEEDED(hr), "Failed to set texture handle, hr %#x.\n", hr);
+ IDirectDrawSurface_Release(texture);
+ }
+ IDirectDrawSurface_Release(src);
+ IDirectDrawSurface_Release(dst);
+ }
+done:
+
+ destroy_viewport(device, viewport);
+ destroy_material(green);
+ IDirectDrawSurface_Release(rt);
+ IDirect3DDevice2_Release(device);
+ refcount = IDirectDraw2_Release(ddraw);
+ ok(refcount == 0, "Ddraw object not properly released, refcount %u.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw2)
{
IDirectDraw2 *ddraw;
@@ -8511,4 +8818,5 @@ START_TEST(ddraw2)
test_texturemapblend();
test_viewport_clear_rect();
test_color_fill();
+ test_colorkey_precision();
}
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index b1ac1f1..85c632c 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -9555,6 +9555,323 @@ static void test_texcoordindex(void)
DestroyWindow(window);
}
+static void test_colorkey_precision(void)
+{
+ static struct
+ {
+ struct vec3 pos;
+ struct vec2 texcoord;
+ }
+ quad[] =
+ {
+ {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
+ {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
+ {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
+ {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
+ };
+ IDirect3DDevice3 *device;
+ IDirect3D3 *d3d;
+ IDirectDraw4 *ddraw;
+ IDirectDrawSurface4 *rt;
+ IDirect3DViewport3 *viewport;
+ HWND window;
+ HRESULT hr;
+ IDirectDrawSurface4 *src, *dst, *texture;
+ IDirect3DTexture2 *d3d_texture;
+ DDSURFACEDESC2 surface_desc, lock_desc;
+ ULONG refcount;
+ D3DCOLOR color;
+ unsigned int t, c;
+ DDCOLORKEY ckey;
+ DDBLTFX fx;
+ DWORD data[4] = {0}, color_mask;
+ D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
+ D3DDEVICEDESC device_desc, hel_desc;
+ BOOL warp;
+ static const struct
+ {
+ unsigned int max, shift, bpp, clear;
+ const char *name;
+ DDPIXELFORMAT fmt;
+ }
+ tests[] =
+ {
+ {
+ 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
+ }
+
+ },
+ {
+ 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
+ {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
+ }
+
+ },
+ };
+
+ window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, 0, 0, 0, 0);
+ if (!(device = create_device(window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device, skipping test.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
+ * (color key doesn't match although the values are equal), and a false
+ * positive when the color key is 0 and the texture contains the value 1.
+ * I don't want to mark this broken unconditionally since this would
+ * essentially disable the test on Windows. Try to detect WARP (and I
+ * guess mismatch other SW renderers) by its ability to texture from
+ * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
+ memset(&device_desc, 0, sizeof(device_desc));
+ device_desc.dwSize = sizeof(device_desc);
+ memset(&hel_desc, 0, sizeof(hel_desc));
+ hel_desc.dwSize = sizeof(hel_desc);
+ hr = IDirect3DDevice3_GetCaps(device, &device_desc, &hel_desc);
+ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
+ warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
+
+ hr = IDirect3DDevice3_GetDirect3D(device, &d3d);
+ ok(SUCCEEDED(hr), "Failed to get Direct3D3 interface, hr %#x.\n", hr);
+ hr = IDirect3D3_QueryInterface(d3d, &IID_IDirectDraw4, (void **)&ddraw);
+ ok(SUCCEEDED(hr), "Failed to get DirectDraw4 interface, hr %#x.\n", hr);
+ IDirect3D3_Release(d3d);
+ hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
+ ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+ viewport = create_viewport(device, 0, 0, 640, 480);
+ hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
+ ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+ ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
+ ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
+ ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
+ /* Multiply the texture read result with 0, that way the result color if the key doesn't
+ * match is constant. In theory color keying works without reading the texture result
+ * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
+ * to differ. */
+ hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ memset(&lock_desc, 0, sizeof(lock_desc));
+ lock_desc.dwSize = sizeof(lock_desc);
+
+ for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
+ {
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ surface_desc.dwWidth = 4;
+ surface_desc.dwHeight = 1;
+ U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
+ /* Windows XP (at least with the r200 driver, other drivers untested) produces
+ * garbage when doing color keyed texture->texture blits. */
+ hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &src, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &dst, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ fx.dwFillColor = tests[t].clear;
+ /* On the w8 testbot (WARP driver) the blit result has different values in the
+ * X channel. */
+ color_mask = U2(tests[t].fmt).dwRBitMask
+ | U3(tests[t].fmt).dwGBitMask
+ | U4(tests[t].fmt).dwBBitMask;
+
+ for (c = 0; c <= tests[t].max; ++c)
+ {
+ /* The idiotic Nvidia Windows driver can't change the color key on a d3d
+ * texture after it has been set once... */
+ surface_desc.dwFlags |= DDSD_CKSRCBLT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface4_QueryInterface(texture, &IID_IDirect3DTexture2, (void **)&d3d_texture);
+ ok(SUCCEEDED(hr), "Failed to get texture interface, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_SetTexture(device, 0, d3d_texture);
+ ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface4_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface4_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
+ break;
+
+ case 2:
+ ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
+ break;
+ }
+ hr = IDirectDrawSurface4_Unlock(src, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface4_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ ckey.dwColorSpaceLowValue = c << tests[t].shift;
+ ckey.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDrawSurface4_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
+ ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface4_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
+ hr = IDirectDrawSurface4_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+
+ case 2:
+ data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+ }
+ hr = IDirectDrawSurface4_Unlock(dst, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+
+ if (!c)
+ {
+ ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[0], tests[t].name, c);
+
+ if (data[3] == tests[t].clear)
+ {
+ /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
+ * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
+ * even when a different surface is used. The blit itself doesn't draw anything,
+ * so we can detect the bug by looking at the otherwise unused 4th texel. It should
+ * never be masked out by the key.
+ *
+ * Also appears to affect the testbot in some way with R5G6B5. Color keying is
+ * terrible on WARP. */
+ skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
+ IDirect3DTexture2_Release(d3d_texture);
+ IDirectDrawSurface4_Release(texture);
+ IDirectDrawSurface4_Release(src);
+ IDirectDrawSurface4_Release(dst);
+ goto done;
+ }
+ }
+ else
+ ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c - 1) << tests[t].shift, data[0], tests[t].name, c);
+
+ ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[1], tests[t].name, c);
+
+ if (c == tests[t].max)
+ ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[2], tests[t].name, c);
+ else
+ ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c + 1) << tests[t].shift, data[2], tests[t].name, c);
+
+ hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
+ ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice3_BeginScene(device);
+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice3_EndScene(device);
+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+ color = get_surface_color(rt, 80, 240);
+ if (!c)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 240, 240);
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 400, 240);
+ if (c == tests[t].max)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ IDirect3DTexture2_Release(d3d_texture);
+ IDirectDrawSurface4_Release(texture);
+ }
+ IDirectDrawSurface4_Release(src);
+ IDirectDrawSurface4_Release(dst);
+ }
+ done:
+
+ destroy_viewport(device, viewport);
+ IDirectDrawSurface4_Release(rt);
+ IDirectDraw4_Release(ddraw);
+ refcount = IDirect3DDevice3_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw4)
{
IDirectDraw4 *ddraw;
@@ -9638,4 +9955,5 @@ START_TEST(ddraw4)
test_signed_formats();
test_color_fill();
test_texcoordindex();
+ test_colorkey_precision();
}
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index e6a8d15..30213c5 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -9740,6 +9740,307 @@ static void test_texcoordindex(void)
DestroyWindow(window);
}
+static void test_colorkey_precision(void)
+{
+ static struct
+ {
+ struct vec3 pos;
+ struct vec2 texcoord;
+ }
+ quad[] =
+ {
+ {{-1.0f, -1.0f, 0.0f}, {0.0f, 1.0f}},
+ {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}},
+ {{ 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f}},
+ {{ 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
+ };
+ IDirect3DDevice7 *device;
+ IDirect3D7 *d3d;
+ IDirectDraw7 *ddraw;
+ IDirectDrawSurface7 *rt;
+ HWND window;
+ HRESULT hr;
+ IDirectDrawSurface7 *src, *dst, *texture;
+ DDSURFACEDESC2 surface_desc, lock_desc;
+ ULONG refcount;
+ D3DCOLOR color;
+ unsigned int t, c;
+ DDCOLORKEY ckey;
+ DDBLTFX fx;
+ DWORD data[4] = {0}, color_mask;
+ D3DDEVICEDESC7 device_desc;
+ BOOL warp;
+ static const struct
+ {
+ unsigned int max, shift, bpp, clear;
+ const char *name;
+ DDPIXELFORMAT fmt;
+ }
+ tests[] =
+ {
+ {
+ 255, 0, 4, 0x00345678, "D3DFMT_X8R8G8B8",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {32}, {0x00ff0000}, {0x0000ff00}, {0x000000ff}, {0x00000000}
+ }
+
+ },
+ {
+ 63, 5, 2, 0x5678, "D3DFMT_R5G6B5, G channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 31, 0, 2, 0x5678, "D3DFMT_R5G6B5, B channel",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB, 0,
+ {16}, {0xf800}, {0x07e0}, {0x001f}, {0x0000}
+ }
+
+ },
+ {
+ 15, 0, 2, 0x0678, "D3DFMT_A4R4G4B4",
+ {
+ sizeof(DDPIXELFORMAT), DDPF_RGB | DDPF_ALPHAPIXELS, 0,
+ {16}, {0x0f00}, {0x00f0}, {0x000f}, {0xf000}
+ }
+
+ },
+ };
+
+ window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+ 0, 0, 640, 480, 0, 0, 0, 0);
+ if (!(device = create_device(window, DDSCL_NORMAL)))
+ {
+ skip("Failed to create a 3D device, skipping test.\n");
+ DestroyWindow(window);
+ return;
+ }
+
+ /* The Windows 8 WARP driver has plenty of false negatives in X8R8G8B8
+ * (color key doesn't match although the values are equal), and a false
+ * positive when the color key is 0 and the texture contains the value 1.
+ * I don't want to mark this broken unconditionally since this would
+ * essentially disable the test on Windows. Try to detect WARP (and I
+ * guess mismatch other SW renderers) by its ability to texture from
+ * system memory. Also on random occasions 254 == 255 and 255 != 255.*/
+ hr = IDirect3DDevice7_GetCaps(device, &device_desc);
+ ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
+ warp = !!(device_desc.dwDevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY);
+
+ hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
+ ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
+ hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw);
+ ok(SUCCEEDED(hr), "Failed to get DirectDraw7 interface, hr %#x.\n", hr);
+ IDirect3D7_Release(d3d);
+ hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
+ ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+ ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE);
+ ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_COLORKEYENABLE, TRUE);
+ ok(SUCCEEDED(hr), "Failed to enable color keying, hr %#x.\n", hr);
+ /* Multiply the texture read result with 0, that way the result color if the key doesn't
+ * match is constant. In theory color keying works without reading the texture result
+ * (meaning we could just op=arg1, arg1=tfactor), but the Geforce7 Windows driver begs
+ * to differ. */
+ hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ ok(SUCCEEDED(hr), "Failed to set color op, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ ok(SUCCEEDED(hr), "Failed to set color arg, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_TEXTUREFACTOR, 0x00000000);
+ ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
+
+ memset(&fx, 0, sizeof(fx));
+ fx.dwSize = sizeof(fx);
+ memset(&lock_desc, 0, sizeof(lock_desc));
+ lock_desc.dwSize = sizeof(lock_desc);
+
+ for (t = 0; t < sizeof(tests) / sizeof(*tests); ++t)
+ {
+ memset(&surface_desc, 0, sizeof(surface_desc));
+ surface_desc.dwSize = sizeof(surface_desc);
+ surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ surface_desc.dwWidth = 4;
+ surface_desc.dwHeight = 1;
+ U4(surface_desc).ddpfPixelFormat = tests[t].fmt;
+ /* Windows XP (at least with the r200 driver, other drivers untested) produces
+ * garbage when doing color keyed texture->texture blits. */
+ hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &src, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &dst, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+ fx.dwFillColor = tests[t].clear;
+ /* On the w8 testbot (WARP driver) the blit result has different values in the
+ * X channel. */
+ color_mask = U2(tests[t].fmt).dwRBitMask
+ | U3(tests[t].fmt).dwGBitMask
+ | U4(tests[t].fmt).dwBBitMask;
+
+ for (c = 0; c <= tests[t].max; ++c)
+ {
+ /* The idiotic Nvidia Windows driver can't change the color key on a d3d
+ * texture after it has been set once... */
+ surface_desc.dwFlags |= DDSD_CKSRCBLT;
+ surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = c << tests[t].shift;
+ surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &texture, NULL);
+ ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_SetTexture(device, 0, texture);
+ ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface7_Blt(dst, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
+ ok(SUCCEEDED(hr), "Failed to clear destination surface, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface7_Lock(src, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ ((DWORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((DWORD *)lock_desc.lpSurface)[3] = 0xffffffff;
+ break;
+
+ case 2:
+ ((WORD *)lock_desc.lpSurface)[0] = (c ? c - 1 : 0) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[1] = c << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[2] = min(c + 1, tests[t].max) << tests[t].shift;
+ ((WORD *)lock_desc.lpSurface)[3] = 0xffff;
+ break;
+ }
+ hr = IDirectDrawSurface7_Unlock(src, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+ hr = IDirectDrawSurface7_Blt(texture, NULL, src, NULL, DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ ckey.dwColorSpaceLowValue = c << tests[t].shift;
+ ckey.dwColorSpaceHighValue = c << tests[t].shift;
+ hr = IDirectDrawSurface7_SetColorKey(src, DDCKEY_SRCBLT, &ckey);
+ ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+ hr = IDirectDrawSurface7_Blt(dst, NULL, src, NULL, DDBLT_KEYSRC | DDBLT_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to blit, hr %#x.\n", hr);
+
+ /* Don't make this read only, it somehow breaks the detection of the Nvidia bug below. */
+ hr = IDirectDrawSurface7_Lock(dst, NULL, &lock_desc, DDLOCK_WAIT, NULL);
+ ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
+ switch (tests[t].bpp)
+ {
+ case 4:
+ data[0] = ((DWORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((DWORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((DWORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((DWORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+
+ case 2:
+ data[0] = ((WORD *)lock_desc.lpSurface)[0] & color_mask;
+ data[1] = ((WORD *)lock_desc.lpSurface)[1] & color_mask;
+ data[2] = ((WORD *)lock_desc.lpSurface)[2] & color_mask;
+ data[3] = ((WORD *)lock_desc.lpSurface)[3] & color_mask;
+ break;
+ }
+ hr = IDirectDrawSurface7_Unlock(dst, 0);
+ ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
+
+ if (!c)
+ {
+ ok(data[0] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[0], tests[t].name, c);
+
+ if (data[3] == tests[t].clear)
+ {
+ /* My Geforce GTX 460 on Windows 7 misbehaves when A4R4G4B4 is blitted with color
+ * keying: The blit takes ~0.5 seconds, and subsequent color keying draws are broken,
+ * even when a different surface is used. The blit itself doesn't draw anything,
+ * so we can detect the bug by looking at the otherwise unused 4th texel. It should
+ * never be masked out by the key.
+ *
+ * Also appears to affect the testbot in some way with R5G6B5. Color keying is
+ * terrible on WARP. */
+ skip("Nvidia A4R4G4B4 color keying blit bug detected, skipping.\n");
+ IDirectDrawSurface7_Release(texture);
+ IDirectDrawSurface7_Release(src);
+ IDirectDrawSurface7_Release(dst);
+ goto done;
+ }
+ }
+ else
+ ok(data[0] == (c - 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c - 1) << tests[t].shift, data[0], tests[t].name, c);
+
+ ok(data[1] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[1], tests[t].name, c);
+
+ if (c == tests[t].max)
+ ok(data[2] == tests[t].clear, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ tests[t].clear, data[2], tests[t].name, c);
+ else
+ ok(data[2] == (c + 1) << tests[t].shift, "Expected surface content %#x, got %#x, format %s, c=%u.\n",
+ (c + 1) << tests[t].shift, data[2], tests[t].name, c);
+
+ hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
+ ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+
+ hr = IDirect3DDevice7_BeginScene(device);
+ ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
+ ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+ hr = IDirect3DDevice7_EndScene(device);
+ ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+ color = get_surface_color(rt, 80, 240);
+ if (!c)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 240, 240);
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ color = get_surface_color(rt, 400, 240);
+ if (c == tests[t].max)
+ ok(compare_color(color, 0x0000ff00, 1) || broken(warp && compare_color(color, 0x00000000, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+ else
+ ok(compare_color(color, 0x00000000, 1) || broken(warp && compare_color(color, 0x0000ff00, 1)),
+ "Got unexpected color 0x%08x, format %s, c=%u.\n",
+ color, tests[t].name, c);
+
+ IDirectDrawSurface7_Release(texture);
+ }
+ IDirectDrawSurface7_Release(src);
+ IDirectDrawSurface7_Release(dst);
+ }
+done:
+
+ IDirectDrawSurface7_Release(rt);
+ IDirectDraw7_Release(ddraw);
+ refcount = IDirect3DDevice7_Release(device);
+ ok(!refcount, "Device has %u references left.\n", refcount);
+ DestroyWindow(window);
+}
+
START_TEST(ddraw7)
{
HMODULE module = GetModuleHandleA("ddraw.dll");
@@ -9834,4 +10135,5 @@ START_TEST(ddraw7)
test_signed_formats();
test_color_fill();
test_texcoordindex();
+ test_colorkey_precision();
}
--
2.4.6
More information about the wine-patches
mailing list