Hi.

I found some problems with D3DRENDERSTATE_TEXTUREMAPBLEND state =
D3DTBLEND_MODULATE in ddraw and handling the alpha channel. This old state is
currently mapped to texture stage states, with alpha part done as

IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0,
WINED3DTSS_ALPHAARG1, WINED3DTA_TEXTURE);
IWineD3DDevice_SetTextureStageState(This->wineD3DDevice, 0,
WINED3DTSS_ALPHAOP, WINED3DTOP_SELECTARG1);

This isn't correct, I believe, because in some cases it should be taken from
diffuse color (Aliens vs Predator 1 depends on it). But the latter behavior
isn't correct in all cases either.

I found this description of this state on some random website via google:

"D3DTBLEND_MODULATE Modulate texture-blending is supported. In this mode, the
RGB values of the texture are multiplied with the RGB values that would have
been used with no texturing. Any alpha values in the texture replace the alpha
values that would have been used with no texturing."

http://www.hi.is/~snorri/SDK-docs/x/exten203.htm

I guess, this means that it either takes alpha from texture or from diffuse
color, depending on whether the current texture has alpha channel (which takes
priority). I've submitted a test for this to wine-patches that includes checks
with both kinds of textures. It passes on XP and thus supports that this is the
way it is supposed to happen. Unfortunately, this doesn't easily translate to
available texture stage states. So it looks like something more hacky is needed
to make it work correctly in all cases in wine. There are two approaches I can
think of:

1) introduce an internal D3DTOP_ value in wined3d that will map to texture alpha
or diffuse alpha, depending on the pixel format of the currently selected 
texture.

2) move D3DRENDERSTATE_TEXTUREMAPBLEND handling to wined3d;

So it would be nice if Stefan Dösinger or maybe somebody else of d3d devs gave
me some directions - which approach (if any) is ok and acceptable for wine
project. I'll attach a diff with my current hacks that show how 1st approach is
about to look.

BTW, this worked in wine around 0.9.15

http://source.winehq.org/git/wine.git/?a=blob;f=dlls/ddraw/opengl_utils.c;h=a2b021985acfe3fbae888cb0e954b8fb47c86db3;hb=0fa7170dc318a6624f960c49e459cb521d2ae999

There it wasn't mapping to texture stage states, but instead was using such 
call:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

From what I read about GL_MODULATE, I'm not sure it always does exactly the
thing TEXTUREMAPBLEND=MODULATE is supposed to do, but with Aliens vs Predator it
worked better.

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;




Reply via email to