[16/16] WineD3D: Some matrix handling cleanup

Stefan Dösinger stefandoesinger at gmx.at
Mon Jan 1 18:45:08 CST 2007


This patch does some additional cleanup which didn't really fit into  
the world and projection matrix patches. It removes  
d3ddevice_set_ortho to have all matrix functionality in the world and  
projection states. UnlockRect and BltOverride set this->last_was_rhw  
and perform an immediate matrix application. Then the vertex decl is  
dirtified to force restoring last_was_rhw and the matrices on the  
next draw.


-------------- next part --------------
From 3938250a55f29dedc6518af49c5cdb0be9c69318 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan_D=C3=B6singer?= <stefan at imac.local>
Date: Mon, 1 Jan 2007 22:29:03 +0100
Subject: [PATCH] WineD3D: Some matrix handling cleanup

---
 dlls/wined3d/device.c          |    3 -
 dlls/wined3d/drawprim.c        |   16 -------
 dlls/wined3d/state.c           |   92 +++++++++++++++++++++++-----------------
 dlls/wined3d/surface.c         |    8 ++-
 dlls/wined3d/wined3d_private.h |    3 -
 5 files changed, 58 insertions(+), 64 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 4bcb047..9f7531f 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1931,7 +1931,6 @@ #endif
     }
 
     /* Initialize the current view state */
-    This->proj_valid = 0;
     This->view_ident = 1;
     This->last_was_rhw = 0;
     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
@@ -5856,7 +5855,7 @@ static void device_render_to_texture(IWi
         This->depth_copy_state = WINED3D_DCS_COPY;
     }
     This->last_was_rhw = FALSE;
-    This->proj_valid = FALSE;
+    /* Viewport state will reapply the projection matrix for now */
     IWineD3DDeviceImpl_MarkStateDirty(This, WINED3DRS_CULLMODE);
 
     /* Restore recording */
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 7fe492a..d9c56a0 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -155,22 +155,6 @@ static const GLfloat invymat[16] = {
 	0.0f, 0.0f, 1.0f, 0.0f,
 	0.0f, 0.0f, 0.0f, 1.0f};
 
-void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
-    /* If the last draw was transformed as well, no need to reapply all the matrixes */
-    if ( (!This->last_was_rhw) || (This->viewport_changed) ) {
-        This->last_was_rhw = TRUE;
-        This->viewport_changed = FALSE;
-
-        /* Transformed already into viewport coordinates, so we do not need transform
-            matrices. Reset all matrices to identity and leave the default matrix in world
-            mode.                                                                         */
-        glMatrixMode(GL_MODELVIEW);
-        checkGLcall("glMatrixMode(GL_MODELVIEW)");
-        glLoadIdentity();
-        checkGLcall("glLoadIdentity");
-    }
-}
-
 static BOOL fixed_get_input(
     BYTE usage, BYTE usage_idx,
     unsigned int* regnum) {
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index de0a17f..7820a6a 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1811,25 +1811,30 @@ #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
+    /* This function is called by transform_view below if the view matrix was changed too
+     *
+     * Deliberately no check if the vertex declaration is dirty because the vdecl state
+     * does not always update the world matrix, only on a switch between transformed
+     * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one
+     * draw, but that should be rather rare and cheaper in total.
      */
-    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");
+    if(stateblock->wineD3DDevice->last_was_rhw) {
+        glLoadIdentity();
+        checkGLcall("glLoadIdentity()");
     } 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");
+        /* 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");
+        }
     }
 }
 
@@ -2028,50 +2033,57 @@ static void vertexdeclaration(DWORD stat
     }
 
     if (!useVertexShaderFunction && transformed) {
-        d3ddevice_set_ortho(stateblock->wineD3DDevice);
-
+        stateblock->wineD3DDevice->last_was_rhw = TRUE;
     } 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;
-
  
- 		/* 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) {
-            stateblock->wineD3DDevice->proj_valid = TRUE;
-        }
+        /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
+         * Not needed as long as only hw shaders are supported
+         */
 
-        /* Vertex Shader output is already transformed, so set up identity matrices */
+        /* This sets the shader output position correction constants.
+         * TODO: Move to the viewport state
+         */
         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;
     }
 
-    /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
-     * or transformed / untransformed was switched
+    /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
+     * off this function will be called again anyway to make sure they're properly set
      */
-    if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
-        transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock);
+    if(!useVertexShaderFunction) {
+
+        /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
+         * or transformed / untransformed was switched
+         */
+        if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
+            transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock);
+        }
+        /* World matrix needs reapplication here only if we're switching between rhw and non-rhw 
+         * mode.
+         *
+         * If a vertex shader is used, the world matrix changed and then vertex shader unbound
+         * this check will fail and the matrix not applied again. This is OK because a simple
+         * world matrix change reapplies the matrix - These checks here are only to satisfy the
+         * needs of the vertex declaration.
+         *
+         * World and view matrix go into the same gl matrix, so only apply them when neither is
+         * dirty
+         */
+         if(transformed != wasrhw &&
+            !isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
+            !isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_VIEW))) {
+            transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock);
+        }
     }
 
-    /* Setup fogging */
 	if(updateFog) {
 		state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock);
 	}
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index a349c35..765efa6 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1156,9 +1156,10 @@ static HRESULT WINAPI IWineD3DSurfaceImp
             /* glDrawPixels transforms the raster position as though it was a vertex -
                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);
-            /* Apply the projection matrix, it sets up orthogonal projection due to last_was_rhw */
+            myDevice->last_was_rhw = TRUE;
+            /* Apply the projection and world matrices, it sets up orthogonal projection due to last_was_rhw */
             StateTable[STATE_TRANSFORM(WINED3DTS_PROJECTION)].apply(STATE_TRANSFORM(WINED3DTS_PROJECTION), myDevice->stateBlock);
+            StateTable[STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))].apply(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), myDevice->stateBlock);
             /* Will reapply the projection matrix too */
             IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
 
@@ -2483,9 +2484,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
 
             /* Draw a textured quad
              */
-            d3ddevice_set_ortho(This->resource.wineD3DDevice);
+            myDevice->last_was_rhw = TRUE;
             /* Apply the projection matrix, it sets up orthogonal projection due to last_was_rhw */
             StateTable[STATE_TRANSFORM(WINED3DTS_PROJECTION)].apply(STATE_TRANSFORM(WINED3DTS_PROJECTION), myDevice->stateBlock);
+            StateTable[STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))].apply(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), myDevice->stateBlock);
             /* That will reapply the projection matrix too */
             IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 3a28d6c..47ffcac 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                    proj_valid;
     BOOL                    view_ident;        /* true iff view matrix is identity                */
     BOOL                    last_was_rhw;      /* true iff last draw_primitive was in xyzrhw mode */
     BOOL                    viewport_changed;  /* Was the viewport changed since the last draw?   */
@@ -705,8 +704,6 @@ typedef struct PrivateData
     DWORD size;
 } PrivateData;
 
-void d3ddevice_set_ortho(IWineD3DDeviceImpl *This);
-
 /*****************************************************************************
  * IWineD3DResource implementation structure
  */
-- 
1.4.2.4

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



More information about the wine-patches mailing list