[6/10] WineD3D: Move the world matrix to the state table

Stefan Dösinger stefandoesinger at gmx.at
Tue Jan 2 15:47:39 CST 2007


From 3e9a03c83a2a14d73c1e72b598a162d0025e0d5d Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan_D=C3=B6singer?= <stefan at imac.local>
Date: Tue, 2 Jan 2007 19:41:37 +0100
Subject: [PATCH] WineD3D: Move the world matrix to the state table

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

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 268c0b0..7eadb20 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1936,7 +1936,6 @@ #endif
     }
 
     /* Initialize the current view state */
-    This->modelview_valid = 1;
     This->proj_valid = 0;
     This->view_ident = 1;
     This->last_was_rhw = 0;
@@ -2364,13 +2363,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 9e6f15c..334d430 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) {
@@ -1859,6 +1888,7 @@ static void vertexdeclaration(DWORD stat
     BOOL transformed, lit;
     /* Some stuff is in the device until we have per context tracking */
     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
+    BOOL wasrhw = device->last_was_rhw;
 
     device->streamFixedUp = FALSE;
  	
@@ -1935,22 +1965,20 @@ static void vertexdeclaration(DWORD stat
     } else {
 
         /* Untransformed, so relies on the view and projection matrices */
+        device->last_was_rhw = FALSE;
+        /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
         device->untransformed = TRUE;
 
-        if (!useVertexShaderFunction) {
-            device->modelview_valid = TRUE;
-            glMatrixMode(GL_MODELVIEW);
-            checkGLcall("glMatrixMode");
-
-            /* In the general case, the view matrix is the identity matrix */
-            if (device->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(device, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
+                transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock);
             }
         }
 
@@ -2753,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 d3259ef..5cf43f1 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 7e41f5c..7b5eaa1 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