Stefan Dösinger : wined3d: Apply shaders in their state handlers.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jan 8 14:44:04 CST 2007


Module: wine
Branch: master
Commit: 799770b992967f562b309fbacce31bf661980a31
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=799770b992967f562b309fbacce31bf661980a31

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sat Jan  6 18:14:12 2007 +0100

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 a8e4c9a..073a3ad 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -946,6 +946,9 @@ static void shader_arb_select(IWineD3DDe
         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(IWineD3DDe
         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 f2aec53..33c7480 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1108,9 +1108,6 @@ inline static void drawPrimitiveDrawStri
 
     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 drawPrimitiveDrawStri
         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 *if
     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 34aa4bc..70a374f 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1833,16 +1833,12 @@ static void pixelshader(DWORD state, IWi
         /* 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, IWi
         }
         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 stat
          * 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) {




More information about the wine-cvs mailing list