[PATCH 3/3] ddraw: Return the right error if range color keys are used.

Stefan Dösinger stefan at codeweavers.com
Sun Aug 23 14:59:35 CDT 2015


This is part of my efforts to fix bug 38581, and also an attempt to find
out how range color keys work now that we have the necessary
infrastructure on the GL side.

Turns out they don't work at all, at least on most GPUs. There is some
evidence online in the form of DxCapsViewer dumps that suggest they work
on i810 and some SiS GPUs. I don't have access to any of those.
---
 dlls/ddraw/surface.c      |  30 ++++++++++--
 dlls/ddraw/tests/ddraw1.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw2.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw4.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw7.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/cs.c         |   4 +-
 dlls/wined3d/texture.c    |  10 +---
 include/wine/wined3d.h    |   1 -
 8 files changed, 497 insertions(+), 16 deletions(-)

diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 77a3d44..4e815aa 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -4641,15 +4641,21 @@ static HRESULT ddraw_surface_set_color_key(struct ddraw_surface *surface, DWORD
     DDCOLORKEY fixed_color_key;
     HRESULT hr = WINED3D_OK;
 
+    if (flags & DDCKEY_COLORSPACE)
+    {
+        if (color_key && color_key->dwColorSpaceLowValue != color_key->dwColorSpaceHighValue)
+        {
+            WARN("Range color keys are not supported, returning DDERR_NOCOLORKEYHW.\n");
+            return DDERR_NOCOLORKEYHW;
+        }
+        flags &= ~DDCKEY_COLORSPACE;
+    }
+
     wined3d_mutex_lock();
 
     if (color_key)
     {
-        fixed_color_key = *color_key;
-        /* Handle case where dwColorSpaceHighValue < dwColorSpaceLowValue */
-        if (fixed_color_key.dwColorSpaceHighValue < fixed_color_key.dwColorSpaceLowValue)
-            fixed_color_key.dwColorSpaceHighValue = fixed_color_key.dwColorSpaceLowValue;
-
+        fixed_color_key.dwColorSpaceLowValue = fixed_color_key.dwColorSpaceHighValue = color_key->dwColorSpaceLowValue;
         switch (flags & ~DDCKEY_COLORSPACE)
         {
             case DDCKEY_DESTBLT:
@@ -6027,6 +6033,20 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
         }
     }
 
+    if (((desc->dwFlags & DDSD_CKDESTOVERLAY)
+            && desc->u3.ddckCKDestOverlay.dwColorSpaceLowValue != desc->u3.ddckCKDestOverlay.dwColorSpaceHighValue)
+            || ((desc->dwFlags & DDSD_CKDESTBLT)
+            && desc->ddckCKDestBlt.dwColorSpaceLowValue != desc->ddckCKDestBlt.dwColorSpaceHighValue)
+            || ((desc->dwFlags & DDSD_CKSRCOVERLAY)
+            && desc->ddckCKSrcOverlay.dwColorSpaceLowValue != desc->ddckCKSrcOverlay.dwColorSpaceHighValue)
+            || ((desc->dwFlags & DDSD_CKSRCBLT)
+            && desc->ddckCKSrcBlt.dwColorSpaceLowValue != desc->ddckCKSrcBlt.dwColorSpaceHighValue))
+    {
+        WARN("Range color keys not supported, returning DDERR_NOCOLORKEYHW.\n");
+        HeapFree(GetProcessHeap(), 0, texture);
+        return DDERR_NOCOLORKEYHW;
+    }
+
     if (desc->ddsCaps.dwCaps & (DDSCAPS_OVERLAY))
         wined3d_desc.usage |= WINED3DUSAGE_OVERLAY;
 
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 676d357..b52bf48 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -7613,6 +7613,122 @@ done:
     DestroyWindow(window);
 }
 
+static void test_range_colorkey(void)
+{
+    IDirectDraw *ddraw;
+    HWND window;
+    HRESULT hr;
+    IDirectDrawSurface *surface;
+    DDSURFACEDESC surface_desc;
+    ULONG refcount;
+    DDCOLORKEY ckey;
+
+    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");
+    hr = IDirectDraw_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+    surface_desc.dwWidth = 1;
+    surface_desc.dwHeight = 1;
+    surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
+
+    /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Same for DDSCAPS_OFFSCREENPLAIN. */
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    /* Range destination keys don't work either. */
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Just to show it's not because of A, R, and G having equal values. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x01010101;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* None of these operations modified the key. */
+    hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    IDirectDrawSurface_Release(surface),
+    refcount = IDirectDraw_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw1)
 {
     IDirectDraw *ddraw;
@@ -7683,4 +7799,5 @@ START_TEST(ddraw1)
     test_viewport_clear_rect();
     test_color_fill();
     test_colorkey_precision();
+    test_range_colorkey();
 }
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index d1f94fc..67a0e1e 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -8742,6 +8742,122 @@ done:
     DestroyWindow(window);
 }
 
+static void test_range_colorkey(void)
+{
+    IDirectDraw2 *ddraw;
+    HWND window;
+    HRESULT hr;
+    IDirectDrawSurface *surface;
+    DDSURFACEDESC surface_desc;
+    ULONG refcount;
+    DDCOLORKEY ckey;
+
+    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");
+    hr = IDirectDraw2_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+    surface_desc.dwWidth = 1;
+    surface_desc.dwHeight = 1;
+    surface_desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(surface_desc.ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(surface_desc.ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(surface_desc.ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(surface_desc.ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    U5(surface_desc.ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
+
+    /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Same for DDSCAPS_OFFSCREENPLAIN. */
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw2_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    /* Range destination keys don't work either. */
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Just to show it's not because of A, R, and G having equal values. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x01010101;
+    hr = IDirectDrawSurface_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* None of these operations modified the key. */
+    hr = IDirectDrawSurface_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    IDirectDrawSurface_Release(surface),
+    refcount = IDirectDraw2_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw2)
 {
     IDirectDraw2 *ddraw;
@@ -8819,4 +8935,5 @@ START_TEST(ddraw2)
     test_viewport_clear_rect();
     test_color_fill();
     test_colorkey_precision();
+    test_range_colorkey();
 }
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 85c632c..eed5f334 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -9872,6 +9872,122 @@ static void test_colorkey_precision(void)
     DestroyWindow(window);
 }
 
+static void test_range_colorkey(void)
+{
+    IDirectDraw4 *ddraw;
+    HWND window;
+    HRESULT hr;
+    IDirectDrawSurface4 *surface;
+    DDSURFACEDESC2 surface_desc;
+    ULONG refcount;
+    DDCOLORKEY ckey;
+
+    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");
+    hr = IDirectDraw4_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+    surface_desc.dwWidth = 1;
+    surface_desc.dwHeight = 1;
+    U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
+
+    /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Same for DDSCAPS_OFFSCREENPLAIN. */
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw4_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    /* Range destination keys don't work either. */
+    hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Just to show it's not because of A, R, and G having equal values. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x01010101;
+    hr = IDirectDrawSurface4_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* None of these operations modified the key. */
+    hr = IDirectDrawSurface4_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    IDirectDrawSurface4_Release(surface),
+    refcount = IDirectDraw4_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw4)
 {
     IDirectDraw4 *ddraw;
@@ -9956,4 +10072,5 @@ START_TEST(ddraw4)
     test_color_fill();
     test_texcoordindex();
     test_colorkey_precision();
+    test_range_colorkey();
 }
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 30213c5..fc119f6 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -10041,6 +10041,122 @@ done:
     DestroyWindow(window);
 }
 
+static void test_range_colorkey(void)
+{
+    IDirectDraw7 *ddraw;
+    HWND window;
+    HRESULT hr;
+    IDirectDrawSurface7 *surface;
+    DDSURFACEDESC2 surface_desc;
+    ULONG refcount;
+    DDCOLORKEY ckey;
+
+    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");
+    hr = IDirectDraw7_SetCooperativeLevel(ddraw, window, DDSCL_NORMAL);
+    ok(SUCCEEDED(hr), "Failed to set cooperative level, hr %#x.\n", hr);
+
+    memset(&surface_desc, 0, sizeof(surface_desc));
+    surface_desc.dwSize = sizeof(surface_desc);
+    surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT;
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+    surface_desc.dwWidth = 1;
+    surface_desc.dwHeight = 1;
+    U4(surface_desc).ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(U4(surface_desc).ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(U4(surface_desc).ddpfPixelFormat).dwRBitMask = 0x00ff0000;
+    U3(U4(surface_desc).ddpfPixelFormat).dwGBitMask = 0x0000ff00;
+    U4(U4(surface_desc).ddpfPixelFormat).dwBBitMask = 0x000000ff;
+    U5(U4(surface_desc).ddpfPixelFormat).dwRGBAlphaBitMask = 0x00000000;
+
+    /* Creating a surface with a range color key fails with DDERR_NOCOLORKEY. */
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Same for DDSCAPS_OFFSCREENPLAIN. */
+    surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000001;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00000000;
+    surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &surface, NULL);
+    ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
+
+    /* Setting a range color key without DDCKEY_COLORSPACE collapses the key. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(ckey.dwColorSpaceLowValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(ckey.dwColorSpaceHighValue == 0x00000001, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    /* DDCKEY_COLORSPACE is ignored if the key is a single value. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(SUCCEEDED(hr), "Failed to set color key, hr %#x.\n", hr);
+
+    /* Using it with a range key results in DDERR_NOCOLORKEYHW. */
+    ckey.dwColorSpaceLowValue = 0x00000001;
+    ckey.dwColorSpaceHighValue = 0x00000000;
+    hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x00000001;
+    hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+    /* Range destination keys don't work either. */
+    hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_DESTBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* Just to show it's not because of A, R, and G having equal values. */
+    ckey.dwColorSpaceLowValue = 0x00000000;
+    ckey.dwColorSpaceHighValue = 0x01010101;
+    hr = IDirectDrawSurface7_SetColorKey(surface, DDCKEY_SRCBLT | DDCKEY_COLORSPACE, &ckey);
+    ok(hr == DDERR_NOCOLORKEYHW, "Got unexpected hr %#x.\n", hr);
+
+    /* None of these operations modified the key. */
+    hr = IDirectDrawSurface7_GetColorKey(surface, DDCKEY_SRCBLT, &ckey);
+    ok(SUCCEEDED(hr), "Failed to get color key, hr %#x.\n", hr);
+    ok(!ckey.dwColorSpaceLowValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceLowValue);
+    ok(!ckey.dwColorSpaceHighValue, "Got unexpected value 0x%08x.\n", ckey.dwColorSpaceHighValue);
+
+    IDirectDrawSurface7_Release(surface),
+    refcount = IDirectDraw7_Release(ddraw);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw7)
 {
     HMODULE module = GetModuleHandleA("ddraw.dll");
@@ -10136,4 +10252,5 @@ START_TEST(ddraw7)
     test_color_fill();
     test_texcoordindex();
     test_colorkey_precision();
+    test_range_colorkey();
 }
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 459fd56..3c4ea8c 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -903,7 +903,7 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat
 
     if (op->set)
     {
-        switch (op->flags & ~WINED3D_CKEY_COLORSPACE)
+        switch (op->flags)
         {
             case WINED3D_CKEY_DST_BLT:
                 texture->async.dst_blt_color_key = op->color_key;
@@ -935,7 +935,7 @@ static void wined3d_cs_exec_set_color_key(struct wined3d_cs *cs, const void *dat
     }
     else
     {
-        switch (op->flags & ~WINED3D_CKEY_COLORSPACE)
+        switch (op->flags)
         {
             case WINED3D_CKEY_DST_BLT:
                 texture->async.color_key_flags &= ~WINED3D_CKEY_DST_BLT;
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 27e0ecd..b369809 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -570,8 +570,8 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
         DWORD flags, const struct wined3d_color_key *color_key)
 {
     struct wined3d_device *device = texture->resource.device;
-    static const DWORD all_flags = WINED3D_CKEY_COLORSPACE | WINED3D_CKEY_DST_BLT
-            | WINED3D_CKEY_DST_OVERLAY | WINED3D_CKEY_SRC_BLT | WINED3D_CKEY_SRC_OVERLAY;
+    static const DWORD all_flags = WINED3D_CKEY_DST_BLT | WINED3D_CKEY_DST_OVERLAY
+            | WINED3D_CKEY_SRC_BLT | WINED3D_CKEY_SRC_OVERLAY;
 
     TRACE("texture %p, flags %#x, color_key %p.\n", texture, flags, color_key);
 
@@ -581,12 +581,6 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
         return WINED3DERR_INVALIDCALL;
     }
 
-    if (flags & WINED3D_CKEY_COLORSPACE)
-    {
-        FIXME("Unhandled flags %#x.\n", flags);
-        return WINED3DERR_INVALIDCALL;
-    }
-
     wined3d_cs_emit_set_color_key(device->cs, texture, flags, color_key);
 
     return WINED3D_OK;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 1d840ed..a07c9ef 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1252,7 +1252,6 @@ enum wined3d_display_rotation
 
 #define WINED3D_RESZ_CODE                                       0x7fa05000
 
-#define WINED3D_CKEY_COLORSPACE                                 0x00000001
 #define WINED3D_CKEY_DST_BLT                                    0x00000002
 #define WINED3D_CKEY_DST_OVERLAY                                0x00000004
 #define WINED3D_CKEY_SRC_BLT                                    0x00000008
-- 
2.4.6




More information about the wine-patches mailing list