[11/16] WineD3D: Move the functionality of primitiveInitState to the state table

Stefan Dösinger stefandoesinger at gmx.at
Mon Jan 1 18:22:39 CST 2007


This is mainly a code move for now, the following patches will tidy  
the thing up and make setting the matrices more efficient.
-------------- next part --------------
From ad275bc26b8e90a5c157a49065b51ef929248795 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan_D=C3=B6singer?= <stefan at imac.local>
Date: Tue, 2 Jan 2007 00:56:20 +0100
Subject: [PATCH] WineD3D: Move the functionality of primitiveinitstate to the state table

---
 dlls/wined3d/device.c          |   15 -----
 dlls/wined3d/drawprim.c        |  123 --------------------------------------
 dlls/wined3d/state.c           |  131 ++++++++++++++++++++++++++++++++++++----
 dlls/wined3d/wined3d_private.h |    1 
 4 files changed, 119 insertions(+), 151 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index ec79793..a99af91 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2361,21 +2361,6 @@ static HRESULT  WINAPI  IWineD3DDeviceIm
     /* Capture the times we can just ignore the change for now */
     if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
         This->modelview_valid = FALSE;
-        return WINED3D_OK;
-
-    } else if (d3dts == WINED3DTS_PROJECTION) {
-        This->proj_valid = FALSE;
-        return WINED3D_OK;
-
-    } else if (d3dts >= WINED3DTS_WORLDMATRIX(1) && d3dts <= WINED3DTS_WORLDMATRIX(255)) {
-        /* Indexed Vertex Blending Matrices 256 -> 511  */
-        /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
-        FIXME("WINED3DTS_WORLDMATRIX(1..255) not handled\n");
-        return WINED3D_OK;
-    }
-
-    if (d3dts >= WINED3DTS_TEXTURE0 && d3dts <= WINED3DTS_TEXTURE7) { /* handle texture matrices */
-        /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
     } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
         /* Handled by the state manager */
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 12d2a11..df357a7 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -227,116 +227,6 @@ void d3ddevice_set_ortho(IWineD3DDeviceI
         }
     }
 }
-/* Setup views - Transformed & lit if RHW, else untransformed.
-       Only unlit if Normals are supplied
-    Returns: Whether to restore lighting afterwards           */
-static void primitiveInitState(
-    IWineD3DDevice *iface,
-    WineDirect3DVertexStridedData* strided,
-    BOOL useVS,
-    BOOL* lighting_changed,
-    BOOL* lighting_original) {
-
-    BOOL fixed_vtx_transformed =
-       (strided->u.s.position.lpData != NULL || strided->u.s.position.VBO != 0 ||
-        strided->u.s.position2.lpData != NULL || strided->u.s.position2.VBO != 0) && 
-        strided->u.s.position_transformed;
-
-    BOOL fixed_vtx_lit = 
-        strided->u.s.normal.lpData == NULL && strided->u.s.normal.VBO == 0 &&
-        strided->u.s.normal2.lpData == NULL && strided->u.s.normal2.VBO == 0;
-
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-
-    *lighting_changed = FALSE;
-
-    /* If no normals, DISABLE lighting otherwise, don't touch lighing as it is
-       set by the appropriate render state. Note Vertex Shader output is already lit */
-    if (fixed_vtx_lit || useVS) {
-        *lighting_changed = TRUE;
-        *lighting_original = glIsEnabled(GL_LIGHTING);
-        glDisable(GL_LIGHTING);
-        checkGLcall("glDisable(GL_LIGHTING);");
-        TRACE("Disabled lighting, old state = %d\n", *lighting_original);
-    }
-
-    if (!useVS && fixed_vtx_transformed) {
-        d3ddevice_set_ortho(This);
-
-    } else {
-
-        /* Untransformed, so relies on the view and projection matrices */
-        This->untransformed = TRUE;
-
-        if (!useVS && (This->last_was_rhw || !This->modelview_valid)) {
-            /* Only reapply when have to */
-            This->modelview_valid = TRUE;
-            glMatrixMode(GL_MODELVIEW);
-            checkGLcall("glMatrixMode");
-
-            /* In the general case, the view matrix is the identity matrix */
-            if (This->view_ident) {
-                glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
-                checkGLcall("glLoadMatrixf");
-            } else {
-                glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
-                checkGLcall("glLoadMatrixf");
-                glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
-                checkGLcall("glMultMatrixf");
-            }
-        }
-
-        if (!useVS && (This->last_was_rhw || !This->proj_valid)) {
-            /* Only reapply when have to */
-            This->proj_valid = TRUE;
-            glMatrixMode(GL_PROJECTION);
-            checkGLcall("glMatrixMode");
-
-            /* The rule is that the window coordinate 0 does not correspond to the
-               beginning of the first pixel, but the center of the first pixel.
-               As a consequence if you want to correctly draw one line exactly from
-               the left to the right end of the viewport (with all matrices set to
-               be identity), the x coords of both ends of the line would be not
-               -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
-               instead.                                                               */
-            glLoadIdentity();
-
-            glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0);
-            checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
-
-            /* D3D texture coordinates are flipped compared to OpenGL ones, so
-             * render everything upside down when rendering offscreen. */
-            if (This->render_offscreen) {
-                glMultMatrixf(invymat);
-                checkGLcall("glMultMatrixf(invymat)");
-            }
-            glMultMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
-            checkGLcall("glLoadMatrixf");
-        }
-
-        /* Vertex Shader output is already transformed, so set up identity matrices */
-        if (useVS) {
-            This->posFixup[1] = This->render_offscreen ? -1.0 : 1.0;
-            This->posFixup[2] = 0.9 / This->stateBlock->viewport.Width;
-            This->posFixup[3] = -0.9 / This->stateBlock->viewport.Height;
-        }
-        This->last_was_rhw = FALSE;
-
-        /* Setup fogging */
-        if (useVS && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->usesFog) {
-            /* In D3D vertex shader return the 'final' fog value, while in OpenGL it is the 'input' fog value.
-             * The code below 'disables' the OpenGL postprocessing by setting the formula to '1'. */
-            glFogi(GL_FOG_MODE, GL_LINEAR);
-            glFogf(GL_FOG_START, 1.0f);
-            glFogf(GL_FOG_END, 0.0f);
-
-        } else if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] 
-                  && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != WINED3DFOG_NONE) {
-            /* Reapply the fog */
-            StateTable[STATE_RENDER(WINED3DRS_FOGENABLE)].apply(STATE_RENDER(WINED3DRS_FOGSTART), This->stateBlock);
-        }
-    }
-}
 
 static BOOL fixed_get_input(
     BYTE usage, BYTE usage_idx,
@@ -1947,8 +1837,6 @@ void drawPrimitive(IWineD3DDevice *iface
     DWORD                         dirtyState, idx;
     BYTE                          shift;
 
-    BOOL lighting_changed, lighting_original = FALSE;
-
     /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software - 
      * here simply check whether a shader was set, or the user disabled shaders */
     if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader && 
@@ -1980,6 +1868,7 @@ void drawPrimitive(IWineD3DDevice *iface
         StateTable[dirtyState].apply(dirtyState, This->stateBlock);
     }
     This->numDirtyEntries = 0; /* This makes the whole list clean */
+    fixup = This->streamFixedUp;
 
     if (TRACE_ON(d3d_draw) && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
         check_fbo_status(iface);
@@ -1990,9 +1879,6 @@ void drawPrimitive(IWineD3DDevice *iface
     }
     This->depth_copy_state = WINED3D_DCS_INITIAL;
 
-    /* Setup transform matrices and sort out */
-    primitiveInitState(iface, &This->strided_streams, useVertexShaderFunction, &lighting_changed, &lighting_original);
-
     /* Now initialize the materials state */
     init_materials(iface, (This->strided_streams.u.s.diffuse.lpData != NULL || This->strided_streams.u.s.diffuse.VBO != 0));
 
@@ -2009,13 +1895,6 @@ void drawPrimitive(IWineD3DDevice *iface
             idxData, idxSize, minIndex, StartIdx, fixup);
     }
 
-    /* If vertex shaders or no normals, restore previous lighting state */
-    if (lighting_changed) {
-        if (lighting_original) glEnable(GL_LIGHTING);
-        else glDisable(GL_LIGHTING);
-        TRACE("Restored lighting to original state\n");
-    }
-
     /* Finshed updating the screen, restore lock */
     LEAVE_GL();
     TRACE("Done all gl drawing\n");
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 89701b4..c41e736 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -71,6 +71,8 @@ static void state_fillmode(DWORD state, 
     }
 }
 
+#if 0
+/* if 0ed because it will be revived later */
 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock) {
 
     /* TODO: Lighting is only enabled if Vertex normals are passed by the application,
@@ -85,6 +87,7 @@ static void state_lighting(DWORD state, 
         checkGLcall("glDisable GL_LIGHTING");
     }
 }
+#endif
 
 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock) {
     switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
@@ -646,7 +649,6 @@ static void state_fog(DWORD state, IWine
     tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
     fogend = tmpvalue.f;
 
-#if 0
     /* Activate when vertex shaders are in the state table */
     if(stateblock->vertexShader && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function &&
        ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->usesFog) {
@@ -656,17 +658,14 @@ #if 0
         fogend = 0.0;
         stateblock->wineD3DDevice->last_was_foggy_shader = TRUE;
     }
-#endif
-
     /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
      * the system will apply only pixel(=table) fog effects."
      */
-    /* else */ if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
+	else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
         glHint(GL_FOG_HINT, GL_FASTEST);
         checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
-#if 0
         stateblock->wineD3DDevice->last_was_foggy_shader = FALSE;
-#endif
+
         switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
             /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
              * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
@@ -727,9 +726,8 @@ #endif
     } else {
         glHint(GL_FOG_HINT, GL_NICEST);
         checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
-#if 0
         stateblock->wineD3DDevice->last_was_foggy_shader = FALSE;
-#endif
+
         switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
             case D3DFOG_EXP:
                 glFogi(GL_FOG_MODE, GL_EXP);
@@ -1841,24 +1839,42 @@ static void transform_view(DWORD state, 
     }
     glPopMatrix();
     checkGLcall("glPopMatrix()");
+
+    /* Call the vdecl update. Will be tidied up later */
+    StateTable[STATE_VDECL].apply(STATE_VDECL, stateblock);
 }
 
 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateBlock) {
 	WARN("World matrix 1 - 255 not supported yet\n");
 }
 
+static const GLfloat invymat[16] = {
+    1.0f, 0.0f, 0.0f, 0.0f,
+    0.0f, -1.0f, 0.0f, 0.0f,
+    0.0f, 0.0f, 1.0f, 0.0f,
+    0.0f, 0.0f, 0.0f, 1.0f};
+
 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock) {
-    BOOL useVertexShaderFunction = FALSE;
+    BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
+    BOOL transformed, lit;
+
     stateblock->wineD3DDevice->streamFixedUp = FALSE;
  	
     /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software - 
      * here simply check whether a shader was set, or the user disabled shaders
      */
     if (stateblock->wineD3DDevice->vs_selected_mode != SHADER_NONE && stateblock->vertexShader && 
-       ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) 
+       ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
         useVertexShaderFunction = TRUE;
 
-        if(stateblock->wineD3DDevice->up_strided) {
+        if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->usesFog != stateblock->wineD3DDevice->last_was_foggy_shader) {
+            updateFog = TRUE;
+        }
+    } else if(stateblock->wineD3DDevice->last_was_foggy_shader) {
+        updateFog = TRUE;
+    }
+
+    if(stateblock->wineD3DDevice->up_strided) {
 
         /* Note: this is a ddraw fixed-function code path */
         TRACE("================ Strided Input ===================\n");
@@ -1890,6 +1906,93 @@ static void vertexdeclaration(DWORD stat
         primitiveConvertToStridedData((IWineD3DDevice *) stateblock->wineD3DDevice, &stateblock->wineD3DDevice->strided_streams,
  									   &stateblock->wineD3DDevice->streamFixedUp);
      }
+	/* Do I have to use ? TRUE : FALSE ? Or can I rely on 15==15 beeing equal to TRUE(=1)? */
+	transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
+		            stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
+			       stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
+	lit = stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData == NULL &&
+		  stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO == 0;
+
+	if(transformed != stateblock->wineD3DDevice->last_was_rhw && !useVertexShaderFunction) {
+		updateFog = TRUE;
+	}
+
+	/* TODO: The vertex declaration changes lighting, but lighting doesn't affect the vertex declaration and the
+	 * stream sources. This can be handled nicer
+	 */
+	if(stateblock->renderState[WINED3DRS_LIGHTING] && !lit) {
+		glEnable(GL_LIGHTING);
+		checkGLcall("glEnable(GL_LIGHTING)");
+	} else {
+		glDisable(GL_LIGHTING);
+		checkGLcall("glDisable(GL_LIGHTING");
+	}
+
+    if (!useVertexShaderFunction && transformed) {
+        d3ddevice_set_ortho(stateblock->wineD3DDevice);
+
+    } else {
+
+        /* Untransformed, so relies on the view and projection matrices */
+        stateblock->wineD3DDevice->untransformed = TRUE;
+
+        if (!useVertexShaderFunction) {
+            stateblock->wineD3DDevice->modelview_valid = TRUE;
+            glMatrixMode(GL_MODELVIEW);
+            checkGLcall("glMatrixMode");
+
+            /* In the general case, the view matrix is the identity matrix */
+            if (stateblock->wineD3DDevice->view_ident) {
+                glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
+                checkGLcall("glLoadMatrixf");
+            } else {
+                glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
+                checkGLcall("glLoadMatrixf");
+                glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
+                checkGLcall("glMultMatrixf");
+            }
+        }
+
+        if (!useVertexShaderFunction) {
+            stateblock->wineD3DDevice->proj_valid = TRUE;
+            glMatrixMode(GL_PROJECTION);
+            checkGLcall("glMatrixMode");
+
+            /* The rule is that the window coordinate 0 does not correspond to the
+               beginning of the first pixel, but the center of the first pixel.
+               As a consequence if you want to correctly draw one line exactly from
+               the left to the right end of the viewport (with all matrices set to
+               be identity), the x coords of both ends of the line would be not
+               -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
+               instead.                                                               */
+            glLoadIdentity();
+
+            glTranslatef(0.9 / stateblock->viewport.Width, -0.9 / stateblock->viewport.Height, 0);
+            checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
+
+            /* D3D texture coordinates are flipped compared to OpenGL ones, so
+             * render everything upside down when rendering offscreen. */
+            if (stateblock->wineD3DDevice->render_offscreen) {
+                glMultMatrixf(invymat);
+                checkGLcall("glMultMatrixf(invymat)");
+            }
+            glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
+            checkGLcall("glLoadMatrixf");
+        }
+
+        /* Vertex Shader output is already transformed, so set up identity matrices */
+        if (useVertexShaderFunction) {
+            stateblock->wineD3DDevice->posFixup[1] = stateblock->wineD3DDevice->render_offscreen ? -1.0 : 1.0;
+            stateblock->wineD3DDevice->posFixup[2] = 0.9 / stateblock->viewport.Width;
+            stateblock->wineD3DDevice->posFixup[3] = -0.9 / stateblock->viewport.Height;
+        }
+        stateblock->wineD3DDevice->last_was_rhw = FALSE;
+    }
+
+    /* Setup fogging */
+	if(updateFog) {
+		state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock);
+	}
 }
 
 const struct StateEntry StateTable[] =
@@ -2033,7 +2136,7 @@ const struct StateEntry StateTable[] =
     { /*134, WINED3DRS_WRAP6                        */      STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          },
     { /*135, WINED3DRS_WRAP7                        */      STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          },
     { /*136, WINED3DRS_CLIPPING                     */      STATE_RENDER(WINED3DRS_CLIPPING),                   state_clipping      },
-    { /*137, WINED3DRS_LIGHTING                     */      STATE_RENDER(WINED3DRS_LIGHTING) /* Vertex decl! */,state_lighting      },
+    { /*137, WINED3DRS_LIGHTING                     */      STATE_VDECL,                                        vertexdeclaration   },
     { /*138, WINED3DRS_EXTENTS                      */      STATE_RENDER(WINED3DRS_EXTENTS),                    state_extents       },
     { /*139, WINED3DRS_AMBIENT                      */      STATE_RENDER(WINED3DRS_AMBIENT),                    state_ambient       },
     { /*140, WINED3DRS_FOGVERTEXMODE                */      STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog           },
@@ -2394,7 +2497,7 @@ const struct StateEntry StateTable[] =
       /* Transform states follow                    */
     { /*  1, undefined                              */      0,                                                  state_undefined     },
     { /*  2, WINED3DTS_VIEW                         */      STATE_TRANSFORM(WINED3DTS_VIEW),                    transform_view      },
-    { /*  3, WINED3DTS_PROJECTION                   */      STATE_TRANSFORM(WINED3DTS_PROJECTION),              state_undefined     },
+    { /*  3, WINED3DTS_PROJECTION                   */      STATE_VDECL,                                        vertexdeclaration   },
     { /*  4, undefined                              */      0,                                                  state_undefined     },
     { /*  5, undefined                              */      0,                                                  state_undefined     },
     { /*  6, undefined                              */      0,                                                  state_undefined     },
@@ -2649,7 +2752,7 @@ const struct StateEntry StateTable[] =
     { /*254, undefined                              */      0,                                                  state_undefined     },
     { /*255, undefined                              */      0,                                                  state_undefined     },
       /* End huge gap */
-    { /*256, WINED3DTS_WORLDMATRIX(0)               */      STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)),          state_undefined     },
+    { /*256, WINED3DTS_WORLDMATRIX(0)               */      STATE_VDECL,                                        vertexdeclaration   },
     { /*257, WINED3DTS_WORLDMATRIX(1)               */      STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)),          transform_worldex   },
     { /*258, WINED3DTS_WORLDMATRIX(2)               */      STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)),          transform_worldex   },
     { /*259, WINED3DTS_WORLDMATRIX(3)               */      STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)),          transform_worldex   },
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 119f053..51fc796 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -581,6 +581,7 @@ #define                         NEEDS_DI
     BOOL                    last_was_notclipped;
     BOOL                    untransformed;
     BOOL                    last_was_pshader;
+    BOOL                    last_was_foggy_shader;
 
     /* State block related */
     BOOL                    isRecordingState;
-- 
1.4.2.4

-------------- next part --------------



More information about the wine-patches mailing list