Commit df97fd3e authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Reinstall the nvrc texture unit mapping.

parent a008003c
...@@ -2079,6 +2079,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR ...@@ -2079,6 +2079,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR
/* TODO: Test if OpenGL is compiled in and loaded */ /* 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 */ /* Setup the implicit swapchain */
TRACE("Creating implicit swapchain\n"); TRACE("Creating implicit swapchain\n");
if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) { if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
...@@ -3676,6 +3682,72 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF( ...@@ -3676,6 +3682,72 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
return WINED3D_OK; 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) { static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader; IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
...@@ -3707,6 +3779,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, I ...@@ -3707,6 +3779,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, I
TRACE("(%p) : setting pShader(%p)\n", This, pShader); TRACE("(%p) : setting pShader(%p)\n", This, pShader);
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER); 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; return WINED3D_OK;
} }
...@@ -4436,6 +4514,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if ...@@ -4436,6 +4514,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *if
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type)); 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; return WINED3D_OK;
} }
...@@ -4549,6 +4634,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD ...@@ -4549,6 +4634,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage)); 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; return WINED3D_OK;
} }
......
...@@ -1362,14 +1362,15 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock) { ...@@ -1362,14 +1362,15 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock) {
if (GL_SUPPORT(ARB_MULTITEXTURE)) { if (GL_SUPPORT(ARB_MULTITEXTURE)) {
/* TODO: register combiners! */ /* 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 && if(stateblock->textureState[stage][WINED3DTSS_COLOROP] != WINED3DTOP_DISABLE &&
stateblock->textureState[stage][WINED3DTSS_COLOROP] != 0) { stateblock->textureState[stage][WINED3DTSS_COLOROP] != 0) {
FIXME("Attempt to enable unsupported stage!\n"); FIXME("Attempt to enable unsupported stage!\n");
} }
return; return;
} }
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[stage]));
checkGLcall("glActiveTextureARB"); checkGLcall("glActiveTextureARB");
} else if (stage > 0) { } else if (stage > 0) {
WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
...@@ -1408,7 +1409,7 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock) { ...@@ -1408,7 +1409,7 @@ static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock) {
stateblock->textureState[stage][WINED3DTSS_COLORARG1], stateblock->textureState[stage][WINED3DTSS_COLORARG1],
stateblock->textureState[stage][WINED3DTSS_COLORARG2], stateblock->textureState[stage][WINED3DTSS_COLORARG2],
stateblock->textureState[stage][WINED3DTSS_COLORARG0], stateblock->textureState[stage][WINED3DTSS_COLORARG0],
stage); stateblock->wineD3DDevice->texUnitMap[stage]);
} else { } else {
set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage, set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
stateblock->textureState[stage][WINED3DTSS_COLOROP], stateblock->textureState[stage][WINED3DTSS_COLOROP],
...@@ -1432,7 +1433,7 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock) { ...@@ -1432,7 +1433,7 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock) {
} }
return; return;
} }
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[stage]));
checkGLcall("glActiveTextureARB"); checkGLcall("glActiveTextureARB");
} else if (stage > 0) { } else if (stage > 0) {
/* We can't do anything here */ /* We can't do anything here */
...@@ -1447,7 +1448,7 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock) { ...@@ -1447,7 +1448,7 @@ static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock) {
stateblock->textureState[stage][WINED3DTSS_ALPHAARG1], stateblock->textureState[stage][WINED3DTSS_ALPHAARG1],
stateblock->textureState[stage][WINED3DTSS_ALPHAARG2], stateblock->textureState[stage][WINED3DTSS_ALPHAARG2],
stateblock->textureState[stage][WINED3DTSS_ALPHAARG0], stateblock->textureState[stage][WINED3DTSS_ALPHAARG0],
stage); stateblock->wineD3DDevice->texUnitMap[stage]);
} else { } else {
set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage, stateblock->textureState[stage][WINED3DTSS_ALPHAOP], set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage, stateblock->textureState[stage][WINED3DTSS_ALPHAOP],
stateblock->textureState[stage][WINED3DTSS_ALPHAARG1], stateblock->textureState[stage][WINED3DTSS_ALPHAARG1],
...@@ -1464,7 +1465,7 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock) { ...@@ -1464,7 +1465,7 @@ static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock) {
if(stage >= GL_LIMITS(sampler_stages)) { if(stage >= GL_LIMITS(sampler_stages)) {
return; return;
} }
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage)); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[stage]));
checkGLcall("glActiveTextureARB"); checkGLcall("glActiveTextureARB");
} else if (stage > 0) { } else if (stage > 0) {
/* We can't do anything here */ /* We can't do anything here */
...@@ -1661,7 +1662,7 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock) { ...@@ -1661,7 +1662,7 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock) {
if(sampler >= GL_LIMITS(sampler_stages)) { if(sampler >= GL_LIMITS(sampler_stages)) {
return; return;
} }
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + sampler)); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stateblock->wineD3DDevice->texUnitMap[sampler]));
checkGLcall("glActiveTextureARB"); checkGLcall("glActiveTextureARB");
} else if (sampler > 0) { } else if (sampler > 0) {
/* We can't do anything here */ /* We can't do anything here */
......
...@@ -652,6 +652,10 @@ typedef struct IWineD3DDeviceImpl ...@@ -652,6 +652,10 @@ typedef struct IWineD3DDeviceImpl
DWORD numDirtyEntries; DWORD numDirtyEntries;
DWORD isStateDirty[STATE_HIGHEST/32 + 1]; /* Bitmap to find out quickly if a state is dirty */ 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; } IWineD3DDeviceImpl;
extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl; extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment