[12/16] WineD3D: Move the world matrix to the state table

Stefan Dösinger stefandoesinger at gmx.at
Mon Jan 1 18:29:03 CST 2007


This patch moves the world matrix to its own state. The rule is that  
the world matrix does not affect the vertex declaration, but the  
vertex declaration may affect the world matrix. The vertexdeclaration  
function will call a world matrix update if it is needed. This avoids  
reapplying the vertex declaration and stream sources needlessly when  
the world matrix is updated.

The final gl world matrix depends on the view matrix too, so the view  
matrix calls a world matrix update too if it isn't sheduled already.  
This avoids reapplying the light transformations needlessly when just  
the world matrix has changed.

-------------- next part --------------
From 184817f88427671e8c902650a8a8b12880f36e8c Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan_D=C3=B6singer?= <stefan at imac.local>
Date: Tue, 2 Jan 2007 01:02:54 +0100
Subject: [PATCH] WineD3D: Move the world matrix to the state table

---
 dlls/wined3d/device.c          |    7 +---
 dlls/wined3d/state.c           |   75 ++++++++++++++++++++++++++++------------
 dlls/wined3d/surface.c         |    2 +
 dlls/wined3d/wined3d_private.h |    1 -
 4 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index a99af91..4bcb047 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1931,7 +1931,6 @@ #endif
     }
 
     /* Initialize the current view state */
-    This->modelview_valid = 1;
     This->proj_valid = 0;
     This->view_ident = 1;
     This->last_was_rhw = 0;
@@ -2359,13 +2358,9 @@ static HRESULT  WINAPI  IWineD3DDeviceIm
      */
 
     /* Capture the times we can just ignore the change for now */
-    if (d3dts == WINED3DTS_WORLDMATRIX(0)) {
-        This->modelview_valid = FALSE;
-    } else if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
+    if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
         /* Handled by the state manager */
-    } else { /* What was requested!?? */
-        WARN("invalid matrix specified: %i\n", d3dts);
     }
 
     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index c41e736..3922ecf 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1803,6 +1803,29 @@ #endif
     }
 }
 
+static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock) {
+    /* Do not bother applying when we're in rhw mode. vertexdeclaration() will call
+     * transform_world if it switches out of rhw mode. This function is also called
+     * by transform_view below if the view matrix was changed
+     */
+    if(stateblock->wineD3DDevice->last_was_rhw) {
+        return;
+    }
+    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");
+    }
+}
+
 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock) {
     unsigned int k;
 
@@ -1813,12 +1836,9 @@ static void transform_view(DWORD state, 
      */
 
     PLIGHTINFOEL *lightChain = NULL;
-    stateblock->wineD3DDevice->modelview_valid = FALSE;
 
     glMatrixMode(GL_MODELVIEW);
     checkGLcall("glMatrixMode(GL_MODELVIEW)");
-    glPushMatrix();
-    checkGLcall("glPushMatrix()");
     glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
     checkGLcall("glLoadMatrixf(...)");
 
@@ -1837,11 +1857,20 @@ static void transform_view(DWORD state, 
         glClipPlane(GL_CLIP_PLANE0 + k, stateblock->clipplane[k]);
         checkGLcall("glClipPlane");
     }
-    glPopMatrix();
-    checkGLcall("glPopMatrix()");
 
-    /* Call the vdecl update. Will be tidied up later */
-    StateTable[STATE_VDECL].apply(STATE_VDECL, stateblock);
+    if(stateblock->wineD3DDevice->last_was_rhw) {
+        glLoadIdentity();
+        checkGLcall("glLoadIdentity()");
+        /* No need to update the world matrix, the identity is fine */
+        return;
+    }
+
+    /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
+     * No need to do it here if the state is scheduled for update.
+     */
+    if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
+        transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock);
+    }
 }
 
 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateBlock) {
@@ -1857,6 +1886,7 @@ static const GLfloat invymat[16] = {
 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock) {
     BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
     BOOL transformed, lit;
+    BOOL wasrhw = stateblock->wineD3DDevice->last_was_rhw;
 
     stateblock->wineD3DDevice->streamFixedUp = FALSE;
  	
@@ -1934,23 +1964,22 @@ static void vertexdeclaration(DWORD stat
     } else {
 
         /* Untransformed, so relies on the view and projection matrices */
+        stateblock->wineD3DDevice->last_was_rhw = FALSE;
+        /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
         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");
-            }
+ 
+ 		/* Don't bother checking for !useVertexShaderFunction here. If shaders are always on wasrhw will never
+ 		 * be true. If they are switched on and off then knowing that the fixed function matrices are ok makes
+ 		 * those switches cheaper
+ 		 */
+        if (wasrhw) {
+            /* switching out of orthogonal mode? have to reapply the modelview matrix.
+             * Only do that when it is not dirty though
+ 			 */
+            if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
+                transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock);
+ 			}
         }
 
         if (!useVertexShaderFunction) {
@@ -2752,7 +2781,7 @@ const struct StateEntry StateTable[] =
     { /*254, undefined                              */      0,                                                  state_undefined     },
     { /*255, undefined                              */      0,                                                  state_undefined     },
       /* End huge gap */
-    { /*256, WINED3DTS_WORLDMATRIX(0)               */      STATE_VDECL,                                        vertexdeclaration   },
+    { /*256, WINED3DTS_WORLDMATRIX(0)               */      STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)),          transform_world     },
     { /*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/surface.c b/dlls/wined3d/surface.c
index b3799da..333036e 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1150,6 +1150,7 @@ static HRESULT WINAPI IWineD3DSurfaceImp
                we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
                per drawprim (and leave set - it will sort itself out due to last_was_rhw */
             d3ddevice_set_ortho(This->resource.wineD3DDevice);
+            IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
 
             if (iface ==  implSwapChain->frontBuffer) {
                 glDrawBuffer(GL_FRONT);
@@ -2473,6 +2474,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
             /* Draw a textured quad
              */
             d3ddevice_set_ortho(This->resource.wineD3DDevice);
+            IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
 
             glBegin(GL_QUADS);
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 51fc796..3a28d6c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -563,7 +563,6 @@ typedef struct IWineD3DDeviceImpl
     const shader_backend_t *shader_backend;
 
     /* Optimization */
-    BOOL                    modelview_valid;
     BOOL                    proj_valid;
     BOOL                    view_ident;        /* true iff view matrix is identity                */
     BOOL                    last_was_rhw;      /* true iff last draw_primitive was in xyzrhw mode */
-- 
1.4.2.4



More information about the wine-patches mailing list