Module: wine Branch: master Commit: df97fd3e46b5c042eea5319ef7c0b4055a205158 URL: http://source.winehq.org/git/wine.git/?a=commit;h=df97fd3e46b5c042eea5319ef7...
Author: Stefan Dösinger stefan@codeweavers.com Date: Tue Dec 19 23:33:34 2006 +0100
wined3d: Reinstall the nvrc texture unit mapping.
---
dlls/wined3d/device.c | 92 ++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/state.c | 15 ++++--- dlls/wined3d/wined3d_private.h | 4 ++ 3 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index dd42bf7..1c1abab 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2079,6 +2079,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl
/* TODO: Test if OpenGL is compiled in and loaded */
+ /* Initialize the texture unit mapping to a 1:1 mapping */ + for(state = 0; state < MAX_SAMPLERS; state++) { + This->texUnitMap[state] = state; + } + This->oneToOneTexUnitMap = TRUE; + /* Setup the implicit swapchain */ TRACE("Creating implicit swapchain\n"); if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) { @@ -3676,6 +3682,72 @@ static HRESULT WINAPI IWineD3DDeviceImpl return WINED3D_OK; }
+static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) { + DWORD i; + for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) { + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i)); + } +} + +static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) { + DWORD i, tex; + /* This code can assume that GL_NV_register_combiners are supported, otherwise + * it is never called. + * + * Rules are: + * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but + * that would be really messy and require shader recompilation + * -> When the mapping of a stage is changed, sampler and ALL texture stage states have + * to be reset. Because of that try to work with a 1:1 mapping as much as possible + * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array + * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10 + */ + if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) { + if(This->oneToOneTexUnitMap) { + TRACE("Not touching 1:1 map\n"); + return; + } + TRACE("Restoring 1:1 texture unit mapping\n"); + /* Restore a 1:1 mapping */ + for(i = 0; i < MAX_SAMPLERS; i++) { + if(This->texUnitMap[i] != i) { + This->texUnitMap[i] = i; + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i)); + markTextureStagesDirty(This, i); + } + } + This->oneToOneTexUnitMap = TRUE; + return; + } else { + /* No pixel shader, and we do not have enought texture units available. Try to skip NULL textures + * First, see if we can succeed at all + */ + tex = 0; + for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) { + if(This->stateBlock->textures[i] == NULL) tex++; + } + + if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) { + FIXME("Too many bound textures to support the combiner settings\n"); + return; + } + + /* Now work out the mapping */ + tex = 0; + This->oneToOneTexUnitMap = FALSE; + FIXME("Non 1:1 mapping UNTESTED!\n"); + for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) { + if(This->stateBlock->textures[i] == NULL) tex++; + TRACE("Mapping texture stage %d to unit %d\n", i, tex); + if(This->texUnitMap[i] != tex) { + This->texUnitMap[i] = tex; + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i)); + markTextureStagesDirty(This, i); + } + } + } +} + static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader; @@ -3707,6 +3779,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl
TRACE("(%p) : setting pShader(%p)\n", This, pShader); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER); + + /* Rebuild the texture unit mapping if nvrc's are supported */ + if(GL_SUPPORT(NV_REGISTER_COMBINERS)) { + IWineD3DDeviceImpl_FindTexUnitMap(This); + } + return WINED3D_OK; }
@@ -4436,6 +4514,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
+ /* Rebuild the stage -> gl texture unit mapping if register combiners are supported + * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader + * will call FindTexUnitMap too. + */ + if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) { + IWineD3DDeviceImpl_FindTexUnitMap(This); + } return WINED3D_OK; }
@@ -4549,6 +4634,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
+ /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no + * pixel shader is used + */ + if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) { + IWineD3DDeviceImpl_FindTexUnitMap(This); + } + return WINED3D_OK; }
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 16057c4..6bf101c 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -1362,14 +1362,15 @@ static void tex_colorop(DWORD state, IWi
if (GL_SUPPORT(ARB_MULTITEXTURE)) { /* TODO: register combiners! */ - if(stage >= GL_LIMITS(sampler_stages)) { + if(stage != stateblock->wineD3DDevice->texUnitMap[stage]) ERR("Foo: %d is %d!\n", stage, stateblock->wineD3DDevice->texUnitMap[stage]); + if(stateblock->wineD3DDevice->texUnitMap[stage] >= GL_LIMITS(sampler_stages)) { if(stateblock->textureState[stage][WINED3DTSS_COLOROP] != WINED3DTOP_DISABLE && stateblock->textureState[stage][WINED3DTSS_COLOROP] != 0) { FIXME("Attempt to enable unsupported stage!\n"); } return; } - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[stage])); checkGLcall("glActiveTextureARB"); } else if (stage > 0) { WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); @@ -1408,7 +1409,7 @@ static void tex_colorop(DWORD state, IWi stateblock->textureState[stage][WINED3DTSS_COLORARG1], stateblock->textureState[stage][WINED3DTSS_COLORARG2], stateblock->textureState[stage][WINED3DTSS_COLORARG0], - stage); + stateblock->wineD3DDevice->texUnitMap[stage]); } else { set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage, stateblock->textureState[stage][WINED3DTSS_COLOROP], @@ -1432,7 +1433,7 @@ static void tex_alphaop(DWORD state, IWi } return; } - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[stage])); checkGLcall("glActiveTextureARB"); } else if (stage > 0) { /* We can't do anything here */ @@ -1447,7 +1448,7 @@ static void tex_alphaop(DWORD state, IWi stateblock->textureState[stage][WINED3DTSS_ALPHAARG1], stateblock->textureState[stage][WINED3DTSS_ALPHAARG2], stateblock->textureState[stage][WINED3DTSS_ALPHAARG0], - stage); + stateblock->wineD3DDevice->texUnitMap[stage]); } else { set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage, stateblock->textureState[stage][WINED3DTSS_ALPHAOP], stateblock->textureState[stage][WINED3DTSS_ALPHAARG1], @@ -1464,7 +1465,7 @@ static void tex_coordindex(DWORD state, if(stage >= GL_LIMITS(sampler_stages)) { return; } - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[stage])); checkGLcall("glActiveTextureARB"); } else if (stage > 0) { /* We can't do anything here */ @@ -1661,7 +1662,7 @@ static void sampler(DWORD state, IWineD3 if(sampler >= GL_LIMITS(sampler_stages)) { return; } - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + sampler)); + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[sampler])); checkGLcall("glActiveTextureARB"); } else if (sampler > 0) { /* We can't do anything here */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1df81bb..6f569e8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -652,6 +652,10 @@ typedef struct IWineD3DDeviceImpl DWORD numDirtyEntries; DWORD isStateDirty[STATE_HIGHEST/32 + 1]; /* Bitmap to find out quickly if a state is dirty */
+ /* With register combiners we can skip junk texture stages */ + DWORD texUnitMap[MAX_SAMPLERS]; + BOOL oneToOneTexUnitMap; + } IWineD3DDeviceImpl;
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;