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