[dx44] texture ops

Ann and Jason Edmeades us at the-edmeades.demon.co.uk
Sat May 31 08:49:38 CDT 2003


This adds a lot more texture ops support, using some code and
algorithums from Lucho. Its not perfect and contains a temporary 'hack'
for the fact that combine and combine4_nv cannot be used at the same
time (one for alpha, one for color). We can address that soon, but this
patch improves some of the textures in ut2003

Changelog

Add support for a lot of the remaining texture ops, move code into the
utils module, and clean up the main code path.

Jason
(Raphael: FYI This is the exact patch I sent you previously.)
-------------- next part --------------
--- dlls/d3d8/device.dx43	2003-05-29 22:32:01.000000000 +0100
+++ dlls/d3d8/device.c	2003-05-29 22:33:05.000000000 +0100
@@ -996,71 +996,6 @@
     TRACE("glEnd\n");
 }
 
-/**
- * @nodoc: todo
- */
-void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand) 
-{
-  BOOL isAlphaReplicate = FALSE;
-  BOOL isComplement     = FALSE;
-  
-  *operand = GL_SRC_COLOR;
-  *source = GL_TEXTURE;
-  
-  /* Catch alpha replicate */
-  if (iValue & D3DTA_ALPHAREPLICATE) {
-    iValue = iValue & ~D3DTA_ALPHAREPLICATE;
-    isAlphaReplicate = TRUE;
-  }
-  
-  /* Catch Complement */
-  if (iValue & D3DTA_COMPLEMENT) {
-    iValue = iValue & ~D3DTA_COMPLEMENT;
-    isComplement = TRUE;
-  }
-  
-  /* Calculate the operand */
-  if (isAlphaReplicate && !isComplement) {
-    *operand = GL_SRC_ALPHA;
-  } else if (isAlphaReplicate && isComplement) {
-    *operand = GL_ONE_MINUS_SRC_ALPHA;
-  } else if (isComplement) {
-    if (isAlphaArg) {
-      *operand = GL_ONE_MINUS_SRC_ALPHA;
-    } else {
-      *operand = GL_ONE_MINUS_SRC_COLOR;
-    }
-  } else {
-    if (isAlphaArg) {
-      *operand = GL_SRC_ALPHA;
-    } else {
-      *operand = GL_SRC_COLOR;
-    }
-  }
-  
-  /* Calculate the source */
-  switch (iValue & D3DTA_SELECTMASK) {
-  case D3DTA_CURRENT:   *source  = GL_PREVIOUS_EXT;
-    break;
-  case D3DTA_DIFFUSE:   *source  = GL_PRIMARY_COLOR_EXT;
-    break;
-  case D3DTA_TEXTURE:   *source  = GL_TEXTURE;
-    break;
-  case D3DTA_TFACTOR:   *source  = GL_CONSTANT_EXT;
-    break;
-  case D3DTA_SPECULAR:
-    /**
-     * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
-     * isnt supported until base GL supports it
-     * There is no concept of temp registers as far as I can tell
-     */
-
-  default:
-    FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
-    *source = GL_TEXTURE;
-  }
-}
-
 /* Apply the current values to the specified texture stage */
 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
     ICOM_THIS(IDirect3DDevice8Impl,iface);
@@ -3884,63 +3819,22 @@
         }
         break;
 
-    case D3DTSS_COLORARG0             :
-    case D3DTSS_ALPHAARG0             :
-        /* FIXME: Mesa seems to struggle setting these at the moment */
-        /*FIXME("COLORARG0/ALPHAARG0 support still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);*/
-        /*break;*/
-
-    case D3DTSS_COLORARG1             :
-    case D3DTSS_COLORARG2             :
-    case D3DTSS_ALPHAARG1             :
-    case D3DTSS_ALPHAARG2             :
-        {
-            BOOL isAlphaArg = (Type == D3DTSS_ALPHAARG1 || Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
-            int  operand = GL_SRC_COLOR;
-            int  source = GL_TEXTURE;
-
-            GetSrcAndOpFromValue(Value, isAlphaArg, &source, &operand);
-            if (isAlphaArg) {
-
-                /* From MSDN (D3DTSS_ALPHAARG1) : 
-                   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 (Type == D3DTSS_ALPHAARG1 && This->StateBlock->textures[Stage] == NULL && Value == D3DTA_TEXTURE) {
-                    GetSrcAndOpFromValue(D3DTA_DIFFUSE, isAlphaArg, &source, &operand);  
-                }
-                TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_ALPHA_EXT(Type), source, OPERANDx_ALPHA_EXT(Type), operand);
-                glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT(Type), source);
-                vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_ALPHA_EXT, source);");
-                glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT(Type), operand);
-                vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_ALPHA_EXT, operand);");
-            } else {
-                TRACE("Source %x = %x, Operand %x = %x\n", SOURCEx_RGB_EXT(Type), source, OPERANDx_RGB_EXT(Type), operand);
-                glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT(Type), source);
-                vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, SOURCEx_RGB_EXT, source);");
-                glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT(Type), operand);
-                vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, OPERANDx_RGB_EXT, operand);");
-            }
-        }
-        break;
-
     case D3DTSS_ALPHAOP               :
     case D3DTSS_COLOROP               :
         {
 
-            int Scale = 1;
-            int Parm = (Type == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
-
-            if (Type == D3DTSS_COLOROP && Value == D3DTOP_DISABLE) {
+            if (Value == D3DTOP_DISABLE) {
                 /* TODO: Disable by making this and all later levels disabled */
-                glDisable(GL_TEXTURE_1D);
-                checkGLcall("Disable GL_TEXTURE_1D");
-                glDisable(GL_TEXTURE_2D);
-                checkGLcall("Disable GL_TEXTURE_2D");
-                glDisable(GL_TEXTURE_3D);
-                checkGLcall("Disable GL_TEXTURE_3D");
+                if (Type == D3DTSS_COLOROP) {
+                    glDisable(GL_TEXTURE_1D);
+                    checkGLcall("Disable GL_TEXTURE_1D");
+                    glDisable(GL_TEXTURE_2D);
+                    checkGLcall("Disable GL_TEXTURE_2D");
+                    glDisable(GL_TEXTURE_3D);
+                    checkGLcall("Disable GL_TEXTURE_3D");
+                }
+                break; /* Dont bother setting the texture operations */
             } else {
-
                 /* Enable only the appropriate texture dimension */
                 if (Type == D3DTSS_COLOROP) {
                     if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
@@ -3972,139 +3866,27 @@
                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
                     }
                 }
-
-                /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
-                if (Value != D3DTOP_DISABLE) {
-                    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
-                }
-
-                /* Now set up the operand correctly */
-                switch (Value) {
-                case D3DTOP_DISABLE                   :
-                    /* Contrary to the docs, alpha can be disabled when colorop is enabled
-                       and it works, so ignore this op */
-                    TRACE("Disable ALPHAOP but COLOROP enabled!\n");
-                    break;
-
-                case D3DTOP_SELECTARG1                :
-                    {
-                        glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
-                        checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
-                    }
-                    break;
-
-                case D3DTOP_SELECTARG2                :
-		    { 
-		        BOOL  isAlphaOp = (Type == D3DTSS_ALPHAOP);
-		        DWORD dwValue = 0;
-			GLenum source;
-			GLenum operand;
-		        /*FIXME("see if D3DTOP_SELECTARG2 behavior is correct now!\n");*/
-                        glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE);
-			checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_REPLACE)");
-			/* GL_REPLACE, swap args 0 and 1? */
-			dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG2 : D3DTSS_COLORARG2];
-			GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
-			if (isAlphaOp) {
-			  TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_ALPHA_EXT, source, GL_OPERAND0_ALPHA_EXT, operand);
-			  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, source);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, 'source')");
-			  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, operand);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, 'operand')");
-			} else {
-			  TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE0_RGB_EXT, source, GL_OPERAND0_RGB_EXT, operand);
-			  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, source);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, 'source')");
-			  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, operand);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, 'operand')");
-			}
-		        dwValue = This->StateBlock->texture_state[Stage][(isAlphaOp) ? D3DTSS_ALPHAARG1 : D3DTSS_COLORARG1];
-			GetSrcAndOpFromValue(dwValue, isAlphaOp, &source, &operand);
-			if (isAlphaOp) {
-			  TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_ALPHA_EXT, source, GL_OPERAND1_ALPHA_EXT, operand);
-			  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, source);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, 'source')");
-			  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, operand);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, 'operand')");
-			} else {
-			  TRACE("Source %x = %x, Operand %x = %x\n", GL_SOURCE1_RGB_EXT, source, GL_OPERAND1_RGB_EXT, operand);
-			  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, source);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, 'source')");
-			  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, operand);
-			  checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, 'operand')");
-			}
-		    }
-		    break;
-
-                case D3DTOP_MODULATE4X                : Scale = Scale * 2;  /* Drop through */
-                case D3DTOP_MODULATE2X                : Scale = Scale * 2;  /* Drop through */
-                case D3DTOP_MODULATE                  :
-
-                    /* Correct scale */
-                    if (Type == D3DTSS_ALPHAOP) {
-                        glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale);
-                        vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, Scale)");
-                    } else {
-                        glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale);
-                        vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, Scale)");
-                    }
-                    glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);
-                    checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_MODULATE);");
-                    break;
-
-                case D3DTOP_ADD                       :
-                    glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD);
-                    vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD)");
-                    break;
-
-                case D3DTOP_ADDSIGNED2X               : Scale = Scale * 2;  /* Drop through */
-                case D3DTOP_ADDSIGNED                 :
-                    glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT);
-                    vcheckGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_ADD_SIGNED_EXT)");
-                    break;
-
-                case D3DTOP_DOTPRODUCT3               :
-#if defined(GL_VERSION_1_3)
-                    if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
-                        glTexEnvi(GL_TEXTURE_ENV, Parm, GL_DOT3_RGBA);
-                        checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);");
-                        break;
-                    }
-#endif
-                    FIXME("DotProduct3 extension requested but not supported via this version of opengl\n");
-                    break;
-
-
-                case D3DTOP_SUBTRACT                  :
-#if defined(GL_VERSION_1_3)
-                    glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT);
-		    checkGLcall("glTexEnvi(GL_TEXTURE_ENV, Parm, GL_SUBTRACT)");
-		    break;
-#else
-		    /**
-		     * @TODO: to check:
-		     *  if ARB_texture_env_combine is supported
-		     *   we can use GL_SUBTRACT_ARB here
-		     */
-#endif
-
-                case D3DTOP_ADDSMOOTH                 :
-                case D3DTOP_BLENDDIFFUSEALPHA         :
-                case D3DTOP_BLENDTEXTUREALPHA         :
-                case D3DTOP_BLENDFACTORALPHA          :
-                case D3DTOP_BLENDTEXTUREALPHAPM       :
-                case D3DTOP_BLENDCURRENTALPHA         :
-                case D3DTOP_PREMODULATE               :
-                case D3DTOP_MODULATEALPHA_ADDCOLOR    :
-                case D3DTOP_MODULATECOLOR_ADDALPHA    :
-                case D3DTOP_MODULATEINVALPHA_ADDCOLOR :
-                case D3DTOP_MODULATEINVCOLOR_ADDALPHA :
-                case D3DTOP_BUMPENVMAP                :
-                case D3DTOP_BUMPENVMAPLUMINANCE       :
-                case D3DTOP_MULTIPLYADD               :
-                case D3DTOP_LERP                      :
-                default:
-                    FIXME("Unhandled texture operation %ld\n", Value);
+            }
+            /* Drop through... (Except disable case) */
+        case D3DTSS_COLORARG0             :
+        case D3DTSS_COLORARG1             :
+        case D3DTSS_COLORARG2             :
+        case D3DTSS_ALPHAARG0             :
+        case D3DTSS_ALPHAARG1             :
+        case D3DTSS_ALPHAARG2             :
+            {
+                BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 || 
+                                   Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
+                if (isAlphaArg) {
+                    set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
+                               This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1], 
+                               This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2], 
+                               This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
+                } else {
+                    set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
+                               This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1], 
+                               This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2], 
+                               This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
                 }
             }
             break;
--- dlls/d3d8/utils.dx43	2003-05-29 22:32:10.000000000 +0100
+++ dlls/d3d8/utils.c	2003-05-29 22:10:32.000000000 +0100
@@ -469,3 +469,617 @@
     }
 }
 
+/* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
+#if defined (GL_VERSION_1_3)
+  #define useext(A) A
+  #define combine_ext 1
+#elif defined (GL_EXT_texture_env_combine)
+  #define useext(A) A##_EXT
+  #define combine_ext 1
+#elif defined (GL_ARB_texture_env_combine)
+  #define useext(A) A##_ARB
+  #define combine_ext 1
+#else
+  #undef combine_ext
+#endif
+
+#if !defined(combine_ext)
+void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
+{ 
+        FIXME("Requires opengl combine extensions to work\n");
+        return;
+}
+#else
+/* Setup the texture operations texture stage states */
+void set_tex_op(LPDIRECT3DDEVICE8 iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
+{
+	GLenum src1, src2, src3;
+	GLenum opr1, opr2, opr3;
+	GLenum comb_target;
+	GLenum src0_target, src1_target, src2_target;
+	GLenum opr0_target, opr1_target, opr2_target;
+	GLenum scal_target;
+	GLenum opr=0, invopr, src3_target, opr3_target;
+        BOOL Handled = FALSE;
+        ICOM_THIS(IDirect3DDevice8Impl,iface);
+
+        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;
+
+	if (isAlpha) {
+		comb_target = useext(GL_COMBINE_ALPHA);
+		src0_target = useext(GL_SOURCE0_ALPHA);
+		src1_target = useext(GL_SOURCE1_ALPHA);
+		src2_target = useext(GL_SOURCE2_ALPHA);
+		opr0_target = useext(GL_OPERAND0_ALPHA);
+		opr1_target = useext(GL_OPERAND1_ALPHA);
+		opr2_target = useext(GL_OPERAND2_ALPHA);
+		scal_target = useext(GL_ALPHA_SCALE);
+	}
+	else {
+		comb_target = useext(GL_COMBINE_RGB);
+		src0_target = useext(GL_SOURCE0_RGB);
+		src1_target = useext(GL_SOURCE1_RGB);
+		src2_target = useext(GL_SOURCE2_RGB);
+		opr0_target = useext(GL_OPERAND0_RGB);
+		opr1_target = useext(GL_OPERAND1_RGB);
+		opr2_target = useext(GL_OPERAND2_RGB);
+		scal_target = useext(GL_RGB_SCALE);
+	}
+
+        /* From MSDN (D3DTSS_ALPHAARG1) : 
+           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) {
+            GetSrcAndOpFromValue(D3DTA_DIFFUSE, isAlpha, &src1, &opr1);  
+        } else {
+            GetSrcAndOpFromValue(arg1, isAlpha, &src1, &opr1);
+        }
+        GetSrcAndOpFromValue(arg2, isAlpha, &src2, &opr2);
+        GetSrcAndOpFromValue(arg3, isAlpha, &src3, &opr3);
+        
+        TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
+
+        Handled = TRUE; /* Assume will be handled */
+	switch (op) {
+	case D3DTOP_SELECTARG1:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_SELECTARG2:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+		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, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATE:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATE2X:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+		break;
+	case D3DTOP_MODULATE4X:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
+		break;
+	case D3DTOP_ADD:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_ADDSIGNED:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_ADDSIGNED2X:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+		break;
+        case D3DTOP_SUBTRACT:
+#if defined(GL_VERSION_1_3) || defined (GL_ARB_texture_env_combine)
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+#else
+                FIXME("This version of opengl does not support GL_SUBTRACT\n");
+#endif
+		break;
+	case D3DTOP_BLENDDIFFUSEALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDTEXTUREALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDFACTORALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_CONSTANT);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDCURRENTALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PREVIOUS);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+        case D3DTOP_DOTPRODUCT3: 
+#if defined(GL_EXT_texture_env_dot3) 
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
+#elif defined(GL_ARB_texture_env_dot3)
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
+#elif defined (GL_VERSION_1_3)
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA");
+#else
+                FIXME("This version of opengl does not support GL_DOT3\n");
+#endif
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	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);
+		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, src3);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	default:
+		Handled = FALSE;
+	}
+        if (Handled) {
+#if defined(GL_NV_texture_env_combine4)
+           /* 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);
+                   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;
+        }
+
+        /* Other texture operations require special extensions: */
+#if defined(GL_NV_texture_env_combine4)
+	if (isAlpha) {
+		invopr = GL_ONE_MINUS_SRC_ALPHA;
+		src3_target = GL_SOURCE3_ALPHA_NV;
+		opr3_target = GL_OPERAND3_ALPHA_NV;
+	}
+	else {
+		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_ADDSMOOTH:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		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");
+		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);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_COLOR; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_SRC_COLOR; break;
+		case GL_SRC_ALPHA: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_ALPHA: opr1 = GL_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDTEXTUREALPHAPM:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		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");
+		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);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATEALPHA_ADDCOLOR:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");  /* Add = a0*a1 + a2*a3 */
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);        /*   a0 = src1/opr1    */
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");    /*   a1 = 1 (see docs) */
+		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);        /*   a2 = arg2         */
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");     /*  a3 = src1 alpha   */
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
+                case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATECOLOR_ADDALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		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");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		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");
+		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);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+		case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+		case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	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);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		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);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src3);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr3);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+
+        default:
+                Handled = FALSE;
+        }
+        if (Handled) {
+	    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
+	    checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
+            return;
+        }
+#endif /* GL_NV_texture_env_combine4 */
+
+        /* After all the extensions, if still unhandled, report fixme */
+        FIXME("Unhandled texture operation %d\n", op);
+}
+#endif
+
+/**
+ * @nodoc: todo
+ */
+void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand) 
+{
+  BOOL isAlphaReplicate = FALSE;
+  BOOL isComplement     = FALSE;
+  
+  *operand = GL_SRC_COLOR;
+  *source = GL_TEXTURE;
+  
+  /* Catch alpha replicate */
+  if (iValue & D3DTA_ALPHAREPLICATE) {
+    iValue = iValue & ~D3DTA_ALPHAREPLICATE;
+    isAlphaReplicate = TRUE;
+  }
+  
+  /* Catch Complement */
+  if (iValue & D3DTA_COMPLEMENT) {
+    iValue = iValue & ~D3DTA_COMPLEMENT;
+    isComplement = TRUE;
+  }
+  
+  /* Calculate the operand */
+  if (isAlphaReplicate && !isComplement) {
+    *operand = GL_SRC_ALPHA;
+  } else if (isAlphaReplicate && isComplement) {
+    *operand = GL_ONE_MINUS_SRC_ALPHA;
+  } else if (isComplement) {
+    if (isAlphaArg) {
+      *operand = GL_ONE_MINUS_SRC_ALPHA;
+    } else {
+      *operand = GL_ONE_MINUS_SRC_COLOR;
+    }
+  } else {
+    if (isAlphaArg) {
+      *operand = GL_SRC_ALPHA;
+    } else {
+      *operand = GL_SRC_COLOR;
+    }
+  }
+  
+  /* Calculate the source */
+  switch (iValue & D3DTA_SELECTMASK) {
+  case D3DTA_CURRENT:   *source  = GL_PREVIOUS_EXT;
+    break;
+  case D3DTA_DIFFUSE:   *source  = GL_PRIMARY_COLOR_EXT;
+    break;
+  case D3DTA_TEXTURE:   *source  = GL_TEXTURE;
+    break;
+  case D3DTA_TFACTOR:   *source  = GL_CONSTANT_EXT;
+    break;
+  case D3DTA_SPECULAR:
+    /**
+     * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
+     * isnt supported until base GL supports it
+     * There is no concept of temp registers as far as I can tell
+     */
+
+  default:
+    FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
+    *source = GL_TEXTURE;
+  }
+}


More information about the wine-patches mailing list