From a54e36adfebd721c1f5c823b2edf784f1af1d9c2 Mon Sep 17 00:00:00 2001 From: "H. Verbeet" Date: Tue, 27 Jun 2006 23:40:42 +0200 Subject: [PATCH] wined3d: Texture limits fixes. 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 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. --- dlls/wined3d/device.c | 32 +++++++++++------------ dlls/wined3d/directx.c | 10 +++++--- dlls/wined3d/drawprim.c | 6 ++--- dlls/wined3d/stateblock.c | 46 ++++++++++++++++------------------ dlls/wined3d/wined3d_private.h | 4 +-- include/wine/wined3d_gl.h | 2 ++ 6 files changed, 51 insertions(+), 49 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2be56925172..44ad98a827d 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -431,8 +431,8 @@ static void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, 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_CreateStateBlock(IWineD3DDevice* iface, 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_CreateStateBlock(IWineD3DDevice* iface, 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_Init3D(IWineD3DDevice *iface, WINED3DPR 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_Uninit3D(IWineD3DDevice *iface) { 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_SetRenderState(IWineD3DDevice *iface, D } /* 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_SetSamplerState(IWineD3DDevice *iface, * 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_ApplyTextureUnitState(IWineD3DDevice *ifac 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_SetTextureStageState(IWineD3DDevice *if 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_SetTexture(IWineD3DDevice *iface, DWORD #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_SetTexture(IWineD3DDevice *iface, DWORD } 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_GetTexture(IWineD3DDevice *iface, DWORD 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_ResourceReleased(IWineD3DDevice *iface, IW 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 68c1131526d..0ccfec9276d 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -432,8 +432,10 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) { * 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_Info *gl_info, Display* display) { 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_Info *gl_info, Display* display) { 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_GetDeviceCaps(IWineD3D *iface, UINT Adapter, 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 7d301727945..675813ff0af 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -1313,7 +1313,7 @@ static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData /* 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(IWineD3DDevice *iface, WineDirect3DVertexStridedData } /* 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(IWineD3DDeviceImpl* This) { * 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 58f0470e9c2..0a17761c0c6 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -90,7 +90,7 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) { } /* 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) } } - /* 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 IWineD3DStateBlockImpl_Capture(IWineD3DStateBlock *iface) This->textureState[j][i] = targetStateBlock->textureState[j][i]; } } - - 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 (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]; + } 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 only the changes get updated*/ 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 only the changes get updated*/ /* 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 only the changes get updated*/ } - 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 only the changes get updated*/ 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 IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat 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 IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat } /* 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 IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat 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 d55b810c03c..9543cb2a0bc 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 304ae0ca124..038cbafa578 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;