[6/10] DDraw, WineD3D: Color keying tests and fixes

Stefan Dösinger stefan at codeweavers.com
Wed Feb 14 20:03:05 CST 2007


-------------- next part --------------
From 7a0e2073a9b1fc09738738a0e68e2b21a7203800 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Tue, 13 Feb 2007 16:11:09 +0100
Subject: [PATCH] DDraw, WineD3D: Color keying tests and fixes

---
 dlls/ddraw/surface.c        |   18 +++
 dlls/ddraw/tests/dsurface.c |  323 +++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/surface.c      |   59 ++++----
 dlls/wined3d/surface_gdi.c  |   35 +++--
 4 files changed, 394 insertions(+), 41 deletions(-)

diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index bfee172..a84b08f 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -696,6 +696,24 @@ IDirectDrawSurfaceImpl_Blt(IDirectDrawSurface7 *iface,
     IDirectDrawSurfaceImpl *Src = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, SrcSurface);
     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
 
+    /* Check for validity of the flags here. WineD3D Has the software-opengl selection path and would have
+     * to check at 2 places, and sometimes do double checks. This also saves the call to wined3d :-)
+     */
+    if((Flags & DDBLT_KEYSRCOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYSRC)) {
+        WARN("Invalid source color key parameters, returning DDERR_INVALIDPARAMS\n");
+        return DDERR_INVALIDPARAMS;
+    }
+
+    if((Flags & DDBLT_KEYDESTOVERRIDE) && (!DDBltFx || Flags & DDBLT_KEYDEST)) {
+        WARN("Invalid destination color key parameters, returning DDERR_INVALIDPARAMS\n");
+        return DDERR_INVALIDPARAMS;
+    }
+
+    if(Flags & DDBLT_KEYSRC && (!Src || !(Src->surface_desc.dwFlags & DDSD_CKSRCBLT))) {
+        WARN("DDBLT_KEYDEST blit without color key in surface, returning DDERR_INVALIDPARAMS\n");
+        return DDERR_INVALIDPARAMS;
+    }
+
     return IWineD3DSurface_Blt(This->WineD3DSurface,
                                DestRect,
                                Src ? Src->WineD3DSurface : NULL,
diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c
index 792a014..5948f3e 100644
--- a/dlls/ddraw/tests/dsurface.c
+++ b/dlls/ddraw/tests/dsurface.c
@@ -170,6 +170,7 @@ static void SrcColorKey32BlitTest(void)
     DDCOLORKEY DDColorKey;
     LPDWORD lpData;
     HRESULT rc;
+    DDBLTFX fx;
 
     ddsd2.dwSize = sizeof(ddsd2);
     ddsd2.ddpfPixelFormat.dwSize = sizeof(ddsd2.ddpfPixelFormat);
@@ -247,6 +248,328 @@ static void SrcColorKey32BlitTest(void)
 
     IDirectDrawSurface_Release(lpSrc);
     IDirectDrawSurface_Release(lpDst);
+
+    /* start with a new set of surfaces to test the color keying parameters to blit */
+    memset(&ddsd, 0, sizeof(ddsd));
+    ddsd.dwSize = sizeof(ddsd);
+    ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
+    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
+    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+    ddsd.dwWidth = 800;
+    ddsd.dwHeight = 600;
+    ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
+    U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
+    U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
+    ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0xFF0000;
+    ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0xFF0000;
+    ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x00FF00;
+    ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x00FF00;
+    rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDst, NULL);
+    ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
+    if(FAILED(rc))
+    {
+        skip("Failed to create surface\n");
+        return;
+    }
+
+    /* start with a new set of surfaces to test the color keying parameters to blit */
+    memset(&ddsd, 0, sizeof(ddsd));
+    ddsd.dwSize = sizeof(ddsd);
+    ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
+    ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CKSRCBLT | DDSD_CKDESTBLT;
+    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+    ddsd.dwWidth = 800;
+    ddsd.dwHeight = 600;
+    ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    U1(ddsd.ddpfPixelFormat).dwRGBBitCount = 32;
+    U2(ddsd.ddpfPixelFormat).dwRBitMask = 0xFF0000;
+    U3(ddsd.ddpfPixelFormat).dwGBitMask = 0x00FF00;
+    U4(ddsd.ddpfPixelFormat).dwBBitMask = 0x0000FF;
+    ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = 0x0000FF;
+    ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0x0000FF;
+    ddsd.ddckCKDestBlt.dwColorSpaceLowValue = 0x000000;
+    ddsd.ddckCKDestBlt.dwColorSpaceHighValue = 0x000000;
+    rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL);
+    ok(rc==DD_OK || rc == DDERR_NOCOLORKEYHW,"CreateSurface returned: %x\n",rc);
+    if(FAILED(rc))
+    {
+        skip("Failed to create surface\n");
+        IDirectDrawSurface_Release(lpDst);
+        return;
+    }
+
+    memset(&fx, 0, sizeof(fx));
+    fx.dwSize = sizeof(fx);
+    fx.ddckSrcColorkey.dwColorSpaceHighValue = 0x110000;
+    fx.ddckSrcColorkey.dwColorSpaceLowValue = 0x110000;
+    fx.ddckDestColorkey.dwColorSpaceHighValue = 0x001100;
+    fx.ddckDestColorkey.dwColorSpaceLowValue = 0x001100;
+
+    rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+    lpData[0] = 0x000000FF; /* Applies to src blt key in src surface */
+    lpData[1] = 0x00000000; /* Applies to dst blt key in src surface */
+    lpData[2] = 0x00FF0000; /* Dst color key in dst surface */
+    lpData[3] = 0x0000FF00; /* Src color key in dst surface */
+    lpData[4] = 0x00001100; /* Src color key in ddbltfx */
+    lpData[5] = 0x00110000; /* Dst color key in ddbltfx */
+    rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+    lpData[0] = 0x55555555;
+    lpData[1] = 0x55555555;
+    lpData[2] = 0x55555555;
+    lpData[3] = 0x55555555;
+    lpData[4] = 0x55555555;
+    lpData[5] = 0x55555555;
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Test a blit without keying */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, 0, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+    /* Should have copied src data unmodified to dst */
+    ok(lpData[0] == 0x000000FF &&
+       lpData[1] == 0x00000000 &&
+       lpData[2] == 0x00FF0000 &&
+       lpData[3] == 0x0000FF00 &&
+       lpData[4] == 0x00001100 &&
+       lpData[5] == 0x00110000, "Surface data after unkeyed blit does not match\n");
+
+    lpData[0] = 0x55555555;
+    lpData[1] = 0x55555555;
+    lpData[2] = 0x55555555;
+    lpData[3] = 0x55555555;
+    lpData[4] = 0x55555555;
+    lpData[5] = 0x55555555;
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Src key */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+
+    ok(lpData[0] == 0x55555555 && /* Here the src key applied */
+       lpData[1] == 0x00000000 &&
+       lpData[2] == 0x00FF0000 &&
+       lpData[3] == 0x0000FF00 &&
+       lpData[4] == 0x00001100 &&
+       lpData[5] == 0x00110000, "Surface data after srckey blit does not match\n");
+
+    lpData[0] = 0x55555555;
+    lpData[1] = 0x55555555;
+    lpData[2] = 0x55555555;
+    lpData[3] = 0x55555555;
+    lpData[4] = 0x55555555;
+    lpData[5] = 0x55555555;
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Src override */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+
+    ok(lpData[0] == 0x000000FF &&
+       lpData[1] == 0x00000000 &&
+       lpData[2] == 0x00FF0000 &&
+       lpData[3] == 0x0000FF00 &&
+       lpData[4] == 0x00001100 &&
+       lpData[5] == 0x55555555, /* Override key applies here */
+       "Surface data after src override key blit does not match\n");
+
+    lpData[0] = 0x55555555;
+    lpData[1] = 0x55555555;
+    lpData[2] = 0x55555555;
+    lpData[3] = 0x55555555;
+    lpData[4] = 0x55555555;
+    lpData[5] = 0x55555555;
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Src override AND src key. That is not supposed to work */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &fx);
+    ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    /* Verify that the destination is unchanged */
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+
+    ok(lpData[0] == 0x55555555 &&
+       lpData[1] == 0x55555555 &&
+       lpData[2] == 0x55555555 &&
+       lpData[3] == 0x55555555 &&
+       lpData[4] == 0x55555555 &&
+       lpData[5] == 0x55555555, /* Override key applies here */
+       "Surface data after src key blit with override does not match\n");
+
+    lpData[0] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[1] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[2] = 0x00001100; /* Dest key in override */
+    lpData[3] = 0x00001100; /* Dest key in override */
+    lpData[4] = 0x00000000; /* Dest key in src surface */
+    lpData[5] = 0x00000000; /* Dest key in src surface */
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Dest key blit */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+
+    /* DirectDraw uses the dest blit key from the SOURCE surface ! */
+    ok(lpData[0] == 0x00ff0000 &&
+       lpData[1] == 0x00ff0000 &&
+       lpData[2] == 0x00001100 &&
+       lpData[3] == 0x00001100 &&
+       lpData[4] == 0x00001100 && /* Key applies here */
+       lpData[5] == 0x00110000,   /* Key applies here */
+       "Surface data after dest key blit does not match\n");
+
+    lpData[0] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[1] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[2] = 0x00001100; /* Dest key in override */
+    lpData[3] = 0x00001100; /* Dest key in override */
+    lpData[4] = 0x00000000; /* Dest key in src surface */
+    lpData[5] = 0x00000000; /* Dest key in src surface */
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Dest override key blit */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+
+    ok(lpData[0] == 0x00FF0000 &&
+       lpData[1] == 0x00FF0000 &&
+       lpData[2] == 0x00FF0000 && /* Key applies here */
+       lpData[3] == 0x0000FF00 && /* Key applies here */
+       lpData[4] == 0x00000000 &&
+       lpData[5] == 0x00000000,
+       "Surface data after dest key override blit does not match\n");
+
+    lpData[0] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[1] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[2] = 0x00001100; /* Dest key in override */
+    lpData[3] = 0x00001100; /* Dest key in override */
+    lpData[4] = 0x00000000; /* Dest key in src surface */
+    lpData[5] = 0x00000000; /* Dest key in src surface */
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Dest override key blit. Supposed to fail too */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE, &fx);
+    ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    /* Check for unchanged data */
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+
+    ok(lpData[0] == 0x00FF0000 &&
+       lpData[1] == 0x00FF0000 &&
+       lpData[2] == 0x00001100 && /* Key applies here */
+       lpData[3] == 0x00001100 && /* Key applies here */
+       lpData[4] == 0x00000000 &&
+       lpData[5] == 0x00000000,
+       "Surface data with dest key and dest override does not match\n");
+
+    lpData[0] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[1] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[2] = 0x00001100; /* Dest key in override */
+    lpData[3] = 0x00001100; /* Dest key in override */
+    lpData[4] = 0x00000000; /* Dest key in src surface */
+    lpData[5] = 0x00000000; /* Dest key in src surface */
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Modify the source data a bit to give some more conclusive results */
+    rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+    lpData[5] = 0x000000FF; /* Applies to src blt key in src surface */
+    rc = IDirectDrawSurface_Unlock(lpSrc, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Source and destination key */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST | DDBLT_KEYSRC, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL);
+    ok(rc==DD_OK,"Lock returned: %x\n",rc);
+    lpData = (LPDWORD)ddsd2.lpSurface;
+
+    ok(lpData[0] == 0x00FF0000 && /* Masked by Destination key */
+       lpData[1] == 0x00FF0000 && /* Masked by Destination key */
+       lpData[2] == 0x00001100 && /* Masked by Destination key */
+       lpData[3] == 0x00001100 && /* Masked by Destination key */
+       lpData[4] == 0x00001100 && /* Allowed by destination key, not masked by source key */
+       lpData[5] == 0x00000000,   /* Allowed by dst key, but masked by source key */
+       "Surface data with src key and dest key blit does not match\n");
+
+    lpData[0] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[1] = 0x00FF0000; /* Dest key in dst surface */
+    lpData[2] = 0x00001100; /* Dest key in override */
+    lpData[3] = 0x00001100; /* Dest key in override */
+    lpData[4] = 0x00000000; /* Dest key in src surface */
+    lpData[5] = 0x00000000; /* Dest key in src surface */
+    rc = IDirectDrawSurface_Unlock(lpDst, NULL);
+    ok(rc==DD_OK,"Unlock returned: %x\n",rc);
+
+    /* Override keys without ddbltfx parameter fail */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, NULL);
+    ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, NULL);
+    ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    /* Try blitting without keys in the source surface*/
+    rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_SRCBLT, NULL);
+    ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
+    rc = IDirectDrawSurface_SetColorKey(lpSrc, DDCKEY_DESTBLT, NULL);
+    ok(rc == DD_OK, "SetColorKey returned %x\n", rc);
+
+    /* That fails now. Do not bother to check that the data is unmodified */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRC, &fx);
+    ok(rc == DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    /* Dest key blit still works. Which key is used this time??? */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDEST, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    /* With korrectly passed override keys no key in the surface is needed.
+     * Again, the result was checked before, no need to do that again
+     */
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYDESTOVERRIDE, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+    rc = IDirectDrawSurface_Blt(lpDst, NULL, lpSrc, NULL, DDBLT_KEYSRCOVERRIDE, &fx);
+    ok(rc == DD_OK, "IDirectDrawSurface_Blt returned %08x\n", rc);
+
+    IDirectDrawSurface_Release(lpSrc);
+    IDirectDrawSurface_Release(lpDst);
 }
 
 static void QueryInterface(void)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 03247db..093af9e 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -2362,6 +2362,13 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
         return WINED3DERR_INVALIDCALL;
     }
 
+    /* No destination color keying supported */
+    if(Flags & (DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE)) {
+        /* Can we support that with glBlendFunc if blitting to the frame buffer? */
+        TRACE("Destination color key not supported in accelerated Blit, falling back to software\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
     if (DestRect) {
         rect.x1 = DestRect->left;
         rect.y1 = DestRect->top;
@@ -2442,6 +2449,12 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
         WINED3DRECT srect;
         BOOL upsideDown, stretchx;
 
+        if(Flags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE)) {
+            TRACE("Color keying not supported by frame buffer to texture blit\n");
+            return WINED3DERR_INVALIDCALL;
+            /* Destination color key is checked above */
+        }
+
         /* Call preload for the surface to make sure it isn't dirty */
         IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
 
@@ -2514,8 +2527,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
     } else if(Src) {
         /* Blit from offscreen surface to render target */
         float glTexCoord[4];
-        DWORD oldCKey;
-        DDCOLORKEY oldBltCKey = {0,0};
+        DWORD oldCKeyFlags = Src->CKeyFlags;
+        DDCOLORKEY oldBltCKey = This->SrcBltCKey;
         RECT SourceRectangle;
         GLint oldDraw;
 
@@ -2543,26 +2556,22 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
 
         /* Color keying: Check if we have to do a color keyed blt,
          * and if not check if a color key is activated.
+         *
+         * Just modify the color keying parameters in the surface and restore them afterwards
+         * The surface keeps track of the color key last used to load the opengl surface.
+         * PreLoad will catch the change to the flags and color key and reload if neccessary.
          */
-        oldCKey = Src->CKeyFlags;
-        if(!(Flags & DDBLT_KEYSRC) &&
-            Src->CKeyFlags & DDSD_CKSRCBLT) {
-            /* Ok, the surface has a color key, but we shall not use it -
-             * Deactivate it for now, LoadTexture will catch this
-             */
+        if(Flags & DDBLT_KEYSRC) {
+            /* Use color key from surface */
+        } else if(Flags & DDBLT_KEYSRCOVERRIDE) {
+            /* Use color key from DDBltFx */
+            Src->CKeyFlags |= DDSD_CKSRCBLT;
+            This->SrcBltCKey = DDBltFx->ddckSrcColorkey;
+        } else {
+            /* Do not use color key */
             Src->CKeyFlags &= ~DDSD_CKSRCBLT;
         }
 
-        /* Color keying */
-        if(Flags & DDBLT_KEYDEST) {
-            oldBltCKey = This->SrcBltCKey;
-            /* Temporary replace the source color key with the destination one. We do this because the color conversion code which
-             * is in the end called from LoadTexture works with the source color. At the end of this function we restore the color key.
-             */
-            This->SrcBltCKey = This->DestBltCKey;
-        } else if (Flags & DDBLT_KEYSRC)
-            oldBltCKey = This->SrcBltCKey;
-
         /* Now load the surface */
         IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
 
@@ -2595,7 +2604,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
         checkGLcall("glTexEnvi");
 
         /* This is for color keying */
-        if(Flags & DDBLT_KEYSRC) {
+        if(Flags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE)) {
             glEnable(GL_ALPHA_TEST);
             checkGLcall("glEnable GL_ALPHA_TEST");
             glAlphaFunc(GL_NOTEQUAL, 0.0);
@@ -2637,15 +2646,9 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
         if(This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer && oldDraw == GL_BACK) {
             glDrawBuffer(oldDraw);
         }
-
-        /* Restore the color key flags */
-        if(oldCKey != Src->CKeyFlags) {
-            Src->CKeyFlags = oldCKey;
-        }
-
-        /* Restore the old color key */
-        if (Flags & (DDBLT_KEYSRC | DDBLT_KEYDEST))
-            This->SrcBltCKey = oldBltCKey;
+        /* Restore the color key parameters */
+        Src->CKeyFlags = oldCKeyFlags;
+        This->SrcBltCKey = oldBltCKey;
 
         LEAVE_GL();
 
diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c
index 34d6bff..803d182 100644
--- a/dlls/wined3d/surface_gdi.c
+++ b/dlls/wined3d/surface_gdi.c
@@ -911,29 +911,33 @@ IWineGDISurfaceImpl_Blt(IWineD3DSurface *iface,
         {
           LONG dstyinc = dlock.Pitch, dstxinc = bpp;
           DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF;
+          DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF;
           if (Flags & (DDBLT_KEYSRC | DDBLT_KEYDEST | DDBLT_KEYSRCOVERRIDE | DDBLT_KEYDESTOVERRIDE))
           {
-
+              /* The color keying flags are checked for correctness in ddraw */
               if (Flags & DDBLT_KEYSRC)
               {
                 keylow  = Src->SrcBltCKey.dwColorSpaceLowValue;
                 keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
               }
-              else if (Flags & DDBLT_KEYDEST)
-              {
-                keylow  = This->DestBltCKey.dwColorSpaceLowValue;
-                keyhigh = This->DestBltCKey.dwColorSpaceHighValue;
-              }
-              else if (Flags & DDBLT_KEYSRCOVERRIDE)
+              else  if (Flags & DDBLT_KEYSRCOVERRIDE)
               {
                 keylow  = DDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
                 keyhigh = DDBltFx->ddckSrcColorkey.dwColorSpaceHighValue;
               }
-              else
+
+              if (Flags & DDBLT_KEYDEST)
+              {
+                /* Destination color keys are taken from the source surface ! */
+                destkeylow  = Src->DestBltCKey.dwColorSpaceLowValue;
+                destkeyhigh = Src->DestBltCKey.dwColorSpaceHighValue;
+              }
+              else if (Flags & DDBLT_KEYDESTOVERRIDE)
               {
-                keylow  = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
-                keyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue;
+                destkeylow  = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
+                destkeyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue;
               }
+
               if(bpp == 1)
               {
                   keymask = 0xff;
@@ -1037,7 +1041,10 @@ IWineGDISurfaceImpl_Blt(IWineD3DSurface *iface,
               dx = d; \
               for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
                   tmp = s[sx >> 16]; \
-                  if ((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) dx[0] = tmp; \
+                  if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
+                      ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
+                       dx[0] = tmp; \
+                     } \
                   dx = (type*)(((LPBYTE)dx)+dstxinc); \
               } \
               d = (type*)(((LPBYTE)d)+dstyinc); \
@@ -1057,10 +1064,12 @@ IWineGDISurfaceImpl_Blt(IWineD3DSurface *iface,
                     dx = d;
                     for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
                     {
-                        DWORD pixel;
+                        DWORD pixel, dpixel = 0;
                         s = sbuf+3*(sx>>16);
                         pixel = s[0]|(s[1]<<8)|(s[2]<<16);
-                        if ((pixel & keymask) < keylow || (pixel & keymask) > keyhigh)
+                        dpixel = dx[0]|(dx[1]<<8)|(dx[2]<<16);
+                        if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) &&
+                            ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh))
                         {
                             dx[0] = (pixel    )&0xff;
                             dx[1] = (pixel>> 8)&0xff;
-- 
1.4.4.3



More information about the wine-patches mailing list