From 8b8e30b1e1a697c07a8c4ca34d4376fcb024e2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 15 Feb 2007 03:03:05 +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 bfee172ddc0..a84b08f9246 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 792a01457c5..5948f3e8eb5 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 03247dbef16..093af9e2de9 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 cd020079f43..1ef038359a5 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) { - keylow = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue; - keyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue; + /* Destination color keys are taken from the source surface ! */ + destkeylow = Src->DestBltCKey.dwColorSpaceLowValue; + destkeyhigh = Src->DestBltCKey.dwColorSpaceHighValue; } + else if (Flags & DDBLT_KEYDESTOVERRIDE) + { + 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;