wined3d: Move the projection matrix into its own state.
This commit is contained in:
parent
a0ff9826ad
commit
82bd0790ed
|
@ -158,8 +158,6 @@ static const GLfloat invymat[16] = {
|
||||||
void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
|
void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
|
||||||
/* If the last draw was transformed as well, no need to reapply all the matrixes */
|
/* If the last draw was transformed as well, no need to reapply all the matrixes */
|
||||||
if ( (!This->last_was_rhw) || (This->viewport_changed) ) {
|
if ( (!This->last_was_rhw) || (This->viewport_changed) ) {
|
||||||
|
|
||||||
double X, Y, height, width, minZ, maxZ;
|
|
||||||
This->last_was_rhw = TRUE;
|
This->last_was_rhw = TRUE;
|
||||||
This->viewport_changed = FALSE;
|
This->viewport_changed = FALSE;
|
||||||
|
|
||||||
|
@ -170,61 +168,6 @@ void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
|
||||||
checkGLcall("glMatrixMode(GL_MODELVIEW)");
|
checkGLcall("glMatrixMode(GL_MODELVIEW)");
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
checkGLcall("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)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1900,6 +1900,74 @@ static const GLfloat invymat[16] = {
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
0.0f, 0.0f, 0.0f, 1.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) {
|
static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock) {
|
||||||
BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
|
BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
|
||||||
BOOL transformed;
|
BOOL transformed;
|
||||||
|
@ -1993,29 +2061,6 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock) {
|
||||||
|
|
||||||
if (!useVertexShaderFunction) {
|
if (!useVertexShaderFunction) {
|
||||||
device->proj_valid = TRUE;
|
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 */
|
/* Vertex Shader output is already transformed, so set up identity matrices */
|
||||||
|
@ -2027,6 +2072,13 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock) {
|
||||||
device->last_was_rhw = FALSE;
|
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 */
|
/* Setup fogging */
|
||||||
if(updateFog) {
|
if(updateFog) {
|
||||||
state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock);
|
state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock);
|
||||||
|
@ -2535,7 +2587,7 @@ const struct StateEntry StateTable[] =
|
||||||
/* Transform states follow */
|
/* Transform states follow */
|
||||||
{ /* 1, undefined */ 0, state_undefined },
|
{ /* 1, undefined */ 0, state_undefined },
|
||||||
{ /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
|
{ /* 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 },
|
{ /* 4, undefined */ 0, state_undefined },
|
||||||
{ /* 5, undefined */ 0, state_undefined },
|
{ /* 5, undefined */ 0, state_undefined },
|
||||||
{ /* 6, undefined */ 0, state_undefined },
|
{ /* 6, undefined */ 0, state_undefined },
|
||||||
|
|
|
@ -1150,6 +1150,9 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
|
||||||
we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
|
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 */
|
per drawprim (and leave set - it will sort itself out due to last_was_rhw */
|
||||||
d3ddevice_set_ortho(This->resource.wineD3DDevice);
|
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);
|
IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
|
||||||
|
|
||||||
if (iface == implSwapChain->frontBuffer) {
|
if (iface == implSwapChain->frontBuffer) {
|
||||||
|
@ -2474,6 +2477,9 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
|
||||||
/* Draw a textured quad
|
/* Draw a textured quad
|
||||||
*/
|
*/
|
||||||
d3ddevice_set_ortho(This->resource.wineD3DDevice);
|
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);
|
IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
|
|
Loading…
Reference in New Issue