[2/2] WINED3D: Fix D3DCOLOR swizzling in shaders.

H. Verbeet hverbeet at gmail.com
Sat Aug 5 11:15:42 CDT 2006


The current D3DCOLOR swizzling code is incorrect. Although a usage of
D3DDECLUSAGE_COLOR is quite a strong hint that an attribute needs
swizzling, it's not a guarantee. Newer graphics cards support the
UBYTE4 data type in addition the D3DCOLOR for vertex declaration
elements, and sometimes it's used for colors. In that case the current
code will swizzle while it shouldn't. Also, sometimes games use the
D3DCOLOR type for attributes with a usage other than
D3DDECLUSAGE_COLOR, like vertex blending indices. This causes
corruption of models that use vertex blending in Battlefield 2, and
Half-life 2 in dxlevel 90.

This patch fixes those issues by looking at the data types in the
vertex declaration the shader will be used with. To be able to do
that, we have to wait with compiling the shader until the shader is
first used and we have a vertex declaration.
-------------- next part --------------
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index e837772..3427dff 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -661,13 +661,31 @@ BOOL vshader_input_is_color(
     IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
     DWORD usage_token = This->semantics_in[regnum].usage;
     DWORD usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+    DWORD usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
 
-    /* FIXME: D3D8 shader: the semantics token is not the way to 
-     * determine color info, since it is just a fake map to shader inputs */
-    if (This->vertexDeclaration != NULL)
-        return FALSE; 
-    else
-        return usage == D3DDECLUSAGE_COLOR;
+    IWineD3DVertexDeclarationImpl *vertexDeclaration = NULL;
+    if (This->vertexDeclaration) {
+        /* D3D8 declaration */
+        vertexDeclaration = (IWineD3DVertexDeclarationImpl *)This->vertexDeclaration;
+    } else {
+        /* D3D9 declaration */
+        vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DDeviceImpl *)This->wineD3DDevice)->stateBlock->vertexDecl;
+    }
+
+    if (vertexDeclaration) {
+        int i;
+        /* Find the declaration element that matches our register, then check
+         * if it has D3DCOLOR as it's type. This works for both d3d8 and d3d9. */
+        for (i = 0; i < vertexDeclaration->declarationWNumElements-1; ++i) {
+            WINED3DVERTEXELEMENT *element = vertexDeclaration->pDeclarationWine + i;
+            if ((element->Usage == usage && element->UsageIndex == usage_idx)) {
+                return element->Type == WINED3DDECLTYPE_D3DCOLOR;
+            }
+        }
+    }
+
+    ERR("Either no vertexdeclaration present, or register not matched. This should never happen.\n");
+    return FALSE;
 }
 
 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB


More information about the wine-patches mailing list