[dx55] Mixture of patches

Ann and Jason Edmeades us at the-edmeades.demon.co.uk
Wed Jun 11 13:50:00 CDT 2003


Changelog

Fix the texture operations to resolve glitches shown in UT2003 when get
quad damage. 
checkGLcall must not supply a \n as that is supplied by its expansion
Performance fixes to save applying the same states 6 times and to reduce
function calls when accessing front/back buffers
Make traces more readable by more constants -> english descriptions

Jason
Note: This applies to cvs + dx53try2 + dx54 patches
-------------- next part --------------
diff -u3 dlls/d3d8/cvsplus54b/d3d8_private.h dlls/d3d8/d3d8_private.h
--- dlls/d3d8/cvsplus54b/d3d8_private.h	2003-06-11 20:35:55.000000000 +0100
+++ dlls/d3d8/d3d8_private.h	2003-06-11 20:26:57.000000000 +0100
@@ -1283,6 +1283,8 @@
 const char* debug_d3dressourcetype(D3DRESOURCETYPE res);
 const char* debug_d3dprimitivetype(D3DPRIMITIVETYPE PrimitiveType);
 const char* debug_d3dpool(D3DPOOL Pool);
+const char *debug_d3drenderstate(DWORD State);
+const char *debug_d3dtexturestate(DWORD State);
 
 /* Some #defines for additional diagnostics */
 #if 0 /* NOTE: Must be 0 in cvs */
diff -u3 dlls/d3d8/cvsplus54b/device.c dlls/d3d8/device.c
--- dlls/d3d8/cvsplus54b/device.c	2003-06-11 20:35:55.000000000 +0100
+++ dlls/d3d8/device.c	2003-06-08 20:53:41.000000000 +0100
@@ -83,7 +83,20 @@
 
     TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
     for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
-        IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
+
+        /* Performance: For texture states where multiples effect the outcome, only bother
+              applying the last one as it will pick up all the other values                */
+        switch (i) {
+        case D3DTSS_COLORARG0:  /* Will be picked up when setting color op */
+        case D3DTSS_COLORARG1:  /* Will be picked up when setting color op */
+        case D3DTSS_COLORARG2:  /* Will be picked up when setting color op */
+        case D3DTSS_ALPHAARG0:  /* Will be picked up when setting alpha op */
+        case D3DTSS_ALPHAARG1:  /* Will be picked up when setting alpha op */
+        case D3DTSS_ALPHAARG2:  /* Will be picked up when setting alpha op */
+           break;
+        default:
+           IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
+        }
     }
 
     /* Note the D3DRS value applies to all textures, but GL has one
@@ -1883,7 +1896,7 @@
     ICOM_THIS(IDirect3DDevice8Impl,iface);
     DWORD OldValue = This->StateBlock->renderstate[State];
         
-    TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
+    TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
     This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
     This->UpdateStateBlock->Set.renderstate[State] = TRUE;
     This->UpdateStateBlock->renderstate[State] = Value;
@@ -2237,7 +2250,7 @@
 		} else {
 		  TRACE("Specular colors cannot be enabled in this version of opengl\n");
 		}
-                checkGLcall("glEnable(GL_COLOR_SUM)\n");
+                checkGLcall("glEnable(GL_COLOR_SUM)");
               } else {
                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
 
@@ -2251,7 +2264,7 @@
 		} else {
 		  TRACE("Specular colors cannot be disabled in this version of opengl\n");
 		}
-                checkGLcall("glDisable(GL_COLOR_SUM)\n");
+                checkGLcall("glDisable(GL_COLOR_SUM)");
 	      }
         }
         break;
@@ -2380,10 +2393,10 @@
         {
             if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
                glEnable(GL_FOG);
-               checkGLcall("glEnable GL_FOG\n");
+               checkGLcall("glEnable GL_FOG");
             } else {
                glDisable(GL_FOG);
-               checkGLcall("glDisable GL_FOG\n");
+               checkGLcall("glDisable GL_FOG");
             }
         }
         break;
@@ -2467,7 +2480,7 @@
 
             if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
                 glEnable(GL_COLOR_MATERIAL);
-                checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
+                checkGLcall("glEnable GL_COLOR_MATERIAL");
 
                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
                       This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
@@ -2493,16 +2506,16 @@
 
                 if (Parm == -1) {
                     glDisable(GL_COLOR_MATERIAL);
-                    checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
+                    checkGLcall("glDisable GL_COLOR_MATERIAL");
                 } else {
                     TRACE("glColorMaterial Parm=%d\n", Parm);
                     glColorMaterial(GL_FRONT_AND_BACK, Parm);
-                    checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
+                    checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
                 }
 
             } else {
                 glDisable(GL_COLOR_MATERIAL);
-                checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
+                checkGLcall("glDisable GL_COLOR_MATERIAL");
             }
         }
         break; 
@@ -2514,12 +2527,12 @@
 
             if (pattern->wRepeatFactor) {
                 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
-                checkGLcall("glLineStipple(repeat, linepattern)\n");
+                checkGLcall("glLineStipple(repeat, linepattern)");
                 glEnable(GL_LINE_STIPPLE);
-                checkGLcall("glEnable(GL_LINE_STIPPLE);\n");
+                checkGLcall("glEnable(GL_LINE_STIPPLE);");
             } else {
                 glDisable(GL_LINE_STIPPLE);
-                checkGLcall("glDisable(GL_LINE_STIPPLE);\n");
+                checkGLcall("glDisable(GL_LINE_STIPPLE);");
             }
         }
         break;
@@ -2560,13 +2573,13 @@
     case D3DRS_POINTSIZE                 :
         TRACE("Set point size to %f\n", *((float*)&Value));
         glPointSize(*((float*)&Value));
-        checkGLcall("glPointSize(...);\n");
+        checkGLcall("glPointSize(...);");
         break;
 
     case D3DRS_POINTSIZE_MIN             :
         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
 	  GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
-	  checkGLcall("glPointParameterfEXT(...);\n");
+	  checkGLcall("glPointParameterfEXT(...);");
 	} else {
 	  FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
 	}
@@ -2575,7 +2588,7 @@
     case D3DRS_POINTSIZE_MAX             :
         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
 	  GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
-	  checkGLcall("glPointParameterfEXT(...);\n");
+	  checkGLcall("glPointParameterfEXT(...);");
 	} else {
 	  FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
 	}
@@ -2595,7 +2608,7 @@
 
 		if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
-		  checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
+		  checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
 		} else {
 		  TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
 		}
@@ -2603,7 +2616,7 @@
                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
 		if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
 		  GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
-		  checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
+		  checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
 		} else {
 		  TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
 		}
@@ -2621,7 +2634,7 @@
                     Value & D3DCOLORWRITEENABLE_GREEN,
 		    Value & D3DCOLORWRITEENABLE_BLUE, 
                     Value & D3DCOLORWRITEENABLE_ALPHA);
-        checkGLcall("glColorMask(...)\n");
+        checkGLcall("glColorMask(...)");
 		break;
 
         /* Unhandled yet...! */
@@ -2853,7 +2866,7 @@
 
     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
    
-    TRACE("(%p) : stub, Stage=%ld, Type=%d, Value=%ld\n", This, Stage, Type, Value);
+    TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
 
     /* Reject invalid texture units */
     if (Stage >= GL_LIMITS(textures)) {
diff -u3 dlls/d3d8/cvsplus54b/surface.c dlls/d3d8/surface.c
--- dlls/d3d8/cvsplus54b/surface.c	2003-06-11 20:35:55.000000000 +0100
+++ dlls/d3d8/surface.c	2003-06-08 20:20:12.000000000 +0100
@@ -193,13 +193,15 @@
 
 	{
 	  long j;
+          GLenum format = D3DFmt2GLFmt(This->Device, This->myDesc.Format);
+          GLenum type   = D3DFmt2GLType(This->Device, This->myDesc.Format);
 	  for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
 	    glReadPixels(This->lockedRect.left, 
 			 This->lockedRect.bottom - j - 1, 
 			 This->lockedRect.right - This->lockedRect.left, 
 			 1,
-			 D3DFmt2GLFmt(This->Device, This->myDesc.Format), 
-                         D3DFmt2GLType(This->Device, This->myDesc.Format), 
+			 format, 
+                         type, 
                          (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
 	    vcheckGLcall("glReadPixels");
 	  }
diff -u3 dlls/d3d8/cvsplus54b/utils.c dlls/d3d8/utils.c
--- dlls/d3d8/cvsplus54b/utils.c	2003-06-11 20:35:55.000000000 +0100
+++ dlls/d3d8/utils.c	2003-06-11 19:40:43.000000000 +0100
@@ -165,6 +165,133 @@
   }
 }
 
+const char* debug_d3drenderstate(DWORD state) {
+  switch (state) {
+#define D3DSTATE_TO_STR(u) case u: return #u
+    D3DSTATE_TO_STR(D3DRS_ZENABLE                   );
+    D3DSTATE_TO_STR(D3DRS_FILLMODE                  );
+    D3DSTATE_TO_STR(D3DRS_SHADEMODE                 );
+    D3DSTATE_TO_STR(D3DRS_LINEPATTERN               );
+    D3DSTATE_TO_STR(D3DRS_ZWRITEENABLE              );
+    D3DSTATE_TO_STR(D3DRS_ALPHATESTENABLE           );
+    D3DSTATE_TO_STR(D3DRS_LASTPIXEL                 );
+    D3DSTATE_TO_STR(D3DRS_SRCBLEND                  );
+    D3DSTATE_TO_STR(D3DRS_DESTBLEND                 );
+    D3DSTATE_TO_STR(D3DRS_CULLMODE                  );
+    D3DSTATE_TO_STR(D3DRS_ZFUNC                     );
+    D3DSTATE_TO_STR(D3DRS_ALPHAREF                  );
+    D3DSTATE_TO_STR(D3DRS_ALPHAFUNC                 );
+    D3DSTATE_TO_STR(D3DRS_DITHERENABLE              );
+    D3DSTATE_TO_STR(D3DRS_ALPHABLENDENABLE          );
+    D3DSTATE_TO_STR(D3DRS_FOGENABLE                 );
+    D3DSTATE_TO_STR(D3DRS_SPECULARENABLE            );
+    D3DSTATE_TO_STR(D3DRS_ZVISIBLE                  );
+    D3DSTATE_TO_STR(D3DRS_FOGCOLOR                  );
+    D3DSTATE_TO_STR(D3DRS_FOGTABLEMODE              );
+    D3DSTATE_TO_STR(D3DRS_FOGSTART                  );
+    D3DSTATE_TO_STR(D3DRS_FOGEND                    );
+    D3DSTATE_TO_STR(D3DRS_FOGDENSITY                );
+    D3DSTATE_TO_STR(D3DRS_EDGEANTIALIAS             );
+    D3DSTATE_TO_STR(D3DRS_ZBIAS                     );
+    D3DSTATE_TO_STR(D3DRS_RANGEFOGENABLE            );
+    D3DSTATE_TO_STR(D3DRS_STENCILENABLE             );
+    D3DSTATE_TO_STR(D3DRS_STENCILFAIL               );
+    D3DSTATE_TO_STR(D3DRS_STENCILZFAIL              );
+    D3DSTATE_TO_STR(D3DRS_STENCILPASS               );
+    D3DSTATE_TO_STR(D3DRS_STENCILFUNC               );
+    D3DSTATE_TO_STR(D3DRS_STENCILREF                );
+    D3DSTATE_TO_STR(D3DRS_STENCILMASK               );
+    D3DSTATE_TO_STR(D3DRS_STENCILWRITEMASK          );
+    D3DSTATE_TO_STR(D3DRS_TEXTUREFACTOR             );
+    D3DSTATE_TO_STR(D3DRS_WRAP0                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP1                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP2                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP3                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP4                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP5                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP6                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP7                     );
+    D3DSTATE_TO_STR(D3DRS_CLIPPING                  );
+    D3DSTATE_TO_STR(D3DRS_LIGHTING                  );
+    D3DSTATE_TO_STR(D3DRS_AMBIENT                   );
+    D3DSTATE_TO_STR(D3DRS_FOGVERTEXMODE             );
+    D3DSTATE_TO_STR(D3DRS_COLORVERTEX               );
+    D3DSTATE_TO_STR(D3DRS_LOCALVIEWER               );
+    D3DSTATE_TO_STR(D3DRS_NORMALIZENORMALS          );
+    D3DSTATE_TO_STR(D3DRS_DIFFUSEMATERIALSOURCE     );
+    D3DSTATE_TO_STR(D3DRS_SPECULARMATERIALSOURCE    );
+    D3DSTATE_TO_STR(D3DRS_AMBIENTMATERIALSOURCE     );
+    D3DSTATE_TO_STR(D3DRS_EMISSIVEMATERIALSOURCE    );
+    D3DSTATE_TO_STR(D3DRS_VERTEXBLEND               );
+    D3DSTATE_TO_STR(D3DRS_CLIPPLANEENABLE           );
+    D3DSTATE_TO_STR(D3DRS_SOFTWAREVERTEXPROCESSING  );
+    D3DSTATE_TO_STR(D3DRS_POINTSIZE                 );
+    D3DSTATE_TO_STR(D3DRS_POINTSIZE_MIN             );
+    D3DSTATE_TO_STR(D3DRS_POINTSPRITEENABLE         );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALEENABLE          );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALE_A              );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALE_B              );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALE_C              );
+    D3DSTATE_TO_STR(D3DRS_MULTISAMPLEANTIALIAS      );
+    D3DSTATE_TO_STR(D3DRS_MULTISAMPLEMASK           );
+    D3DSTATE_TO_STR(D3DRS_PATCHEDGESTYLE            );
+    D3DSTATE_TO_STR(D3DRS_PATCHSEGMENTS             );
+    D3DSTATE_TO_STR(D3DRS_DEBUGMONITORTOKEN         );
+    D3DSTATE_TO_STR(D3DRS_POINTSIZE_MAX             );
+    D3DSTATE_TO_STR(D3DRS_INDEXEDVERTEXBLENDENABLE  );
+    D3DSTATE_TO_STR(D3DRS_COLORWRITEENABLE          );
+    D3DSTATE_TO_STR(D3DRS_TWEENFACTOR               );
+    D3DSTATE_TO_STR(D3DRS_BLENDOP                   );
+    D3DSTATE_TO_STR(D3DRS_POSITIONORDER             );
+    D3DSTATE_TO_STR(D3DRS_NORMALORDER               );
+#undef D3DSTATE_TO_STR
+  default:
+    FIXME("Unrecognized %lu render state!\n", state);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dtexturestate(DWORD state) {
+  switch (state) {
+#define D3DSTATE_TO_STR(u) case u: return #u
+    D3DSTATE_TO_STR(D3DTSS_COLOROP               );
+    D3DSTATE_TO_STR(D3DTSS_COLORARG1             );
+    D3DSTATE_TO_STR(D3DTSS_COLORARG2             );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAOP               );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAARG1             );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAARG2             );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT00          );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT01          );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT10          );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT11          );
+    D3DSTATE_TO_STR(D3DTSS_TEXCOORDINDEX         );
+    D3DSTATE_TO_STR(D3DTSS_ADDRESSU              );
+    D3DSTATE_TO_STR(D3DTSS_ADDRESSV              );
+    D3DSTATE_TO_STR(D3DTSS_BORDERCOLOR           );
+    D3DSTATE_TO_STR(D3DTSS_MAGFILTER             );
+    D3DSTATE_TO_STR(D3DTSS_MINFILTER             );
+    D3DSTATE_TO_STR(D3DTSS_MIPFILTER             );
+    D3DSTATE_TO_STR(D3DTSS_MIPMAPLODBIAS         );
+    D3DSTATE_TO_STR(D3DTSS_MAXMIPLEVEL           );
+    D3DSTATE_TO_STR(D3DTSS_MAXANISOTROPY         );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVLSCALE         );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVLOFFSET        );
+    D3DSTATE_TO_STR(D3DTSS_TEXTURETRANSFORMFLAGS );
+    D3DSTATE_TO_STR(D3DTSS_ADDRESSW              );
+    D3DSTATE_TO_STR(D3DTSS_COLORARG0             );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAARG0             );
+    D3DSTATE_TO_STR(D3DTSS_RESULTARG             );
+#undef D3DSTATE_TO_STR
+  case 12:
+    /* Note D3DTSS are not consecutive, so skip these */
+    return "unused";
+    break;
+  default:
+    FIXME("Unrecognized %lu texture state!\n", state);
+    return "unrecognized";
+  }
+}
+
 /*
  * Simple utility routines used for dx -> gl mapping of byte formats
  */
@@ -564,6 +691,17 @@
         TRACE("Alpha?(%d), Stage:%d Op(%d), a1(%ld), a2(%ld), a3(%ld)\n", isAlpha, Stage, op, arg1, arg2, arg3);
         if (op == D3DTOP_DISABLE) return;
 
+        /* Note: Operations usually involve two ars, src0 and src1 and are operations of
+           the form (a1 <operation> a2). However, some of the more complex operations
+           take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added  
+           in a third parameter called a0. Therefore these are operations of the form
+           a0 <operation> a1 <operation> a2, ie the new parameter goes to the front.
+           
+           However, below we treat the new (a0) parameter as src2/opr2, so in the actual
+           functions below, expect their syntax to differ slightly to those listed in the
+           manuals, ie replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
+           This affects D3DTOP_MULTIPLYADD and D3DTOP_LERP                               */
+           
 	if (isAlpha) {
 		comb_target = useext(GL_COMBINE_ALPHA);
 		src0_target = useext(GL_SOURCE0_ALPHA);
@@ -589,7 +727,7 @@
            The default argument is D3DTA_TEXTURE. If no texture is set for this stage, 
                    then the default argument is D3DTA_DIFFUSE.
                    FIXME? If texture added/removed, may need to reset back as well?    */
-        if (isAlpha && Stage==0 && This->StateBlock->textures[Stage] == NULL && arg1 == D3DTA_TEXTURE) {
+        if (isAlpha && This->StateBlock->textures[Stage] == NULL && arg1 == D3DTA_TEXTURE) {
             GetSrcAndOpFromValue(D3DTA_DIFFUSE, isAlpha, &src1, &opr1);  
         } else {
             GetSrcAndOpFromValue(arg1, isAlpha, &src1, &opr1);
@@ -817,17 +955,17 @@
 	case D3DTOP_LERP:
 		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
 		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
-		glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
 		checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
-		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
 		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
-		glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
 		checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
-		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
 		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
-		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
 		checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
-		glTexEnvi(GL_TEXTURE_ENV, opr2_target, src1);
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, src3);
 		checkGLcall("GL_TEXTURE_ENV, opr2_target, src1");
 		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
 		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
@@ -835,43 +973,95 @@
 	default:
 		Handled = FALSE;
 	}
+
         if (Handled) {
+            BOOL  combineOK = TRUE;
 #if defined(GL_NV_texture_env_combine4)
+            DWORD op2;
+
+            if (isAlpha) {
+                op2 = This->UpdateStateBlock->texture_state[Stage][D3DTSS_COLOROP];
+            } else {
+                op2 = This->UpdateStateBlock->texture_state[Stage][D3DTSS_ALPHAOP];
+            }
+
            /* Note: If COMBINE4 in effect cant go back to combine! */
-           if (isAlpha) {
-               switch (This->UpdateStateBlock->texture_state[Stage][D3DTSS_COLOROP])
-               {
-               case D3DTOP_ADDSMOOTH:
-               case D3DTOP_BLENDTEXTUREALPHAPM:
-               case D3DTOP_MODULATEALPHA_ADDCOLOR:
-               case D3DTOP_MODULATECOLOR_ADDALPHA:
-               case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
-               case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
-               case D3DTOP_MULTIPLYADD:
-                   FIXME("Cant have COMBINE4 and COMBINE in efferct together, alphaop=%d\n", op);
+           switch (op2)
+           {
+           case D3DTOP_ADDSMOOTH:
+           case D3DTOP_BLENDTEXTUREALPHAPM:
+           case D3DTOP_MODULATEALPHA_ADDCOLOR:
+           case D3DTOP_MODULATECOLOR_ADDALPHA:
+           case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
+           case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
+           case D3DTOP_MULTIPLYADD:
+               /* Ignore those implemented in both cases */
+               switch (op) {
+               case D3DTOP_SELECTARG1:
+               case D3DTOP_SELECTARG2:
+                   combineOK = FALSE;
+                   Handled   = FALSE;
+                   break;
+               default:
+                   FIXME("Cant have COMBINE4 and COMBINE in efferct together, thisop=%d, otherop=%ld, isAlpha(%d)\n", 
+                              op, op2, isAlpha);
                    return;
                }
            }
 #endif
-	   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
-	   checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
-	   return;
+
+           if (combineOK == TRUE) {
+	       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
+	       checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
+	       return;
+           }
         }
 
         /* Other texture operations require special extensions: */
 #if defined(GL_NV_texture_env_combine4)
 	if (isAlpha) {
+                opr = GL_SRC_ALPHA;
 		invopr = GL_ONE_MINUS_SRC_ALPHA;
 		src3_target = GL_SOURCE3_ALPHA_NV;
 		opr3_target = GL_OPERAND3_ALPHA_NV;
 	}
 	else {
+                opr = GL_SRC_COLOR;
 		invopr = GL_ONE_MINUS_SRC_COLOR;
 		src3_target = GL_SOURCE3_RGB_NV;
 		opr3_target = GL_OPERAND3_RGB_NV;
 	}
         Handled = TRUE; /* Again, assume handled */
 	switch (op) {
+        case D3DTOP_SELECTARG1:                                          /* = a1 * 1 + 0 * 0 */
+        case D3DTOP_SELECTARG2:                                          /* = a2 * 1 + 0 * 0 */
+                glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                if (op == D3DTOP_SELECTARG1) {
+                    glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);                
+                    checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                    glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);        
+                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");  
+                } else {
+                    glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);                
+                    checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
+                    glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);        
+                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");  
+                }
+                glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);             
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);              
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");  
+                glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);             
+                checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
+                glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");  
+                glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);             
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");  
+                break;
+
 	case D3DTOP_ADDSMOOTH:
 		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
 		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
@@ -1037,21 +1227,21 @@
 	case D3DTOP_MULTIPLYADD:
 		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
 		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
-		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
 		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
-		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
 		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
 		glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
 		checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
 		glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
 		checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
-		glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
 		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
-		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
 		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
-		glTexEnvi(GL_TEXTURE_ENV, src3_target, src3);
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
 		checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
-		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr3);
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
 		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
 		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
 		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");


More information about the wine-patches mailing list