[3/6] WINED3D: Texture limits fixes

H. Verbeet hverbeet at gmail.com
Tue Jun 27 16:40:42 CDT 2006


GL_LIMITS(textures) is currently used for both the number of texture
stages and the maximum number of simultaneous textures. In the current
code that's the same, but in a later patch (6/6) that will be
separated, since a texture stage doesn't have to reference an actual
texture. Also, shaders can access a larger number of samplers than the
number of texture units the fixed function pipeline can access.
-------------- next part --------------
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 2be5692..44ad98a 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -431,8 +431,8 @@ static void WINAPI IWineD3DDeviceImpl_Se
     clamping, MIPLOD, etc. This will work for up to 16 samplers.
     */
    
-    if (Sampler >= GL_LIMITS(samplers)) {
-        FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(samplers));
+    if (Sampler >= GL_LIMITS(sampler_stages)) {
+        FIXME("Trying to set the state of more samplers %ld than are supported %d by this openGL implementation\n", Sampler, GL_LIMITS(sampler_stages));
         return;
     }
     VTRACE(("Activating appropriate texture state %ld\n", Sampler));
@@ -828,7 +828,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
         }
-        for (j = 0; j < GL_LIMITS(textures); j++) {
+        for (j = 0; j < GL_LIMITS(texture_stages); j++) {
             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
             }
@@ -856,7 +856,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
         }
-        for (j = 0; j < GL_LIMITS(textures); j++) {
+        for (j = 0; j < GL_LIMITS(texture_stages); j++) {
             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
             }
@@ -2098,7 +2098,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
-    int texstage;
+    int sampler;
     IUnknown* stencilBufferParent;
     IUnknown* swapChainParent;
     uint i;
@@ -2106,8 +2106,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
 
-    for(texstage = 0; texstage < GL_LIMITS(textures); texstage++) {
-        IWineD3DDevice_SetTexture(iface, texstage, NULL);
+    for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
+        IWineD3DDevice_SetTexture(iface, sampler, NULL);
     }
 
     /* Release the buffers (with sanity checks)*/
@@ -3825,7 +3825,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
             }
 
             /* And now the default texture color as well */
-            for (i = 0; i < GL_LIMITS(textures); i++) {
+            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!               */
@@ -4528,9 +4528,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
      ******************/
     /** NOTE: States are appled in IWineD3DBaseTextre ApplyStateChanges and IWineD3DDevice SetupTextureStates**/
-    if(Sampler >  GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
+    if(Sampler >  GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
          FIXME("sampler %ld type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
-            Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE);
+            Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
         return WINED3DERR_INVALIDCALL;
     }
 
@@ -5384,7 +5384,7 @@ static void WINAPI IWineD3DDeviceImpl_Ap
     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
 
     /* Check that the stage is within limits  */
-    if (Stage >= GL_LIMITS(textures) || Stage < 0) {
+    if (Stage >= GL_LIMITS(texture_stages) || Stage < 0) {
         TRACE("Attempt to access invalid texture rejected\n");
         return;
     }
@@ -5600,7 +5600,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     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)) {
+    if (Stage >= GL_LIMITS(texture_stages)) {
         TRACE("Attempt to access invalid texture rejected\n");
         return WINED3DERR_INVALIDCALL;
     }
@@ -5638,7 +5638,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 #endif
 
     /* Reject invalid texture units */
-    if (Stage >= GL_LIMITS(textures) || Stage < 0) {
+    if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
         WARN("Attempt to access invalid texture rejected\n");
         return WINED3DERR_INVALIDCALL;
     }
@@ -5653,7 +5653,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     }
 
     oldTexture = This->updateStateBlock->textures[Stage];
-    TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
+    TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
 
     This->updateStateBlock->set.textures[Stage]     = TRUE;
@@ -5702,7 +5702,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
     TRACE("(%p) : (%ld /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
 
     /* Reject invalid texture units */
-    if (Stage >= GL_LIMITS(textures)) {
+    if (Stage >= GL_LIMITS(sampler_stages)) {
         TRACE("Attempt to access invalid texture rejected\n");
         return WINED3DERR_INVALIDCALL;
     }
@@ -7774,7 +7774,7 @@ static void WINAPI IWineD3DDeviceImpl_Re
         case WINED3DRTYPE_TEXTURE:
         case WINED3DRTYPE_CUBETEXTURE:
         case WINED3DRTYPE_VOLUMETEXTURE:
-                for (counter = 0; counter < GL_LIMITS(textures); counter++) {
+                for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
                         This->stateBlock->textures[counter] = NULL;
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 68c1131..0ccfec9 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -432,8 +432,10 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_
      *  with Default values
      */
     memset(&gl_info->supported, 0, sizeof(gl_info->supported));
-    gl_info->max_textures   = 1;
-    gl_info->max_samplers   = 1;
+    gl_info->max_textures       = 1;
+    gl_info->max_texture_stages = 1;
+    gl_info->max_samplers       = 1;
+    gl_info->max_sampler_stages = 1;
     gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
     gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
     gl_info->vs_nv_version  = VS_VERSION_NOT_SUPPORTED;
@@ -503,6 +505,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_
                 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
                 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
                 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
+                gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
                 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
             } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
                 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
@@ -667,6 +670,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_
             if (*GL_Extensions == ' ') GL_Extensions++;
         }
     }
+    gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
 
     /* Load all the lookup tables
     TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
@@ -1680,7 +1684,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDe
                             D3DTEXOPCAPS_PREMODULATE */
 #endif
 
-    *pCaps->MaxTextureBlendStages   = GL_LIMITS(textures);
+    *pCaps->MaxTextureBlendStages   = GL_LIMITS(texture_stages);
     *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
     *pCaps->MaxUserClipPlanes       = GL_LIMITS(clipplanes);
     *pCaps->MaxActiveLights         = GL_LIMITS(lights);
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 7d30172..675813f 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1313,7 +1313,7 @@ static void loadVertexData(IWineD3DDevic
 
     /* Texture coords -------------------------------------------*/
 
-    for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+    for (textureNo = 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)) {
@@ -1509,7 +1509,7 @@ static void drawStridedSlow(IWineD3DDevi
         }
 
         /* Texture coords --------------------------- */
-        for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+        for (textureNo = 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");
@@ -2092,7 +2092,7 @@ void inline drawPrimitiveUploadTextures(
 * otherwise disable all texture types on that unit.
 **/
     /* upload the textures */
-    for (i = 0; i< GL_LIMITS(textures); ++i) {
+    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));
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 58f0470..0a17761 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -90,7 +90,7 @@ static ULONG  WINAPI IWineD3DStateBlockI
             }
 
             /* NOTE: according to MSDN: The application is responsible for making sure the texture references are cleared down */
-            for (counter = 0; counter < GL_LIMITS(textures); counter++) {
+            for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
                 if (This->textures[counter]) {
                     /* release our 'internal' hold on the texture */
                     if(0 != IWineD3DBaseTexture_Release(This->textures[counter])) {
@@ -374,9 +374,8 @@ static HRESULT  WINAPI IWineD3DStateBloc
             }
         }
 
-        /* FIXME: textures are up to MAX_SAMPLERS for d3d9? */
-        /* Texture */
-        for (j = 0; j < GL_LIMITS(textures); j++) {
+        /* Texture states */
+        for (j = 0; j < GL_LIMITS(texture_stages); j++) {
             /* TODO: move over to using memcpy */
             for (i = 1; i <= WINED3D_HIGHEST_TEXTURE_STATE ; i++) {
                 if (This->set.textureState[j][i]) {
@@ -385,17 +384,15 @@ static HRESULT  WINAPI IWineD3DStateBloc
                     This->textureState[j][i]         =  targetStateBlock->textureState[j][i];
                 }
             }
+        }
 
+        /* Samplers */
+        /* TODO: move over to using memcpy */
+        for (j = 0; j < GL_LIMITS(sampler_stages); j++) {
             if (This->set.textures[j]) {
                 TRACE("Updating texture %d to %p (was %p)\n", j, targetStateBlock->textures[j],  This->textures[j]);
                 This->textures[j] = targetStateBlock->textures[j];
             }
-
-        }
-
-        /* Samplers */
-        /* TODO: move over to using memcpy */
-        for (j = 0 ; j < GL_LIMITS(samplers); j++){
             for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE ; i++){ /* States are 1 based */
                 if (This->set.samplerState[j][i]) {
                     TRACE("Updating sampler state %d,%d to %ld (was %ld)\n",
@@ -528,12 +525,8 @@ should really perform a delta so that on
                 IWineD3DDevice_SetRenderState(pDevice, i, This->renderState[i]);
         }
 
-        /* FIXME: Texture are set against samplers... not just TextureStages */
-        /* Texture */
-        for (j = 0; j < GL_LIMITS(textures); j++) { /* Set The texture first, just in case it resets the states? */
-            if (This->set.textures[j] && This->changed.textures[j]) {
-                IWineD3DDevice_SetTexture(pDevice, j, This->textures[j]);
-            }
+        /* Texture states */
+        for (j = 0; j < GL_LIMITS(texture_stages); j++) { /* Set The texture first, just in case it resets the states? */
             /* TODO: move over to memcpy */
             for (i = 1; i <= WINED3D_HIGHEST_TEXTURE_STATE; i++) {
                 if (This->set.textureState[j][i] && This->changed.textureState[j][i]) { /* tb_dx9_10 failes without this test */
@@ -546,7 +539,10 @@ should really perform a delta so that on
 
         /* Samplers */
         /* TODO: move over to memcpy */
-        for (j = 0 ; j < GL_LIMITS(samplers); j++){
+        for (j = 0 ; j < GL_LIMITS(sampler_stages); j++){
+            if (This->set.textures[j] && This->changed.textures[j]) {
+                IWineD3DDevice_SetTexture(pDevice, j, This->textures[j]);
+            }
             for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE; i++){
                 if (This->set.samplerState[j][i] && This->changed.samplerState[j][i]) {
                     ((IWineD3DDeviceImpl *)pDevice)->stateBlock->samplerState[j][i]         = This->samplerState[j][i];
@@ -565,13 +561,13 @@ should really perform a delta so that on
 
         }
 
-        for (j = 0; j < GL_LIMITS(textures); j++) {
+        for (j = 0; j < GL_LIMITS(texture_stages); j++) {
             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
                 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->textureState[j][SavedPixelStates_T[i]] = This->textureState[j][SavedPixelStates_T[i]];
             }
         }
 
-        for (j = 0; j < GL_LIMITS(samplers); j++) {
+        for (j = 0; j < GL_LIMITS(sampler_stages); j++) {
             for (i = 0; i < NUM_SAVEDPIXELSTATES_S; i++) {
                 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->samplerState[j][SavedPixelStates_S[i]] = This->samplerState[j][SavedPixelStates_S[i]];
             }
@@ -584,13 +580,13 @@ should really perform a delta so that on
                 IWineD3DDevice_SetRenderState(pDevice, SavedVertexStates_R[i], This->renderState[SavedVertexStates_R[i]]);
         }
 
-        for (j = 0; j < GL_LIMITS(textures); j++) {
+        for (j = 0; j < GL_LIMITS(texture_stages); j++) {
             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
                 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->textureState[j][SavedVertexStates_T[i]] = This->textureState[j][SavedVertexStates_T[i]];
             }
         }
 
-        for (j = 0; j < GL_LIMITS(textures); j++) {
+        for (j = 0; j < GL_LIMITS(sampler_stages); j++) {
             for (i = 0; i < NUM_SAVEDVERTEXSTATES_S; i++) {
                 ((IWineD3DDeviceImpl *)pDevice)->stateBlock->samplerState[j][SavedVertexStates_S[i]] = This->samplerState[j][SavedVertexStates_S[i]];
             }
@@ -777,7 +773,7 @@ static HRESULT  WINAPI IWineD3DStateBloc
     This->clip_status.ClipIntersection = 0xFFFFFFFF;
 
     /* Texture Stage States - Put directly into state block, we will call function below */
-    for (i = 0; i < GL_LIMITS(textures); i++) {
+    for (i = 0; i < GL_LIMITS(texture_stages); i++) {
         TRACE("Setting up default texture states for texture Stage %d\n", i);
         memcpy(&This->transforms[D3DTS_TEXTURE0 + i], &identity, sizeof(identity));
         This->textureState[i][D3DTSS_COLOROP               ] = (i==0)? D3DTOP_MODULATE :  D3DTOP_DISABLE;
@@ -801,7 +797,7 @@ static HRESULT  WINAPI IWineD3DStateBloc
     }
 
         /* Sampler states*/
-    for (i = 0 ; i <  GL_LIMITS(samplers); i++) {
+    for (i = 0 ; i <  GL_LIMITS(sampler_stages); i++) {
         TRACE("Setting up default samplers states for sampler %d\n", i);
         This->samplerState[i][WINED3DSAMP_ADDRESSU         ] = D3DTADDRESS_WRAP;
         This->samplerState[i][WINED3DSAMP_ADDRESSV         ] = D3DTADDRESS_WRAP;
@@ -826,7 +822,7 @@ static HRESULT  WINAPI IWineD3DStateBloc
 
     ENTER_GL();
 
-    for (i = 0; i < GL_LIMITS(textures); i++) {
+    for (i = 0; i < GL_LIMITS(texture_stages); i++) {
         GLubyte white = 255;
 
         /* Note this avoids calling settexture, so pretend it has been called */
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d55b810..9543cb2 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1003,7 +1003,7 @@ typedef struct SAVEDSTATES {
         BOOL                      fvf;
         BOOL                      streamSource[MAX_STREAMS];
         BOOL                      streamFreq[MAX_STREAMS];
-        BOOL                      textures[MAX_TEXTURES];
+        BOOL                      textures[MAX_SAMPLERS];
         BOOL                      transform[HIGHEST_TRANSFORMSTATE + 1];
         BOOL                      viewport;
         BOOL                      renderState[WINEHIGHEST_RENDER_STATE + 1];
@@ -1092,7 +1092,7 @@ struct IWineD3DStateBlockImpl
     DWORD                     renderState[WINEHIGHEST_RENDER_STATE + 1];
 
     /* Texture */
-    IWineD3DBaseTexture      *textures[MAX_TEXTURES];
+    IWineD3DBaseTexture      *textures[MAX_SAMPLERS];
     int                       textureDimensions[MAX_SAMPLERS];
 
     /* Texture State Stage */
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index 304ae0c..038cbaf 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -1670,7 +1670,9 @@ typedef struct _WineD3D_GL_Info {
    */
   UINT   max_lights;
   UINT   max_textures;
+  UINT   max_texture_stages;
   UINT   max_samplers;
+  UINT   max_sampler_stages;
   UINT   max_clipplanes;
   UINT   max_texture_size;
   float  max_pointsize;


More information about the wine-patches mailing list