[dx69+70] FPS + SetTransform transformation

Ann and Jason Edmeades us at the-edmeades.demon.co.uk
Wed Jul 16 18:10:53 CDT 2003


This was to be two patches but I didnt save the intermediate files, so
heres the merged version. Again, I only take credit for merging in the
work, the hard bit was done by Lucho.
(Tested againsts wc3, MaxPayne, UT2003demo, OperationFlashpoint and they
all were still playable!)

Note: I had a concern about calling gettimeofday, but I saw it was
already used in dlls\ntdll\time.c and I think I have done the right
includes.

Changelog
Add fps debug channel, so we can see how the d3d code is performing and
their impact of performance changes
SetTransform almost rewritten in a much neater way, and in coordination
with drawprim it significantly reduces the number of times that we
reload the matrixes.

Jason
-------------- next part --------------
Index: dlls/d3d8/d3d8_private.h
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/d3d8_private.h,v
retrieving revision 1.40
diff -u -r1.40 d3d8_private.h
--- dlls/d3d8/d3d8_private.h	3 Jul 2003 18:10:22 -0000	1.40
+++ dlls/d3d8/d3d8_private.h	16 Jul 2003 22:51:54 -0000
@@ -326,10 +326,11 @@
     UINT                          currentPalette;
 
     /* Optimization */
-    D3DMATRIX                     lastProj;
-    D3DMATRIX                     lastView;
-    D3DMATRIX                     lastWorld0;
-    D3DMATRIX                     lastTexTrans[8];
+    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 */
+
 
     /* OpenGL related */
     GLXContext                    glCtx;
Index: dlls/d3d8/device.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/device.c,v
retrieving revision 1.75
diff -u -r1.75 device.c
--- dlls/d3d8/device.c	15 Jul 2003 20:52:21 -0000	1.75
+++ dlls/d3d8/device.c	16 Jul 2003 22:52:01 -0000
@@ -45,6 +45,14 @@
 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
 IDirect3DPixelShaderImpl*             PixelShaders[64];
 
+/* For fps support: */
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+WINE_DECLARE_DEBUG_CHANNEL(fps);
+static long prev_time = 0, frames = 0;
+
+/* Debugging aids: */
 #ifdef FRAME_DEBUGGING
 BOOL isOn             = FALSE;
 BOOL isDumpingFrames  = FALSE;
@@ -109,6 +117,47 @@
     TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
 }
 
+/* Setup this textures matrix */
+static void set_texture_matrix(float *smat, DWORD flags)
+{
+    float mat[16];
+
+    glMatrixMode(GL_TEXTURE);
+
+    if (flags == D3DTTFF_DISABLE) {
+        glLoadIdentity();
+        checkGLcall("glLoadIdentity()");
+        return;
+    }
+
+    if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
+        ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
+        checkGLcall("glLoadIdentity()");
+        return;
+    }
+
+    memcpy(mat, smat, 16*sizeof(float));
+
+    switch (flags & ~D3DTTFF_PROJECTED) {
+    case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
+    case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
+    default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
+    }
+    
+    if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
+    case D3DTTFF_COUNT2:
+        mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
+        mat[1] = mat[5] = mat[9] = mat[13] = 0;
+        break;
+    case D3DTTFF_COUNT3:
+        mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
+        mat[2] = mat[6] = mat[10] = mat[14] = 0;
+        break;
+    }
+    glLoadMatrixf(mat);
+    checkGLcall("glLoadMatrixf(mat)");
+}
+
 /* IDirect3D IUnknown parts follow: */
 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
 {
@@ -322,6 +371,21 @@
     /* Dont call checkGLcall, as glGetError is not applicable here */
     TRACE("glXSwapBuffers called, Starting new frame\n");
 
+    /* FPS support */
+    if (__WINE_GET_DEBUGGING(_TRACE,(__wine_dbch_fps))) {
+        long time; /* in milliseconds */
+        struct timeval tv;
+        frames++;
+        gettimeofday(&tv, NULL);
+        time = tv.tv_usec/1000 + tv.tv_sec*1000;
+        /* every 1.5 seconds */
+        if (time - prev_time > 1500) {
+            TRACE_(fps)("@@@ %.2ffps\n", 1000.0*frames/(time - prev_time));
+            prev_time = time;
+            frames = 0;
+        }
+    }
+
 #if defined(FRAME_DEBUGGING)
 {
     if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
@@ -1244,268 +1308,110 @@
 }
 HRESULT  WINAPI  IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
     ICOM_THIS(IDirect3DDevice8Impl,iface);
-    D3DMATRIX m;
     int k;
-    float f;
-    BOOL viewChanged = TRUE;
-    int  Stage;
 
     /* Most of this routine, comments included copied from ddraw tree initially: */
     TRACE("(%p) : State=%d\n", This, d3dts);
 
-    This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
-    This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
-    memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
-
     /* Handle recording of state blocks */
     if (This->isRecordingState) {
         TRACE("Recording... not performing anything\n");
+        This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
+        This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
+        memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
         return D3D_OK;
     }
 
     /*
-       ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
-
-       where ViewMat = Camera space, WorldMat = world space.
-
-       In OpenGL, camera and world space is combined into GL_MODELVIEW
-       matrix.  The Projection matrix stay projection matrix. */
-
-    /* After reading through both OpenGL and Direct3D documentations, I
-       thought that D3D matrices were written in 'line major mode' transposed
-       from OpenGL's 'column major mode'. But I found out that a simple memcpy
-       works fine to transfer one matrix format to the other (it did not work
-       when transposing)....
-
-       So :
-        1) are the documentations wrong
-        2) does the matrix work even if they are not read correctly
-        3) is Mesa's implementation of OpenGL not compliant regarding Matrix
-           loading using glLoadMatrix ?
-
-       Anyway, I always use 'conv_mat' to transfer the matrices from one format
-       to the other so that if I ever find out that I need to transpose them, I
-       will able to do it quickly, only by changing the macro conv_mat. */
-
-    if (d3dts < 256) { 
-      switch (d3dts) {
-      case D3DTS_VIEW:
-        conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
-        break;
-
-      case D3DTS_PROJECTION:
-        conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
-        break;
-
-      case D3DTS_TEXTURE0:
-      case D3DTS_TEXTURE1:
-      case D3DTS_TEXTURE2:
-      case D3DTS_TEXTURE3:
-      case D3DTS_TEXTURE4:
-      case D3DTS_TEXTURE5:
-      case D3DTS_TEXTURE6:
-      case D3DTS_TEXTURE7:
-        conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
-        break;
-
-      default:
-        FIXME("Unhandled transform state!!\n");
-        break;
-      }
+     * if the new matrix is the same as the current one,
+     * we cut off any further processing. this seems to be a reasonable
+     * optimization because as was noticed, some apps (warcraft3 for example)
+     * tend towards setting the same matrix repeatedly for some dumb reason.
+     *
+     * From here on we assume that the new matrix is different, wherever it matters
+     * but note
+     */
+    if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
+        TRACE("The app is setting the same matrix over again\n");
+        return D3D_OK;
     } else {
-      /** 
-       * Indexed Vertex Blending Matrices 256 -> 511 
-       *  where WORLDMATRIX(0) == 256!
-       */
-      /** store it */
-      conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
-#if 0
-      if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
-          FIXME("TODO\n");
-      } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
-          FIXME("TODO\n");
-      }
-#endif
+        conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
     }
 
     /*
-     * Move the GL operation to outside of switch to make it work
-     * regardless of transform set order.
+       ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
+       where ViewMat = Camera space, WorldMat = world space.
+
+       In OpenGL, camera and world space is combined into GL_MODELVIEW
+       matrix.  The Projection matrix stay projection matrix. 
      */
-    ENTER_GL();
-    if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
-        glMatrixMode(GL_PROJECTION);
-        checkGLcall("glMatrixMode");
-        glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
-        checkGLcall("glLoadMatrixf");
-        memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
-    } else {
-        TRACE("Skipping as projection already correct\n");
-    }
 
-    glMatrixMode(GL_MODELVIEW);
-    checkGLcall("glMatrixMode");
-    viewChanged = FALSE;
-    if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
-       glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
-       checkGLcall("glLoadMatrixf");
-       memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
-       viewChanged = TRUE;
-
-       /* If we are changing the View matrix, reset the light and clipping planes to the new view */
-       if (d3dts == D3DTS_VIEW) {
-
-           /* NOTE: We have to reset the positions even if the light/plane is not currently
-              enabled, since the call to enable it will not reset the position.             */
-
-           /* Reset lights */
-           for (k = 0; k < GL_LIMITS(lights); k++) {
-               glLightfv(GL_LIGHT0 + k, GL_POSITION,       &This->lightPosn[k][0]);
-               checkGLcall("glLightfv posn");
-               glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
-               checkGLcall("glLightfv dirn");
-           }
+    /* Capture the times we can just ignore the change */
+    if (d3dts == D3DTS_WORLDMATRIX(0)) {
+        This->modelview_valid = FALSE;
+        return D3D_OK;
 
-           /* Reset Clipping Planes if clipping is enabled */
-           for (k = 0; k < GL_LIMITS(clipplanes); k++) {
-               glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
-               checkGLcall("glClipPlane");
-           }
+    } else if (d3dts == D3DTS_PROJECTION) {
+        This->proj_valid = FALSE;
+        return D3D_OK;
 
-           /* Reapply texture transforms as based off modelview when applied */
-           for (Stage = 0; Stage < GL_LIMITS(textures); Stage++) {
+    } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511  */
+        /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
+        FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
+        return D3D_OK;
+    } 
+    
+    /* Chances are we really are going to have to change a matrix */
+    ENTER_GL();
 
-               /* Only applicable if the transforms are not disabled */
-               if (This->UpdateStateBlock->texture_state[Stage][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) 
-               {
-                   /* Now apply texture transforms if not applying to the dummy textures */
+    if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
+        if (d3dts < GL_LIMITS(textures)) {
+            int tex = d3dts - D3DTS_TEXTURE0;
 #if defined(GL_VERSION_1_3)
-                  glActiveTexture(GL_TEXTURE0 + Stage);
+            glActiveTexture(GL_TEXTURE0 + tex);
 #else 
-                  glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
+            glActiveTextureARB(GL_TEXTURE0_ARB + tex);
 #endif
-                  checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
-
-                  glMatrixMode(GL_TEXTURE);
-                  if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
-                     glLoadIdentity();
-                  } else {
-                     D3DMATRIX fred;
-                     conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
-                     glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
-                  }
-               }
-               checkGLcall("Load matrix for texture");
-           }
-           glMatrixMode(GL_MODELVIEW);  /* Always leave in model view */
-       }
-    } else if ((d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) &&
-              (This->UpdateStateBlock->texture_state[d3dts - D3DTS_TEXTURE0][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)) {
-        /* Now apply texture transforms if not applying to the dummy textures */
-        Stage = d3dts - D3DTS_TEXTURE0;
-
-        if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX))) {
-	   memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX));
+            set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
+        }
 
-#if defined(GL_VERSION_1_3)
-           glActiveTexture(GL_TEXTURE0 + Stage);
-#else
-           glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
-#endif
-           checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
+    } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
+        float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
+        This->modelview_valid = FALSE;
+        This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
+        glMatrixMode(GL_MODELVIEW);
+        checkGLcall("glMatrixMode(GL_MODELVIEW)");
+        glPushMatrix();
+        glLoadMatrixf((float *)lpmatrix);
+        checkGLcall("glLoadMatrixf(...)");
+
+        /* If we are changing the View matrix, reset the light and clipping planes to the new view   
+         * NOTE: We have to reset the positions even if the light/plane is not currently
+         *       enabled, since the call to enable it will not reset the position.                 
+         * NOTE2: Apparently texture transforms do NOT need reapplying
+         */
 
-           glMatrixMode(GL_TEXTURE);
-           if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
-              glLoadIdentity();
-           } else {
-              D3DMATRIX fred;
-              conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
-              glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
-           }
-           checkGLcall("Load matrix for texture");
-           glMatrixMode(GL_MODELVIEW);  /* Always leave in model view */
-        } else {
-            TRACE("Skipping texture transform as already correct\n");
+        /* Reset lights */
+        for (k = 0; k < GL_LIMITS(lights); k++) {
+            glLightfv(GL_LIGHT0 + k, GL_POSITION, This->lightPosn[k]);
+            checkGLcall("glLightfv posn");
+            glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, This->lightDirn[k]);
+            checkGLcall("glLightfv dirn");
         }
+        /* Reset Clipping Planes if clipping is enabled */
+        for (k = 0; k < GL_LIMITS(clipplanes); k++) {
+            glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
+            checkGLcall("glClipPlane");
+        }
+        glPopMatrix();
 
-    } else {
-        TRACE("Skipping view setup as view already correct\n");
-    }
+    } else { /* What was requested!?? */
+        WARN("invalid matrix specified: %i\n", d3dts);
 
-    /**
-     * Vertex Blending as described
-     *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
-     */
-    switch (This->UpdateStateBlock->vertex_blend) {
-    case D3DVBF_DISABLE:
-      {
-          if (viewChanged == TRUE || 
-              (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
-               memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
-              if (viewChanged == FALSE) {
-                 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
-                 checkGLcall("glLoadMatrixf");
-              }
-              glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
-              checkGLcall("glMultMatrixf");
-          } else {
-              TRACE("Skipping as world already correct\n");
-          }
-      }
-      break;
-    case D3DVBF_1WEIGHTS:
-    case D3DVBF_2WEIGHTS:
-    case D3DVBF_3WEIGHTS:
-      {
-          FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
-          /*
-           * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
-           * so waiting for the values before matrix work
-          for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
-            glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
-            checkGLcall("glMultMatrixf");
-          }
-          */
-      }
-      break;
-    case D3DVBF_TWEENING:
-      {
-          FIXME("valid/correct D3DVBF_TWEENING\n");
-          f = This->UpdateStateBlock->tween_factor;
-          m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
-          m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
-          m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
-          m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
-          if (viewChanged == FALSE) {
-              glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
-              checkGLcall("glLoadMatrixf");
-          }
-          glMultMatrixf((float *) &m.u.m[0][0]);
-          checkGLcall("glMultMatrixf");
-      }
-      break;
-    case D3DVBF_0WEIGHTS:
-      {
-          FIXME("valid/correct D3DVBF_0WEIGHTS\n");
-          /* single matrix of weight 1.0f */
-          m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
-          m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
-          m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
-          m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
-          if (viewChanged == FALSE) {
-              glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
-              checkGLcall("glLoadMatrixf");
-          }
-          glMultMatrixf((float *) &m.u.m[0][0]);
-          checkGLcall("glMultMatrixf");
-      }
-      break;
-    default:
-      break; /* stupid compilator */
     }
 
+    /* Release lock, all done */
     LEAVE_GL();
-
     return D3D_OK;
 
 }
@@ -1887,9 +1793,9 @@
           This->UpdateStateBlock->clipplane[Index][2], 
 	  This->UpdateStateBlock->clipplane[Index][3]);
     glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
+    checkGLcall("glClipPlane");
 
     glPopMatrix();
-    checkGLcall("glClipPlane");
 
     LEAVE_GL();
 
@@ -3278,30 +3184,7 @@
         break;
 
     case D3DTSS_TEXTURETRANSFORMFLAGS :
-        {
-           switch (Value & ~D3DTTFF_PROJECTED)
-           {
-           case D3DTTFF_DISABLE: /* Disable transform matrix for this texture by setting up the identity matrix */
-               glMatrixMode(GL_TEXTURE);
-               glLoadIdentity();
-               checkGLcall("Load identity matrix for texture");
-               glMatrixMode(GL_MODELVIEW);  /* Always leave in model view */
-               break;
-
-           default: /* Enable it */
-               IDirect3DDevice8Impl_SetTransform(iface, D3DTS_TEXTURE0+Stage, &This->UpdateStateBlock->transforms[D3DTS_TEXTURE0+Stage]);
-               break;
-           }
-
-           /* From web: <quote source="opengl12.pdf" section="Apendix C, Version 1.1/Other changes"
-                2. Texture coordinates s, t, and r are divided by q during the rasterization
-                of points, pixel rectangles, and bitmaps. This division was documented
-                only for lines and polygons in the 1.0 version. </quote>                            
-              I interpret this as we can implement projected transforms in slow vertex mode
-                by moving the last coord to the 'q' coord and using one less dimension. The only
-                way to do it in TexCoordPtr would be to massage the data stream to insert extra
-                coords                                                                              */
-        }
+        set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
         break; 
 
     case D3DTSS_MIPMAPLODBIAS         :
Index: dlls/d3d8/directx.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/directx.c,v
retrieving revision 1.44
diff -u -r1.44 directx.c
--- dlls/d3d8/directx.c	13 Jun 2003 18:53:06 -0000	1.44
+++ dlls/d3d8/directx.c	16 Jul 2003 22:52:03 -0000
@@ -1083,6 +1083,12 @@
        IDirect3DDevice8Impl_SetViewport((LPDIRECT3DDEVICE8) object, &vp);
     }
 
+    /* Initialize the current view state */
+    object->modelview_valid = 1;
+    object->proj_valid = 0;
+    object->view_ident = 1;
+    object->last_was_rhw = 0;
+
     TRACE("(%p,%d) All defaults now set up, leaving CreateDevice\n", This, Adapter);
     return D3D_OK;
 }
Index: dlls/d3d8/drawprim.c
===================================================================
RCS file: /home/wine/wine/dlls/d3d8/drawprim.c,v
retrieving revision 1.5
diff -u -r1.5 drawprim.c
--- dlls/d3d8/drawprim.c	3 Jul 2003 18:10:22 -0000	1.5
+++ dlls/d3d8/drawprim.c	16 Jul 2003 22:52:05 -0000
@@ -172,67 +172,90 @@
         isLightingOn = glIsEnabled(GL_LIGHTING);
         glDisable(GL_LIGHTING);
         checkGLcall("glDisable(GL_LIGHTING);");
-        TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
+        TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn);
     }
 
     if (vtx_transformed) {
-        double X, Y, height, width, minZ, maxZ;
 
-        /* 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");
-        glLoadIdentity();
-        checkGLcall("glLoadIdentity");
-
-        glMatrixMode(GL_PROJECTION);
-        checkGLcall("glMatrixMode");
-        glLoadIdentity();
-        checkGLcall("glLoadIdentity");
-
-        /* Set up the viewport to be full viewport */
-        X      = This->StateBlock->viewport.X;
-        Y      = This->StateBlock->viewport.Y;
-        height = This->StateBlock->viewport.Height;
-        width  = This->StateBlock->viewport.Width;
-        minZ   = This->StateBlock->viewport.MinZ;
-        maxZ   = This->StateBlock->viewport.MaxZ;
-        TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
-        glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
-        checkGLcall("glOrtho");
-
-        /* Window Coord 0 is the middle of the first pixel, so translate by half
-           a pixel (See comment above glTranslate below)                         */
-        glTranslatef(0.5, 0.5, 0);
-        checkGLcall("glTranslatef(0.5, 0.5, 0)");
+        /* If the last draw was transformed as well, no need to reapply all the matrixes */
+        if (!This->last_was_rhw) {
+
+            double X, Y, height, width, minZ, maxZ;
+            This->last_was_rhw = TRUE;
+
+            /* 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");
+            glLoadIdentity();
+            checkGLcall("glLoadIdentity");
+
+            glMatrixMode(GL_PROJECTION);
+            checkGLcall("glMatrixMode");
+            glLoadIdentity();
+            checkGLcall("glLoadIdentity");
+
+            /* Set up the viewport to be full viewport */
+            X      = This->StateBlock->viewport.X;
+            Y      = This->StateBlock->viewport.Y;
+            height = This->StateBlock->viewport.Height;
+            width  = This->StateBlock->viewport.Width;
+            minZ   = This->StateBlock->viewport.MinZ;
+            maxZ   = This->StateBlock->viewport.MaxZ;
+            TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
+            glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
+            checkGLcall("glOrtho");
+
+            /* Window Coord 0 is the middle of the first pixel, so translate by half
+               a pixel (See comment above glTranslate below)                         */
+            glTranslatef(0.5, 0.5, 0);
+            checkGLcall("glTranslatef(0.5, 0.5, 0)");
+        }
 
     } else {
 
         /* Untransformed, so relies on the view and projection matrices */
-        glMatrixMode(GL_MODELVIEW);
-        checkGLcall("glMatrixMode");
-        glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
-        checkGLcall("glLoadMatrixf");
-        glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
-        checkGLcall("glMultMatrixf");
-
-        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(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
-        checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
-        glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
-        checkGLcall("glLoadMatrixf");
 
+        if (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[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
+                checkGLcall("glLoadMatrixf");
+            } else {
+                glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
+                checkGLcall("glLoadMatrixf");
+                glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
+                checkGLcall("glMultMatrixf");
+            }
+        }
+
+        if (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(1.0/This->StateBlock->viewport.Width, -1.0/This->StateBlock->viewport.Height, 0);
+            checkGLcall("glTranslatef (1.0/width, -1.0/height, 0)");
+            glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
+            checkGLcall("glLoadMatrixf");
+        }
+
+        This->last_was_rhw = FALSE;
     }
     return isLightingOn;
 }


More information about the wine-patches mailing list