Stefan Dösinger : wined3d: Add pixel shaders to the state table.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Dec 20 12:24:51 CST 2006


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Tue Dec 19 23:22:19 2006 +0100

wined3d: Add pixel shaders to the state table.

---

 dlls/wined3d/device.c          |   31 ++++------------------
 dlls/wined3d/drawprim.c        |    8 -----
 dlls/wined3d/state.c           |   56 ++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |    6 +++-
 4 files changed, 67 insertions(+), 34 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 833c84b..1bc25c2 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3690,37 +3690,18 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     if (NULL != pShader) {
         IWineD3DPixelShader_AddRef(pShader);
-        if(oldShader == NULL) {
-            /* Fixed function color ops deactivate the texture dimensions from the first stage which has colorop = disable
-             * Pixel shaders require that this is enabled, so dirtify all samplers, they will enable the dimensions.
-             * do not dirtify the colorop - it won't do anything when a ashader is bound
-             * This is temporary until pixel shaders are handled by the state table too
-             */
-            int i;
-            for(i = 0; i < MAX_SAMPLERS; i++) {
-                IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
-            }
-        }
     }
     if (NULL != oldShader) {
         IWineD3DPixelShader_Release(oldShader);
-        if(pShader == NULL) {
-            /* Fixed function pipeline color args conflict with pixel shader setup, so we do not apply them when a pshader is
-             * bound. Due to that we have to reapply all color ops when disabling pixel shaders.
-             * When pixel shaders are handled by the state table too, the pshader function will take care for that, and this
-             * will also handle draw -> SetPixelShader(NULL) -> SetPixelShader(!= NULL) -> draw cases better
-             */
-            int i;
-            for(i = 0; i < MAX_TEXTURES; i++) {
-                IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
-            }
-        }
+    }
+
+    if (This->isRecordingState) {
+        TRACE("Recording... not performing anything\n");
+        return WINED3D_OK;
     }
 
     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
-    /**
-     * TODO: merge HAL shaders context switching from prototype
-     */
+    IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
     return WINED3D_OK;
 }
 
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index c550d04..a050bb2 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1781,14 +1781,6 @@ inline static void drawPrimitiveDrawStri
         useDrawStridedSlow = TRUE;
     }
 
-    if(usePixelShaderFunction) {
-        /* We compile the shader here because it depends on the texture stage state
-         * setup of the bound textures. If the shader is already compiled and the texture stage
-         * state setup matches the program this function will do nothing
-         */
-        IWineD3DPixelShader_CompileShader(This->stateBlock->pixelShader);
-    }
-
     /* Make any shaders active */
     This->shader_backend->shader_select(iface, usePixelShaderFunction, useVertexShaderFunction);
 
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 89e2e2b..16057c4 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1707,6 +1707,60 @@ static void sampler(DWORD state, IWineD3
     }
 }
 
+static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock) {
+    int i;
+
+    if(stateblock->pixelShader && ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.function != NULL) {
+        if(!stateblock->wineD3DDevice->last_was_pshader) {
+            /* Former draw without a pixel shader, some samplers
+             * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
+             * make sure to enable them
+             */
+            for(i=0; i < MAX_SAMPLERS; i++) {
+                if(!isStateDirty(stateblock->wineD3DDevice, STATE_SAMPLER(i))) {
+                    sampler(STATE_SAMPLER(i), stateblock);
+                }
+            }
+        } else {
+           /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
+            * if a different texture was bound. I don't have to do anything.
+            */
+        }
+
+        /* 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
+        stateblock->wineD3DDevice->last_was_pshader = TRUE;
+    } else {
+        /* Disabled the pixel shader - color ops weren't applied
+         * while it was enabled, so re-apply them.
+         */
+        for(i=0; i < MAX_TEXTURES; i++) {
+            if(!isStateDirty(stateblock->wineD3DDevice, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
+                tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), 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
+    }
+}
+
 const struct StateEntry StateTable[] =
 {
       /* State name                                         representative,                                     apply function */
@@ -2204,4 +2258,6 @@ const struct StateEntry StateTable[] =
     { /*13, Sampler 13                              */      STATE_SAMPLER(13),                                  sampler             },
     { /*14, Sampler 14                              */      STATE_SAMPLER(14),                                  sampler             },
     { /*15, Sampler 15                              */      STATE_SAMPLER(15),                                  sampler             },
+    /* Pixel shader */
+    { /*  , Pixel Shader                            */      STATE_PIXELSHADER,                                  pixelshader         },
 };
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 360ed7b..1df81bb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -420,7 +420,10 @@ typedef void (*APPLYSTATEFUNC)(DWORD sta
 #define STATE_SAMPLER(num) (STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE) + 1 + (num))
 #define STATE_IS_SAMPLER(num) ((num) >= STATE_SAMPLER(0) && (num) <= STATE_SAMPLER(MAX_SAMPLERS - 1))
 
-#define STATE_HIGHEST (STATE_SAMPLER(MAX_SAMPLERS - 1))
+#define STATE_PIXELSHADER (STATE_SAMPLER(MAX_SAMPLERS - 1) + 1)
+#define STATE_IS_PIXELSHADER(a) ((a) == STATE_PIXELSHADER)
+
+#define STATE_HIGHEST (STATE_PIXELSHADER)
 
 struct StateEntry
 {
@@ -564,6 +567,7 @@ typedef struct IWineD3DDeviceImpl
     BOOL                    texture_shader_active;  /* TODO: Confirm use is correct */
     BOOL                    last_was_notclipped;
     BOOL                    untransformed;
+    BOOL                    last_was_pshader;
 
     /* State block related */
     BOOL                    isRecordingState;




More information about the wine-cvs mailing list