[16/19] Add pixel shaders to the state table

Stefan Dösinger stefan at codeweavers.com
Tue Dec 19 16:22:19 CST 2006


This patch makes things easier :-) The hacks in SetPixelShader can be removed, 
this is handled properly now by the pixel shader state. Having the pixel 
shader in the state table allows putting the nvrc texture unit mapping back 
too.

the pixelshader handling function can't activate the shader yet because glsl 
shaders need both pixel and vertex shaders compiled and available, so this is 
still in drawPrim until vertex shaders are handled by the state table too.
-------------- next part --------------
From 433652a4a93c8aecf7ea0232ba7163b7db542f3f Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Mon, 18 Dec 2006 17:10:36 +0100
Subject: [PATCH] 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 c5b173f..e39db9d 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3686,37 +3686,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 @@ #undef BUFFER_OR_DATA
         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 1e07ca5..f5e52f3 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 ab81162..1054f5f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -420,7 +420,10 @@ #define STATE_IS_TEXTURESTAGE(a) ((a) >=
 #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 @@ #define                         NEEDS_DI
     BOOL                    texture_shader_active;  /* TODO: Confirm use is correct */
     BOOL                    last_was_notclipped;
     BOOL                    untransformed;
+    BOOL                    last_was_pshader;
 
     /* State block related */
     BOOL                    isRecordingState;
-- 
1.4.2.4



More information about the wine-patches mailing list