diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 135d6e9..e2cd23a 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -2534,10 +2534,9 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, { case D3DTBLEND_MODULATE: IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG1, WINED3DTA_TEXTURE); - IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE); IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLORARG2, WINED3DTA_CURRENT); IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_COLOROP, WINED3DTOP_MODULATE); - IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1); + IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0, WINED3DTSS_ALPHAOP, WINED3DTOP_DX6MODULATE); break; case D3DTBLEND_MODULATEALPHA: diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 59ff3d4..9f11f73 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -351,6 +351,12 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend); glBlendFunc(srcBlend, dstBlend); checkGLcall("glBlendFunc"); + + /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state, + so it may need updating */ + if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) { + StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); + } } static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { @@ -1932,6 +1938,24 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2]; arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0]; + if (op == WINED3DTOP_DX6MODULATE) { + IWineD3DSurfaceImpl *surf = NULL; + + if (stage > 0) ERR("unexpected WINED3DTOP_DX6MODULATE at stage > 0\n"); + + if (stateblock->textures[0]) + surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0]; + + if (surf && getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask) { + op = WINED3DTOP_SELECTARG1; + arg1 = WINED3DTA_TEXTURE; + } + else { + op = WINED3DTOP_SELECTARG1; + arg1 = WINED3DTA_CURRENT; + } + } + if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0] && (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) { @@ -1945,13 +1969,29 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D * cannot remove the texture's alpha channel entirely. * * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work - * on color keyed surfaces. + * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to + * draw things like translucent text and perform other blending effects. * * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing */ - if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1; - if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE; - else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE; + if(op == WINED3DTOP_DISABLE) { + arg1 = WINED3DTA_TEXTURE; + op = WINED3DTOP_SELECTARG1; + } + else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { + arg2 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg1 = WINED3DTA_TEXTURE; + } + else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) { + if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { + arg1 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg2 = WINED3DTA_TEXTURE; + } } } @@ -2432,6 +2472,11 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]); checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])"); } + + if (sampler == 0 && (stateblock->textureState[0][WINED3DTSS_ALPHAOP] == WINED3DTOP_DX6MODULATE)) { + /* fixup in tex_alphaop may depend on currently set stage 0 texture */ + StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); + } } static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { diff --git a/include/wine/wined3d_types.h b/include/wine/wined3d_types.h index 477df24..fa9a6e8 100644 --- a/include/wine/wined3d_types.h +++ b/include/wine/wined3d_types.h @@ -758,6 +758,7 @@ typedef enum _WINED3DTEXTUREOP { WINED3DTOP_DOTPRODUCT3 = 24, WINED3DTOP_MULTIPLYADD = 25, WINED3DTOP_LERP = 26, + WINED3DTOP_DX6MODULATE = 50, WINED3DTOP_FORCE_DWORD = 0x7fffffff, } WINED3DTEXTUREOP;