From 799770b992967f562b309fbacce31bf661980a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Sat, 6 Jan 2007 18:14:12 +0100 Subject: [PATCH] wined3d: Apply shaders in their state handlers. --- dlls/wined3d/arb_program_shader.c | 6 +++++ dlls/wined3d/drawprim.c | 14 ++++++----- dlls/wined3d/state.c | 39 ++++++++++++++++++------------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index a8e4c9afd08..073a3ad3821 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -946,6 +946,9 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);"); TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId); + } else if(GL_SUPPORT(GL_VERTEX_PROGRAM_ARB)) { + glDisable(GL_VERTEX_PROGRAM_ARB); + checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)"); } if (usePS) { @@ -961,6 +964,9 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);"); TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId); + } else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); } } diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index f2aec539946..33c74806985 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -1108,9 +1108,6 @@ inline static void drawPrimitiveDrawStrided( IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - /* Make any shaders active */ - This->shader_backend->shader_select(iface, usePixelShaderFunction, useVertexShaderFunction); - /* Load any global constants/uniforms that may have been set by the application */ This->shader_backend->shader_load_constants(iface, usePixelShaderFunction, useVertexShaderFunction); @@ -1119,9 +1116,6 @@ inline static void drawPrimitiveDrawStrided( drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx, baseVIndex); else drawStridedFast(iface, numberOfIndicies, glPrimType, idxData, idxSize, minIndex, StartIdx, baseVIndex); - - /* Cleanup any shaders */ - This->shader_backend->shader_cleanup(usePixelShaderFunction, useVertexShaderFunction); } static void check_fbo_status(IWineD3DDevice *iface) { @@ -1164,6 +1158,14 @@ static void depth_blt(IWineD3DDevice *iface, GLuint texture) { glBindTexture(GL_TEXTURE_2D, old_binding); glPopAttrib(); + + /* Reselect the old shaders. There doesn't seem to be any glPushAttrib bit for arb shaders, + * and this seems easier and more efficient than providing the shader backend with a private + * storage to read and restore the old shader settings + */ + This->shader_backend->shader_select(iface, + This->stateBlock->pixelShader && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.function, + This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.function); } static void depth_copy(IWineD3DDevice *iface) { diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 34aa4bce7d8..70a374ff3e5 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -1833,16 +1833,12 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock) { /* Compile and bind the shader */ IWineD3DPixelShader_CompileShader(stateblock->pixelShader); -#if 0 - /* Can't do that here right now, because glsl shaders depend on having both pixel and vertex shader - * setup at the same time. The shader_select call will be done by drawprim until vertex shaders are - * moved to the state table too - */ - stateblock->wineD3DDevice->shader_backend->shader_select( - (IWineD3DDevice *) stateblock->wineD3DDevice, - TRUE, - !stateblock->vertexShader ? FALSE : ((IWineD3DVertexShaderImpl *) stateblock->vertexShader)->baseShader.function != NULL); -#endif + if(!isStateDirty(stateblock->wineD3DDevice, StateTable[STATE_VSHADER].representative)) { + stateblock->wineD3DDevice->shader_backend->shader_select( + (IWineD3DDevice *) stateblock->wineD3DDevice, + TRUE, + !stateblock->vertexShader ? FALSE : ((IWineD3DVertexShaderImpl *) stateblock->vertexShader)->baseShader.function != NULL); + } stateblock->wineD3DDevice->last_was_pshader = TRUE; } else { /* Disabled the pixel shader - color ops weren't applied @@ -1855,12 +1851,12 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock) { } stateblock->wineD3DDevice->last_was_pshader = FALSE; -#if 0 - stateblock->wineD3DDevice->shader_backend->shader_select( - (IWineD3DDevice *) stateblock->wineD3DDevice, - FALSE, - !stateblock->vertexShader ? FALSE : ((IWineD3DVertexShaderImpl *) stateblock->vertexShader)->baseShader.function != NULL); -#endif + if(!isStateDirty(stateblock->wineD3DDevice, StateTable[STATE_VSHADER].representative)) { + stateblock->wineD3DDevice->shader_backend->shader_select( + (IWineD3DDevice *) stateblock->wineD3DDevice, + FALSE, + !stateblock->vertexShader ? FALSE : ((IWineD3DVertexShaderImpl *) stateblock->vertexShader)->baseShader.function != NULL); + } } } @@ -2653,6 +2649,17 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock) { * in order to determine if we need to do any swizzling for D3DCOLOR * registers. If the shader is already compiled this call will do nothing. */ IWineD3DVertexShader_CompileShader(stateblock->vertexShader); + + /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the + * application + */ + if(!isStateDirty(device, STATE_PIXELSHADER)) { + BOOL usePixelShaderFunction = device->ps_selected_mode != SHADER_NONE && + stateblock->pixelShader && + ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function; + + device->shader_backend->shader_select((IWineD3DDevice *) device, usePixelShaderFunction, useVertexShaderFunction); + } } if(updateFog) {