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
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;
}