[8/10] WineD3D: Move the projection matrix into its own state
Stefan Dösinger
stefandoesinger at gmx.at
Tue Jan 2 15:50:38 CST 2007
Its pointless to reapply the vdecl if the projection transform
setting has changed. Simmilar to the lighting state.
-------------- next part --------------
From 5189f91b62b321b20466deecb7336e18e7ce81b1 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan_D=C3=B6singer?= <stefan at imac.local>
Date: Tue, 2 Jan 2007 22:00:45 +0100
Subject: [PATCH] WineD3D: Move the projection matrix to the state table
---
dlls/wined3d/drawprim.c | 57 ---------------------------
dlls/wined3d/state.c | 100 ++++++++++++++++++++++++++++++++++++-----------
dlls/wined3d/surface.c | 6 +++
3 files changed, 82 insertions(+), 81 deletions(-)
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index c79c2b0..9ccc358 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -158,8 +158,6 @@ static const GLfloat invymat[16] = {
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) ) {
-
- double X, Y, height, width, minZ, maxZ;
This->last_was_rhw = TRUE;
This->viewport_changed = FALSE;
@@ -170,61 +168,6 @@ void d3ddevice_set_ortho(IWineD3DDeviceI
checkGLcall("glMatrixMode(GL_MODELVIEW)");
glLoadIdentity();
checkGLcall("glLoadIdentity");
-
- glMatrixMode(GL_PROJECTION);
- checkGLcall("glMatrixMode(GL_PROJECTION)");
- 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;
- if(!This->untransformed) {
- TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
- glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
- } else {
- TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
- glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
- }
- 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.375, 0.375, 0);
- checkGLcall("glTranslatef(0.375, 0.375, 0)");
- /* D3D texture coordinates are flipped compared to OpenGL ones, so
- * render everything upside down when rendering offscreen. */
- if (This->render_offscreen) {
- glMultMatrixf(invymat);
- checkGLcall("glMultMatrixf(invymat)");
- }
-
- /* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
- if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != WINED3DFOG_NONE) {
- if(GL_SUPPORT(EXT_FOG_COORD)) {
- glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
- checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
- glFogi(GL_FOG_MODE, GL_LINEAR);
- checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
- /* The dx fog range in this case is fixed to 0 - 255,
- * but in GL it still depends on the fog start and end (according to the ext)
- * Use this to turn around the fog as it's needed. That prevents some
- * calculations during drawing :-)
- */
- glFogf(GL_FOG_START, (float) 0xff);
- checkGLcall("glFogfv GL_FOG_END");
- glFogf(GL_FOG_END, 0.0);
- checkGLcall("glFogfv GL_FOG_START");
- } else {
- /* Disable GL fog, handle this in software in drawStridedSlow */
- glDisable(GL_FOG);
- checkGLcall("glDisable(GL_FOG)");
- }
- }
}
}
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 9f690c5..0e9c8a5 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1890,6 +1890,74 @@ static const GLfloat invymat[16] = {
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f};
+static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock) {
+ glMatrixMode(GL_PROJECTION);
+ checkGLcall("glMatrixMode(GL_PROJECTION)");
+ glLoadIdentity();
+ checkGLcall("glLoadIdentity");
+
+ if(stateblock->wineD3DDevice->last_was_rhw) {
+ double X, Y, height, width, minZ, maxZ;
+
+ X = stateblock->viewport.X;
+ Y = stateblock->viewport.Y;
+ height = stateblock->viewport.Height;
+ width = stateblock->viewport.Width;
+ minZ = stateblock->viewport.MinZ;
+ maxZ = stateblock->viewport.MaxZ;
+
+ if(!stateblock->wineD3DDevice->untransformed) {
+ /* Transformed vertices are supposed to bypass the whole transform pipeline including
+ * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
+ * suppress depth clipping. This can be done because it is an orthogonal projection and
+ * the Z coordinate does not affect the size of the primitives
+ */
+ TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
+ glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
+ } else {
+ /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
+ * trick above because this would mess up transformed and untransformed Z order. Pass the z position
+ * unmodified to opengl.
+ *
+ * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
+ * replacement shader.
+ */
+ TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
+ glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
+ }
+ checkGLcall("glOrtho");
+
+ /* Window Coord 0 is the middle of the first pixel, so translate by 3/8 pixels */
+ glTranslatef(0.375, 0.375, 0);
+ checkGLcall("glTranslatef(0.375, 0.375, 0)");
+ /* D3D texture coordinates are flipped compared to OpenGL ones, so
+ * render everything upside down when rendering offscreen. */
+ if (stateblock->wineD3DDevice->render_offscreen) {
+ glMultMatrixf(invymat);
+ checkGLcall("glMultMatrixf(invymat)");
+ }
+ } else {
+ /* 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. */
+ glTranslatef(0.9 / stateblock->viewport.Width, -0.9 / stateblock->viewport.Height, 0);
+ checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
+
+ /* D3D texture coordinates are flipped compared to OpenGL ones, so
+ * render everything upside down when rendering offscreen. */
+ if (stateblock->wineD3DDevice->render_offscreen) {
+ glMultMatrixf(invymat);
+ checkGLcall("glMultMatrixf(invymat)");
+ }
+ glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
+ checkGLcall("glLoadMatrixf");
+ }
+}
+
static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock) {
BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
BOOL transformed;
@@ -1983,29 +2051,6 @@ static void vertexdeclaration(DWORD stat
if (!useVertexShaderFunction) {
device->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(0.9 / stateblock->viewport.Width, -0.9 / stateblock->viewport.Height, 0);
- checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
-
- /* D3D texture coordinates are flipped compared to OpenGL ones, so
- * render everything upside down when rendering offscreen. */
- if (device->render_offscreen) {
- glMultMatrixf(invymat);
- checkGLcall("glMultMatrixf(invymat)");
- }
- glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
- checkGLcall("glLoadMatrixf");
}
/* Vertex Shader output is already transformed, so set up identity matrices */
@@ -2017,6 +2062,13 @@ static void vertexdeclaration(DWORD stat
device->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
+ */
+ if(!isStateDirty(stateblock->wineD3DDevice, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
+ transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock);
+ }
+
/* Setup fogging */
if(updateFog) {
state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock);
@@ -2525,7 +2577,7 @@ const struct StateEntry StateTable[] =
/* Transform states follow */
{ /* 1, undefined */ 0, state_undefined },
{ /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
- { /* 3, WINED3DTS_PROJECTION */ STATE_VDECL, vertexdeclaration },
+ { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
{ /* 4, undefined */ 0, state_undefined },
{ /* 5, undefined */ 0, state_undefined },
{ /* 6, undefined */ 0, state_undefined },
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 5cf43f1..d9355d4 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1150,6 +1150,9 @@ 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);
+ /* 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);
+ /* Will reapply the projection matrix too */
IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
if (iface == implSwapChain->frontBuffer) {
@@ -2474,6 +2477,9 @@ static HRESULT IWineD3DSurfaceImpl_BltOv
/* Draw a textured quad
*/
d3ddevice_set_ortho(This->resource.wineD3DDevice);
+ /* 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);
+ /* That will reapply the projection matrix too */
IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
glBegin(GL_QUADS);
--
1.4.2.4
More information about the wine-patches
mailing list