[6/6] WINED3D: Use register combiners for texture stage operations

H. Verbeet hverbeet at gmail.com
Tue Jun 27 16:44:26 CDT 2006


This patch makes wined3d use register combiners for texture stage
operations. In order to do that the texture unit index needs to be
separated from the texture stage index. For cards that don't support
the NV_register_combiners extension nothing should change. This is a
somewhat larger patch, but obviously the texture indices should all be
changed at the same time.
-------------- next part --------------
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 44ad98a..087ba92 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -418,7 +418,7 @@ static void delete_glsl_shader_list(IWin
 
 
 /* Apply the current values to the specified texture stage */
-static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD Flags) {
+static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Sampler, DWORD texture_idx, DWORD Flags) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     float col[4];
 
@@ -438,7 +438,7 @@ static void WINAPI IWineD3DDeviceImpl_Se
     VTRACE(("Activating appropriate texture state %ld\n", Sampler));
     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
         ENTER_GL();
-        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + Sampler));
+        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
         checkGLcall("glActiveTextureARB");
         LEAVE_GL();
         /* Could we use bindTexture and then apply the states instead of GLACTIVETEXTURE */
@@ -3824,20 +3824,21 @@ static HRESULT WINAPI IWineD3DDeviceImpl
                 WARN("Unsupported in local OpenGL implementation: glBlendColor\n");
             }
 
-            /* And now the default texture color as well */
-            for (i = 0; i < GL_LIMITS(texture_stages); i++) {
+            if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+                /* And now the default texture color as well */
+                for (i = 0; i < GL_LIMITS(texture_stages); i++) {
+                    /* Note the D3DRS value applies to all textures, but GL has one
+                       per texture, so apply it now ready to be used!               */
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+                        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+                        checkGLcall("glActiveTextureARB");
+                    } else if (i>0) {
+                        FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+                    }
 
-                /* Note the D3DRS value applies to all textures, but GL has one
-                   per texture, so apply it now ready to be used!               */
-                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                    GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
-                    checkGLcall("glActiveTextureARB");
-                } else if (i>0) {
-                    FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+                    glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
+                    checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
                 }
-
-                glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
-                checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
             }
         }
         break;
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 0ccfec9..e7d225b 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -618,7 +618,9 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_
                 gl_info->ps_nv_version = PS_VERSION_11;
                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
             } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
-                TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support\n");
+                glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
+                gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
+                TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
                 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
             } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
                 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 157ec0f..616e042 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1024,6 +1024,7 @@ void loadNumberedArrays(
 
 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
     unsigned int textureNo   = 0;
+    unsigned int texture_idx = 0;
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     GLint curVBO = -1;
 
@@ -1313,7 +1314,7 @@ static void loadVertexData(IWineD3DDevic
 
     /* Texture coords -------------------------------------------*/
 
-    for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
+    for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
         /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
         /* Abort if we don't support the extension. */
         if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
@@ -1321,21 +1322,24 @@ static void loadVertexData(IWineD3DDevic
             continue;
         }
 
-        /* Select the correct texture stage */
-        GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
+        if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) {
+            /* Select the correct texture stage */
+            GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
+        }
+
         if (This->stateBlock->textures[textureNo] != NULL) {
             int coordIdx = This->stateBlock->textureState[textureNo][D3DTSS_TEXCOORDINDEX];
-            TRACE("Setting up texture %u, cordindx %u, data %p\n", textureNo, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
+            TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n", textureNo, texture_idx, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
 
             if (coordIdx >= MAX_TEXTURES) {
                 VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-                GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
+                GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
 
             } else if (sd->u.s.texCoords[coordIdx].lpData == NULL && sd->u.s.texCoords[coordIdx].VBO == 0) {
                 VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-                GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
+                GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + texture_idx, 0, 0, 0, 1));
 
             } else {
                 if(curVBO != sd->u.s.texCoords[coordIdx].VBO) {
@@ -1347,8 +1351,15 @@ static void loadVertexData(IWineD3DDevic
                 glTexCoordPointer(WINED3D_ATR_SIZE(texCoords[coordIdx]), WINED3D_ATR_GLTYPE(texCoords[coordIdx]), sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
             }
-
-        } else {
+        } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+            GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
+        }
+        if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
+    }
+    if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+        for (textureNo = texture_idx; textureNo < GL_LIMITS(textures); ++textureNo) {
+            GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo));
             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
             GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
         }
@@ -1399,6 +1410,7 @@ static void drawStridedSlow(IWineD3DDevi
                      const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
 
     unsigned int               textureNo    = 0;
+    unsigned int               texture_idx  = 0;
     const short               *pIdxBufS     = NULL;
     const long                *pIdxBufL     = NULL;
     LONG                       SkipnStrides = 0;
@@ -1509,7 +1521,7 @@ static void drawStridedSlow(IWineD3DDevi
         }
 
         /* Texture coords --------------------------- */
-        for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
+        for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
 
             if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
                 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
@@ -1581,7 +1593,7 @@ static void drawStridedSlow(IWineD3DDevi
                     case D3DTTFF_COUNT1:
                         VTRACE(("tex:%d, s=%f\n", textureNo, s));
                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord1fARB(textureNo, s));
+                            GL_EXTCALL(glMultiTexCoord1fARB(texture_idx, s));
                         } else {
                             glTexCoord1f(s);
                         }
@@ -1589,7 +1601,7 @@ static void drawStridedSlow(IWineD3DDevi
                     case D3DTTFF_COUNT2:
                         VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord2fARB(textureNo, s, t));
+                            GL_EXTCALL(glMultiTexCoord2fARB(texture_idx, s, t));
                         } else {
                             glTexCoord2f(s, t);
                         }
@@ -1597,7 +1609,7 @@ static void drawStridedSlow(IWineD3DDevi
                     case D3DTTFF_COUNT3:
                         VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord3fARB(textureNo, s, t, r));
+                            GL_EXTCALL(glMultiTexCoord3fARB(texture_idx, s, t, r));
                         } else {
                             glTexCoord3f(s, t, r);
                         }
@@ -1605,7 +1617,7 @@ static void drawStridedSlow(IWineD3DDevi
                     case D3DTTFF_COUNT4:
                         VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
                         if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-                            GL_EXTCALL(glMultiTexCoord4fARB(textureNo, s, t, r, q));
+                            GL_EXTCALL(glMultiTexCoord4fARB(texture_idx, s, t, r, q));
                         } else {
                             glTexCoord4f(s, t, r, q);
                         }
@@ -1615,6 +1627,7 @@ static void drawStridedSlow(IWineD3DDevi
                     }
                 }
             }
+            if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[textureNo]) ++texture_idx;
         } /* End of textures */
 
         /* Diffuse -------------------------------- */
@@ -2111,109 +2124,134 @@ static void drawPrimitiveUploadTexturesP
 
         /* Upload texture, apply states */
         IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
-        IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
+        IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
         IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
     }
 }
 
 /* uploads textures and setup texture states ready for rendering */
-void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
-
+static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
+    INT current_sampler = 0;
+    float constant_color[4];
     unsigned int i;
-/**
-* OK, here we clear down any old junk iect in the context
-* enable the new texture and apply any state changes:
-*
-* Loop through all textures
-* select texture unit
-* if there is a texture bound to that unit then..
-* disable all textures types on that unit
-* enable and bind the texture that is bound to that unit.
-* otherwise disable all texture types on that unit.
-**/
-    /* upload the textures */
-    for (i = 0; i< GL_LIMITS(texture_stages); ++i) {
-        /* Bind the texture to the stage here */
-        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-            GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
-            checkGLcall("glActiveTextureARB");
-        } else if (0 < i) {
-            /* This isn't so much a warn as a message to the user about lack of hardware support */
-            WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+
+    /* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
+     * nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
+     * Register combiners however provide up to 8 combiner stages. In order to
+     * take advantage of this, we need to be separate D3D texture stages from
+     * GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
+     * corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
+     * corresponds to MaxTextureBlendStages in the caps. */
+
+    if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+        glEnable(GL_REGISTER_COMBINERS_NV);
+        D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
+        GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
+    }
+
+    for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
+        INT texture_idx = -1;
+
+        /* D3DTOP_DISABLE disables the current & any higher texture stages */
+        if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == D3DTOP_DISABLE) break;
+
+        if (!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]) {
+            texture_idx = current_sampler++;
+
+            /* Active the texture unit corresponding to the current texture stage */
+            if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+                GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
+                checkGLcall("glActiveTextureARB");
+            } else if (i) {
+                WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+            }
         }
 
-        /* don't bother with textures that have a colorop of disable */
-        if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
-            if (This->stateBlock->textures[i] != NULL) {
-
-                glDisable(GL_TEXTURE_1D);
-                This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
-                /* disable all texture states that aren't the selected textures' dimension */
-                switch(This->stateBlock->textureDimensions[i]) {
+        if (This->stateBlock->textures[i]) {
+            /* Enable the correct target. */
+            glDisable(GL_TEXTURE_1D);
+            This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
+            switch(This->stateBlock->textureDimensions[i]) {
                 case GL_TEXTURE_2D:
                     glDisable(GL_TEXTURE_3D);
                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
-                break;
+                    break;
                 case GL_TEXTURE_3D:
                     glDisable(GL_TEXTURE_CUBE_MAP_ARB);
                     glDisable(GL_TEXTURE_2D);
-                break;
+                    break;
                 case GLTEXTURECUBEMAP:
                     glDisable(GL_TEXTURE_2D);
                     glDisable(GL_TEXTURE_3D);
-                break;
-                }
-                /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
-                if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
-                    glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
-                } else {
-                    glEnable(This->stateBlock->textureDimensions[i]);
-                }
-                  /* Load up the texture now */
-                IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
-                IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
-                /* this is a stub function representing the state blocks
-                 * being separated here we are only updating the texture
-                 * state changes, other objects and units get updated when
-                 * they change (or need to be updated), e.g. states that
-                 * relate to a context member line the texture unit are
-                 * only updated when the context needs updating
-                 */
-                /* Tell the abse texture to sync it's states */
-                IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
-
-              }
-            /* Bind a default texture if no texture has been set, but colour-op is enabled */
-            else {
-                glDisable(GL_TEXTURE_2D);
-                glDisable(GL_TEXTURE_3D);
-                glDisable(GL_TEXTURE_CUBE_MAP_ARB);
-                glEnable(GL_TEXTURE_1D);
-                This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
-                glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
+                    break;
             }
-/** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
-        dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
-            set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
-                        This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
-                        This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
-                        This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
-            /* alphaop */
-            set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
-                        This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
-                        This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
-                        This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
-        } else {
 
-            /* no colorop so disable all the texture states */
-            glDisable(GL_TEXTURE_1D);
+            /* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
+            if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
+                glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
+            } else {
+                glEnable(This->stateBlock->textureDimensions[i]);
+            }
+
+            /* Upload texture, apply states */
+            IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
+            IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
+            IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
+        } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+            /* ARB_texture_env_combine needs a valid texture bound to the
+             * texture unit, even if it isn't used. Bind a dummy texture. */
             glDisable(GL_TEXTURE_2D);
             glDisable(GL_TEXTURE_3D);
             glDisable(GL_TEXTURE_CUBE_MAP_ARB);
-          }
+            glEnable(GL_TEXTURE_1D);
+            This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
+            glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
+        }
+
+        /** these ops apply to the texture unit, so they are preserved between texture changes, but for now brute force and reapply all
+          dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
+        if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+            set_tex_op_nvrc((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
+                    This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
+                    This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
+                    This->stateBlock->textureState[i][WINED3DTSS_COLORARG0],
+                    texture_idx);
+            /* alphaop */
+            set_tex_op_nvrc((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
+                    This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
+                    This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
+                    This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0],
+                    texture_idx);
+        } else {
+            set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
+                    This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
+                    This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
+                    This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
+            /* alphaop */
+            set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
+                    This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
+                    This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
+                    This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
+        }
+    }
 
-      }
+    /* If we're using register combiners, set the amount of *used* combiners.
+     * Ie, the number of stages below the first stage to have a color op of
+     * D3DTOP_DISABLE. */
+    if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+        /* NUM_GENERAL_COMBINERS_NV should be > 0 */
+        if (!i) glDisable(GL_REGISTER_COMBINERS_NV);
+        else GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, i));
+    }
 
+    /* Disable the remaining texture units. */
+    for (i = current_sampler; i < GL_LIMITS(textures); ++i) {
+        GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+        glDisable(GL_TEXTURE_1D);
+        glDisable(GL_TEXTURE_2D);
+        glDisable(GL_TEXTURE_3D);
+        glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+    }
 }
 
 /* Routine common to the draw primitive and draw indexed primitive routines */
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 0a17761..b5556ff 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -819,45 +819,46 @@ static HRESULT  WINAPI IWineD3DStateBloc
        bound. We emulate this by creating dummy textures and binding them to each
        texture stage, but disable all stages by default. Hence if a stage is enabled
        then the default texture will kick in until replaced by a SetTexture call     */
+    if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+        ENTER_GL();
 
-    ENTER_GL();
+        for (i = 0; i < GL_LIMITS(texture_stages); i++) {
+            GLubyte white = 255;
 
-    for (i = 0; i < GL_LIMITS(texture_stages); i++) {
-        GLubyte white = 255;
-
-        /* Note this avoids calling settexture, so pretend it has been called */
-        This->set.textures[i]     = TRUE;
-        This->changed.textures[i] = TRUE;
-        This->textures[i]         = NULL;
-
-        /* Make appropriate texture active */
-        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
-            GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
-            checkGLcall("glActiveTextureARB");
-        } else if (i > 0) {
-            FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+            /* Note this avoids calling settexture, so pretend it has been called */
+            This->set.textures[i]     = TRUE;
+            This->changed.textures[i] = TRUE;
+            This->textures[i]         = NULL;
+
+            /* Make appropriate texture active */
+            if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+                GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
+                checkGLcall("glActiveTextureARB");
+            } else if (i > 0) {
+                FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
+            }
+
+            /* Generate an opengl texture name */
+            glGenTextures(1, &ThisDevice->dummyTextureName[i]);
+            checkGLcall("glGenTextures");
+            TRACE("Dummy Texture %d given name %d\n", i, ThisDevice->dummyTextureName[i]);
+
+            /* Generate a dummy 1d texture */
+            This->textureDimensions[i] = GL_TEXTURE_1D;
+            glBindTexture(GL_TEXTURE_1D, ThisDevice->dummyTextureName[i]);
+            checkGLcall("glBindTexture");
+
+            glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
+            checkGLcall("glTexImage1D");
+    #if 1   /* TODO: move the setting texture states off to basetexture */
+            /* Reapply all the texture state information to this texture */
+            IWineD3DDevice_SetupTextureStates(device, i, i, REAPPLY_ALL);
+    #endif
         }
 
-        /* Generate an opengl texture name */
-        glGenTextures(1, &ThisDevice->dummyTextureName[i]);
-        checkGLcall("glGenTextures");
-        TRACE("Dummy Texture %d given name %d\n", i, ThisDevice->dummyTextureName[i]);
-
-        /* Generate a dummy 1d texture */
-        This->textureDimensions[i] = GL_TEXTURE_1D;
-        glBindTexture(GL_TEXTURE_1D, ThisDevice->dummyTextureName[i]);
-        checkGLcall("glBindTexture");
-
-        glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
-        checkGLcall("glTexImage1D");
-#if 1   /* TODO: move the setting texture states off to basetexture */
-        /* Reapply all the texture state information to this texture */
-        IWineD3DDevice_SetupTextureStates(device, i, REAPPLY_ALL);
-#endif
+        LEAVE_GL();
     }
 
-    LEAVE_GL();
-
     /* Defaulting palettes - Note these are device wide but reinitialized here for convenience*/
     for (i = 0; i < MAX_PALETTES; ++i) {
       int j;
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index 5af0f95..5ede0b4 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -497,7 +497,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD
     STDMETHOD(GetRenderTargetData)(THIS_ struct IWineD3DSurface* pRenderTarget, struct IWineD3DSurface* pSurface) PURE;
     STDMETHOD(GetFrontBufferData)(THIS_ UINT iSwapChain,struct IWineD3DSurface* pSurface) PURE;
     /*** Internal use IWineD3Device methods ***/
-    STDMETHOD_(void, SetupTextureStates)(THIS_ DWORD Stage, DWORD Flags);
+    STDMETHOD_(void, SetupTextureStates)(THIS_ DWORD Stage, DWORD texture_idx, DWORD Flags);
     /*** object tracking ***/
     STDMETHOD_(void, ResourceReleased)(THIS_ struct IWineD3DResource *resource);
 };
@@ -638,7 +638,7 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD
 #define IWineD3DDevice_StretchRect(p,a,b,c,d,e)                 (p)->lpVtbl->StretchRect(p,a,b,c,d,e)
 #define IWineD3DDevice_GetRenderTargetData(p,a,b)               (p)->lpVtbl->GetRenderTargetData(p,a,b)
 #define IWineD3DDevice_GetFrontBufferData(p,a,b)                (p)->lpVtbl->GetFrontBufferData(p,a,b)
-#define IWineD3DDevice_SetupTextureStates(p,a,b)                (p)->lpVtbl->SetupTextureStates(p,a,b)
+#define IWineD3DDevice_SetupTextureStates(p,a,b,c)              (p)->lpVtbl->SetupTextureStates(p,a,b,c)
 #define IWineD3DDevice_ResourceReleased(p,a)                    (p)->lpVtbl->ResourceReleased(p,a)
 #endif
 



More information about the wine-patches mailing list