Stefan Dösinger : wined3d: Some texture transform fixes.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Aug 27 13:57:13 CDT 2007
Module: wine
Branch: master
Commit: fe0f0eb48a12e29af6a9e7407d4eec8bc500a057
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fe0f0eb48a12e29af6a9e7407d4eec8bc500a057
Author: Stefan Dösinger <stefan at codeweavers.com>
Date: Mon Aug 27 14:33:46 2007 +0200
wined3d: Some texture transform fixes.
---
dlls/wined3d/drawprim.c | 1 +
dlls/wined3d/state.c | 17 ++++++++--
dlls/wined3d/utils.c | 61 +++++++++++++++++++++++++++++++++------
dlls/wined3d/wined3d_private.h | 2 +-
4 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 2dcaa5d..4eb6786 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -414,6 +414,7 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
ptrToCoords = (float *)(texCoords[coordIdx] + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
if (texCoords[coordIdx] == NULL) {
TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
+ glTexCoord4f(0, 0, 0, 1);
continue;
} else {
int texture_idx = This->texUnitMap[textureNo];
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 4526151..900e366 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -1859,6 +1859,13 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W
DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
+ /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
+ if(stateblock->vertexShader ||
+ isStateDirty(context, STATE_VDECL)) {
+ TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
+ return;
+ }
+
if (mapped_stage < 0) return;
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
@@ -1876,7 +1883,10 @@ static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, W
set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU,
- context->last_was_rhw);
+ context->last_was_rhw,
+ stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
+ stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
+ WINED3DDECLTYPE_UNUSED);
}
@@ -3199,7 +3209,7 @@ static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVer
}
static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
- BOOL useVertexShaderFunction = FALSE, updateFog = FALSE, updateTexMatrices = FALSE;
+ BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
&& ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
BOOL transformed;
@@ -3228,7 +3238,6 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
updateFog = TRUE;
- updateTexMatrices = TRUE;
}
/* Reapply lighting if it is not scheduled for reapplication already */
@@ -3333,7 +3342,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
if(updateFog) {
state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
}
- if(updateTexMatrices) {
+ if(!useVertexShaderFunction) {
int i;
for(i = 0; i < MAX_TEXTURES; i++) {
if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 3f9cdd5..9417055 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -2418,14 +2418,14 @@ void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP
#endif
/* Setup this textures matrix according to the texture flags*/
-void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed)
+void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed, DWORD coordtype)
{
float mat[16];
glMatrixMode(GL_TEXTURE);
checkGLcall("glMatrixMode(GL_TEXTURE)");
- if (flags == WINED3DTTFF_DISABLE || transformed) {
+ if (flags == WINED3DTTFF_DISABLE || flags == WINED3DTTFF_COUNT1 || transformed) {
glLoadIdentity();
checkGLcall("glLoadIdentity()");
return;
@@ -2438,12 +2438,6 @@ void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, B
memcpy(mat, smat, 16 * sizeof(float));
- switch (flags & ~WINED3DTTFF_PROJECTED) {
- case WINED3DTTFF_COUNT1: mat[1] = mat[5] = mat[13] = 0;
- case WINED3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
- default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
- }
-
if (flags & WINED3DTTFF_PROJECTED) {
switch (flags & ~WINED3DTTFF_PROJECTED) {
case WINED3DTTFF_COUNT2:
@@ -2456,8 +2450,55 @@ void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, B
break;
}
} else if(!calculatedCoords) { /* under directx the R/Z coord can be used for translation, under opengl we use the Q coord instead */
- mat[12] = mat[8];
- mat[13] = mat[9];
+ switch(coordtype) {
+ case WINED3DDECLTYPE_FLOAT1:
+ /* Direct3D passes the default 1.0 in the 2nd coord, while gl passes it in the 4th.
+ * swap 2nd and 4th coord. No need to store the value of mat[12] in mat[4] because
+ * the input value to the transformation will be 0, so the matrix value is irrelevant
+ */
+ mat[12] = mat[4];
+ mat[13] = mat[5];
+ mat[14] = mat[6];
+ mat[15] = mat[7];
+ break;
+ case WINED3DDECLTYPE_FLOAT2:
+ /* See above, just 3rd and 4th coord
+ */
+ mat[12] = mat[8];
+ mat[13] = mat[9];
+ mat[14] = mat[10];
+ mat[15] = mat[11];
+ break;
+ case WINED3DDECLTYPE_FLOAT3: /* Opengl defaults match dx defaults */
+ case WINED3DDECLTYPE_FLOAT4: /* No defaults apply, all app defined */
+
+ /* This is to prevent swaping the matrix lines and put the default 4th coord = 1.0
+ * into a bad place. The division elimination below will apply to make sure the
+ * 1.0 doesn't do anything bad. The caller will set this value if the stride is 0
+ */
+ case WINED3DDECLTYPE_UNUSED: /* No texture coords, 0/0/0/1 defaults are passed */
+ break;
+ default:
+ FIXME("Unexpected fixed function texture coord input\n");
+ }
+ switch (flags & ~WINED3DTTFF_PROJECTED) {
+ /* case WINED3DTTFF_COUNT1: Won't ever get here */
+ case WINED3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
+ /* OpenGL divides the first 3 vertex coord by the 4th by default,
+ * which is essentially the same as D3DTTFF_PROJECTED. Make sure that
+ * the 4th coord evaluates to 1.0 to eliminate that.
+ *
+ * If the fixed function pipeline is used, the 4th value remains unused,
+ * so there is no danger in doing this. With vertex shaders we have a
+ * problem. Should an app hit that problem, the code here would have to
+ * check for pixel shaders, and the shader has to undo the default gl divide.
+ *
+ * A more serious problem occurs if the app passes 4 coordinates in, and the
+ * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow
+ * or a replacement shader
+ */
+ default: mat[3] = mat[7] = mat[11] = 0; mat[15] = 1;
+ }
}
glLoadMatrixf(mat);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 36185a1..e02aabb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1532,7 +1532,7 @@ GLenum StencilOp(DWORD op);
GLenum CompareFunc(DWORD func);
void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3);
void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx);
-void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed);
+void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, BOOL transformed, DWORD coordtype);
void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height);
GLenum surface_get_gl_buffer(IWineD3DSurface *iface, IWineD3DSwapChain *swapchain);
More information about the wine-cvs
mailing list