d3dx9: Implement D3DXDeclaratorFromFVF. (try 2)

Henri Verbeet hverbeet at gmail.com
Wed Aug 25 05:28:35 CDT 2010


On 25 August 2010 04:04, misha680 <misha680 at gmail.com> wrote:
> What do you think about this one on top of those? I will wait to send to
> wine-patches until your patches have been committed.
> http://wine.1045685.n5.nabble.com/file/n2652101/0004-d3dx9-Implement-D3DXDeclaratorFromFVF.txt

Still not quite right, I'm afraid, although it's a bit closer.
However, as mentioned in
http://www.winehq.org/pipermail/wine-devel/2010-August/086112.html,
since this is about the tenth version of D3DXDeclaratorFromFVF() I'm
seeing (not counting the ones in d3d9 and wined3d...), I went ahead
and just implemented it myself. The patch attached to that mail is the
initial untested version. The patch attached to this mail is what I
think it should look like after doing some tests. I'll probably send
it in tomorrow.
-------------- next part --------------
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
index cc22107..ed7f9a8 100644
--- a/dlls/d3dx9_36/mesh.c
+++ b/dlls/d3dx9_36/mesh.c
@@ -190,14 +190,114 @@ static const UINT d3dx_decltype_size[D3DDECLTYPE_UNUSED] =
    /* D3DDECLTYPE_FLOAT16_4 */ 4 * 2,
 };
 
+static void append_decl_element(D3DVERTEXELEMENT9 *declaration, UINT *idx, UINT *offset,
+        D3DDECLTYPE type, D3DDECLUSAGE usage, UINT usage_idx)
+{
+    declaration[*idx].Stream = 0;
+    declaration[*idx].Offset = *offset;
+    declaration[*idx].Type = type;
+    declaration[*idx].Method = D3DDECLMETHOD_DEFAULT;
+    declaration[*idx].Usage = usage;
+    declaration[*idx].UsageIndex = usage_idx;
+
+    *offset += d3dx_decltype_size[type];
+    ++(*idx);
+}
+
 /*************************************************************************
  * D3DXDeclaratorFromFVF
  */
-HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 Declaration[MAX_FVF_DECL_SIZE])
+HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD fvf, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
 {
-    FIXME("(%d, %p): stub\n", fvf, Declaration);
+    static const D3DVERTEXELEMENT9 end_element = D3DDECL_END();
+    DWORD tex_count = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+    unsigned int offset = 0;
+    unsigned int idx = 0;
+    unsigned int i;
 
-    return E_NOTIMPL;
+    TRACE("fvf %#x, declaration %p.\n", fvf, declaration);
+
+    if (fvf & D3DFVF_POSITION_MASK)
+    {
+        BOOL has_blend = (fvf & D3DFVF_XYZB5) >= D3DFVF_XYZB1;
+        DWORD blend_count = 1 + (((fvf & D3DFVF_XYZB5) - D3DFVF_XYZB1) >> 1);
+        BOOL has_blend_idx = (fvf & D3DFVF_LASTBETA_D3DCOLOR) || (fvf & D3DFVF_LASTBETA_UBYTE4);
+
+        if (has_blend_idx) --blend_count;
+
+        if ((fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZW
+                || (has_blend && blend_count > 4))
+            return D3DERR_INVALIDCALL;
+
+        if ((fvf & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)
+            append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT4, D3DDECLUSAGE_POSITIONT, 0);
+        else
+            append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_POSITION, 0);
+
+        if (has_blend)
+        {
+            switch (blend_count)
+            {
+                 case 0:
+                    break;
+                 case 1:
+                    append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT1, D3DDECLUSAGE_BLENDWEIGHT, 0);
+                    break;
+                 case 2:
+                    append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT2, D3DDECLUSAGE_BLENDWEIGHT, 0);
+                    break;
+                 case 3:
+                    append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_BLENDWEIGHT, 0);
+                    break;
+                 case 4:
+                    append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT4, D3DDECLUSAGE_BLENDWEIGHT, 0);
+                    break;
+                 default:
+                     ERR("Invalid blend count %u.\n", blend_count);
+                     break;
+            }
+
+            if (has_blend_idx)
+            {
+                if (fvf & D3DFVF_LASTBETA_UBYTE4)
+                    append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_UBYTE4, D3DDECLUSAGE_BLENDINDICES, 0);
+                else if (fvf & D3DFVF_LASTBETA_D3DCOLOR)
+                    append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_BLENDINDICES, 0);
+            }
+        }
+    }
+
+    if (fvf & D3DFVF_NORMAL)
+        append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_NORMAL, 0);
+    if (fvf & D3DFVF_PSIZE)
+        append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT1, D3DDECLUSAGE_PSIZE, 0);
+    if (fvf & D3DFVF_DIFFUSE)
+        append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_COLOR, 0);
+    if (fvf & D3DFVF_SPECULAR)
+        append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_COLOR, 1);
+
+    for (i = 0; i < tex_count; ++i)
+    {
+        switch ((fvf >> (16 + 2 * i)) & 0x03)
+        {
+            case D3DFVF_TEXTUREFORMAT1:
+                append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT1, D3DDECLUSAGE_TEXCOORD, i);
+                break;
+            case D3DFVF_TEXTUREFORMAT2:
+                append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT2, D3DDECLUSAGE_TEXCOORD, i);
+                break;
+            case D3DFVF_TEXTUREFORMAT3:
+                append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_TEXCOORD, i);
+                break;
+            case D3DFVF_TEXTUREFORMAT4:
+                append_decl_element(declaration, &idx, &offset, D3DDECLTYPE_FLOAT4, D3DDECLUSAGE_TEXCOORD, i);
+                break;
+        }
+    }
+
+    declaration[idx] = end_element;
+
+    return D3D_OK;
 }
 
 /*************************************************************************
diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index 882323b..221c81a 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -469,7 +469,7 @@ static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_el
     D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
 
     hr = D3DXDeclaratorFromFVF(test_fvf, decl);
-    todo_wine ok(hr == expected_hr,
+    ok(hr == expected_hr,
             "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n",
             line, test_id, hr, expected_hr);
     if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id);


More information about the wine-devel mailing list