[2/9] d3dx9/tests: Add tests for D3DXLoadMeshHierarchyFromXInMemory.

Dylan Smith dylan.ah.smith at gmail.com
Mon Jun 6 11:53:35 CDT 2011


---
 dlls/d3dx9_36/tests/mesh.c |  562 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 562 insertions(+), 0 deletions(-)

diff --git a/dlls/d3dx9_36/tests/mesh.c b/dlls/d3dx9_36/tests/mesh.c
index cedef32..85f0ecb 100644
--- a/dlls/d3dx9_36/tests/mesh.c
+++ b/dlls/d3dx9_36/tests/mesh.c
@@ -18,11 +18,16 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#define COBJMACROS
 #include <stdio.h>
 #include <float.h>
 #include "wine/test.h"
 #include "d3dx9.h"
 
+/* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
+ * function call traces of ID3DXAllocateHierarchy callbacks. */
+#define TRACECALLBACK if(winetest_debug > 1) trace
+
 #define admitted_error 0.0001f
 
 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
@@ -48,6 +53,29 @@ static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
     return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
 }
 
+#define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim)
+static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim)
+{
+    int i;
+    char exp_buffer[256] = "";
+    char got_buffer[256] = "";
+    char *exp_buffer_ptr = exp_buffer;
+    char *got_buffer_ptr = got_buffer;
+    BOOL equal = TRUE;
+
+    for (i = 0; i < dim; i++) {
+        if (i) {
+            exp_buffer_ptr += sprintf(exp_buffer_ptr, ", ");
+            got_buffer_ptr += sprintf(got_buffer_ptr, ", ");
+        }
+        equal = equal && compare(*exp, *got);
+        exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp);
+        got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got);
+        exp++, got++;
+    }
+    ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer);
+}
+
 struct vertex
 {
     D3DXVECTOR3 position;
@@ -1370,6 +1398,539 @@ static void D3DXCreateMeshFVFTest(void)
     DestroyWindow(wnd);
 }
 
+#define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \
+    check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf)
+static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf)
+{
+    DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh);
+    DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh);
+    const void *mesh_vertices;
+    HRESULT hr;
+
+    ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf);
+    ok_(__FILE__,line)(num_vertices == mesh_num_vertices,
+       "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices);
+
+    hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices);
+    ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
+    if (FAILED(hr))
+        return;
+
+    if (mesh_fvf == fvf) {
+        DWORD vertex_size = D3DXGetFVFVertexSize(fvf);
+        int i;
+        for (i = 0; i < min(num_vertices, mesh_num_vertices); i++)
+        {
+            const FLOAT *exp_float = vertices;
+            const FLOAT *got_float = mesh_vertices;
+            DWORD texcount;
+            DWORD pos_dim = 0;
+            int j;
+            BOOL last_beta_dword = FALSE;
+            char prefix[128];
+
+            switch (fvf & D3DFVF_POSITION_MASK) {
+                case D3DFVF_XYZ: pos_dim = 3; break;
+                case D3DFVF_XYZRHW: pos_dim = 4; break;
+                case D3DFVF_XYZB1:
+                case D3DFVF_XYZB2:
+                case D3DFVF_XYZB3:
+                case D3DFVF_XYZB4:
+                case D3DFVF_XYZB5:
+                    pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1;
+                    if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
+                    {
+                        pos_dim--;
+                        last_beta_dword = TRUE;
+                    }
+                    break;
+                case D3DFVF_XYZW: pos_dim = 4; break;
+            }
+            sprintf(prefix, "vertex[%u] position, ", i);
+            check_floats_(line, prefix, got_float, exp_float, pos_dim);
+            exp_float += pos_dim;
+            got_float += pos_dim;
+
+            if (last_beta_dword) {
+                ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
+                    "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
+                exp_float++;
+                got_float++;
+            }
+
+            if (fvf & D3DFVF_NORMAL) {
+                sprintf(prefix, "vertex[%u] normal, ", i);
+                check_floats_(line, prefix, got_float, exp_float, 3);
+                exp_float += 3;
+                got_float += 3;
+            }
+            if (fvf & D3DFVF_PSIZE) {
+                ok_(__FILE__,line)(compare(*exp_float, *got_float),
+                        "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float);
+                exp_float++;
+                got_float++;
+            }
+            if (fvf & D3DFVF_DIFFUSE) {
+                ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
+                    "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
+                exp_float++;
+                got_float++;
+            }
+            if (fvf & D3DFVF_SPECULAR) {
+                ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float,
+                    "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float);
+                exp_float++;
+                got_float++;
+            }
+
+            texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+            for (j = 0; j < texcount; j++) {
+                DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1;
+                sprintf(prefix, "vertex[%u] texture, ", i);
+                check_floats_(line, prefix, got_float, exp_float, dim);
+                exp_float += dim;
+                got_float += dim;
+            }
+
+            vertices = (BYTE*)vertices + vertex_size;
+            mesh_vertices = (BYTE*)mesh_vertices + vertex_size;
+        }
+    }
+
+    mesh->lpVtbl->UnlockVertexBuffer(mesh);
+}
+
+#define check_index_buffer(mesh, indices, num_indices, index_size) \
+    check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size)
+static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size)
+{
+    DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2;
+    DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3;
+    const void *mesh_indices;
+    HRESULT hr;
+    DWORD i;
+
+    ok_(__FILE__,line)(index_size == mesh_index_size,
+        "Expected index size %u, got %u\n", index_size, mesh_index_size);
+    ok_(__FILE__,line)(num_indices == mesh_num_indices,
+        "Expected %u indices, got %u\n", num_indices, mesh_num_indices);
+
+    hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices);
+    ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK);
+    if (FAILED(hr))
+        return;
+
+    if (mesh_index_size == index_size) {
+        for (i = 0; i < min(num_indices, mesh_num_indices); i++)
+        {
+            if (index_size == 4)
+                ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices,
+                    "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices);
+            else
+                ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices,
+                    "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices);
+            indices = (BYTE*)indices + index_size;
+            mesh_indices = (BYTE*)mesh_indices + index_size;
+        }
+    }
+    mesh->lpVtbl->UnlockIndexBuffer(mesh);
+}
+
+#define check_matrix(got, expected) check_matrix_(__LINE__, got, expected)
+static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected)
+{
+    int i, j;
+    for (i = 0; i < 4; i++) {
+        for (j = 0; j < 4; j++) {
+            ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]),
+                    "matrix[%u][%u]: expected %g, got %g\n",
+                    i, j, U(*expected).m[i][j], U(*got).m[i][j]);
+        }
+    }
+}
+
+#define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon)
+static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon)
+{
+    DWORD *expected;
+    DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh);
+    HRESULT hr;
+
+    expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3);
+    if (!expected) {
+        skip_(__FILE__, line)("Out of memory\n");
+        return;
+    }
+    hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected);
+    ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+    if (SUCCEEDED(hr))
+    {
+        int i;
+        for (i = 0; i < num_faces; i++)
+        {
+            ok_(__FILE__, line)(expected[i * 3] == got[i * 3] &&
+                    expected[i * 3 + 1] == got[i * 3 + 1] &&
+                    expected[i * 3 + 2] == got[i * 3 + 2],
+                    "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i,
+                    expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2],
+                    got[i * 3], got[i * 3 + 1], got[i * 3 + 2]);
+        }
+    }
+    HeapFree(GetProcessHeap(), 0, expected);
+}
+
+static LPSTR strdupA(LPCSTR p)
+{
+    LPSTR ret;
+    if (!p) return NULL;
+    ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1);
+    if (ret) strcpy(ret, p);
+    return ret;
+}
+
+static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame)
+{
+    TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame);
+    if (frame) {
+        HeapFree(GetProcessHeap(), 0, frame->Name);
+        HeapFree(GetProcessHeap(), 0, frame);
+    }
+    return D3D_OK;
+}
+
+static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, LPCSTR name, LPD3DXFRAME *new_frame)
+{
+    LPD3DXFRAME frame;
+
+    TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame);
+    frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame));
+    if (!frame)
+        return E_OUTOFMEMORY;
+    if (name) {
+        frame->Name = strdupA(name);
+        if (!frame->Name) {
+            HeapFree(GetProcessHeap(), 0, frame);
+            return E_OUTOFMEMORY;
+        }
+    }
+    *new_frame = frame;
+    return D3D_OK;
+}
+
+static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container)
+{
+    int i;
+
+    if (!mesh_container)
+        return D3D_OK;
+    HeapFree(GetProcessHeap(), 0, mesh_container->Name);
+    if (U(mesh_container->MeshData).pMesh)
+        IUnknown_Release(U(mesh_container->MeshData).pMesh);
+    if (mesh_container->pMaterials) {
+        for (i = 0; i < mesh_container->NumMaterials; i++)
+            HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename);
+        HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials);
+    }
+    if (mesh_container->pEffects) {
+        for (i = 0; i < mesh_container->NumMaterials; i++) {
+            HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename);
+            if (mesh_container->pEffects[i].pDefaults) {
+                int j;
+                for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) {
+                    HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName);
+                    HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue);
+                }
+                HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults);
+            }
+        }
+        HeapFree(GetProcessHeap(), 0, mesh_container->pEffects);
+    }
+    HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency);
+    if (mesh_container->pSkinInfo)
+        IUnknown_Release(mesh_container->pSkinInfo);
+    HeapFree(GetProcessHeap(), 0, mesh_container);
+    return D3D_OK;
+}
+
+static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container)
+{
+    TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container);
+    return destroy_mesh_container(mesh_container);
+}
+
+static CALLBACK HRESULT ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface,
+        LPCSTR name, CONST D3DXMESHDATA *mesh_data, CONST D3DXMATERIAL *materials,
+        CONST D3DXEFFECTINSTANCE *effects, DWORD num_materials, CONST DWORD *adjacency,
+        LPD3DXSKININFO skin_info, LPD3DXMESHCONTAINER *new_mesh_container)
+{
+    LPD3DXMESHCONTAINER mesh_container = NULL;
+    int i;
+
+    TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n",
+            iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects,
+            num_materials, adjacency, skin_info, *new_mesh_container);
+
+    mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container));
+    if (!mesh_container)
+        return E_OUTOFMEMORY;
+
+    if (name) {
+        mesh_container->Name = strdupA(name);
+        if (!mesh_container->Name)
+            goto error;
+    }
+
+    mesh_container->NumMaterials = num_materials;
+    if (num_materials) {
+        mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials));
+        if (!mesh_container->pMaterials)
+            goto error;
+
+        memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials));
+        for (i = 0; i < num_materials; i++)
+            mesh_container->pMaterials[i].pTextureFilename = NULL;
+        for (i = 0; i < num_materials; i++) {
+            if (materials[i].pTextureFilename) {
+                mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename);
+                if (!mesh_container->pMaterials[i].pTextureFilename)
+                    goto error;
+            }
+        }
+
+        mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects));
+        if (!mesh_container->pEffects)
+            goto error;
+        for (i = 0; i < num_materials; i++) {
+            int j;
+            const D3DXEFFECTINSTANCE *effect_src = &effects[i];
+            D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i];
+
+            if (effect_src->pEffectFilename) {
+                effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename);
+                if (!effect_dest->pEffectFilename)
+                    goto error;
+            }
+            effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                    effect_src->NumDefaults * sizeof(*effect_src->pDefaults));
+            if (!effect_dest->pDefaults)
+                goto error;
+            effect_dest->NumDefaults = effect_src->NumDefaults;
+            for (j = 0; j < effect_src->NumDefaults; j++) {
+                const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j];
+                D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j];
+
+                if (default_src->pParamName) {
+                    default_dest->pParamName = strdupA(default_src->pParamName);
+                    if (!default_dest->pParamName)
+                        goto error;
+                }
+                default_dest->NumBytes = default_src->NumBytes;
+                default_dest->Type = default_src->Type;
+                default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes);
+                memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes);
+            }
+        }
+    }
+
+    ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n");
+    if (adjacency) {
+        if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) {
+            ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh;
+            DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh);
+            size_t size = num_faces * sizeof(DWORD) * 3;
+            mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size);
+            if (!mesh_container->pAdjacency)
+                goto error;
+            memcpy(mesh_container->pAdjacency, adjacency, size);
+        } else {
+            ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type);
+            if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH)
+                trace("FIXME: copying adjacency data for patch mesh not implemented");
+        }
+    }
+
+    memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data));
+    if (U(*mesh_data).pMesh)
+        IUnknown_AddRef(U(*mesh_data).pMesh);
+    if (skin_info) {
+        mesh_container->pSkinInfo = skin_info;
+        skin_info->lpVtbl->AddRef(skin_info);
+    }
+    *new_mesh_container = mesh_container;
+
+    return S_OK;
+error:
+    destroy_mesh_container(mesh_container);
+    return E_OUTOFMEMORY;
+}
+
+static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = {
+    ID3DXAllocateHierarchyImpl_CreateFrame,
+    ID3DXAllocateHierarchyImpl_CreateMeshContainer,
+    ID3DXAllocateHierarchyImpl_DestroyFrame,
+    ID3DXAllocateHierarchyImpl_DestroyMeshContainer,
+};
+static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl };
+
+static void D3DXLoadMeshTest(void)
+{
+    static const char empty_xfile[] = "xof 0303txt 0032";
+    /*________________________*/
+    static const char simple_xfile[] =
+        "xof 0303txt 0032"
+        "Mesh {"
+            "3;"
+            "0.0; 0.0; 0.0;,"
+            "0.0; 1.0; 0.0;,"
+            "1.0; 1.0; 0.0;;"
+            "1;"
+            "3; 0, 1, 2;;"
+        "}";
+    static const WORD simple_index_buffer[] = {0, 1, 2};
+    static const D3DXVECTOR3 simple_vertex_buffer[] = {
+        {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}
+    };
+    const DWORD simple_fvf = D3DFVF_XYZ;
+    static const char framed_xfile[] =
+        "xof 0303txt 0032"
+        "Frame {"
+            "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 1.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }"
+            "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */
+              "1.0, 0.0, 0.0, 0.0,"
+              "0.0, 1.0, 0.0, 0.0,"
+              "0.0, 0.0, 1.0, 0.0,"
+              "0.0, 0.0, 2.0, 1.0;;"
+            "}"
+            "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 2.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }"
+            "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */
+              "1.0, 0.0, 0.0, 0.0,"
+              "0.0, 1.0, 0.0, 0.0,"
+              "0.0, 0.0, 1.0, 0.0,"
+              "0.0, 0.0, 3.0, 1.0;;"
+            "}"
+            "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }"
+        "}";
+    static const WORD framed_index_buffer[] = { 0, 1, 2 };
+    static const D3DXVECTOR3 framed_vertex_buffers[3][3] = {
+        {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}},
+        {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}},
+        {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}},
+    };
+    const DWORD framed_fvf = D3DFVF_XYZ;
+    /*________________________*/
+    HRESULT hr;
+    HWND wnd = NULL;
+    IDirect3D9 *d3d = NULL;
+    IDirect3DDevice9 *device = NULL;
+    D3DPRESENT_PARAMETERS d3dpp;
+    ID3DXMesh *mesh = NULL;
+    D3DXFRAME *frame_hier = NULL;
+    D3DXMATRIX transform;
+
+    wnd = CreateWindow("static", "d3dx9_test", WS_POPUP, 0, 0, 1000, 1000, NULL, NULL, NULL, NULL);
+    if (!wnd)
+    {
+        skip("Couldn't create application window\n");
+        return;
+    }
+    d3d = Direct3DCreate9(D3D_SDK_VERSION);
+    if (!d3d)
+    {
+        skip("Couldn't create IDirect3D9 object\n");
+        goto cleanup;
+    }
+
+    ZeroMemory(&d3dpp, sizeof(d3dpp));
+    d3dpp.Windowed = TRUE;
+    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device);
+    if (FAILED(hr))
+    {
+        skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
+        goto cleanup;
+    }
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1,
+            D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
+    ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0,
+            D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
+    ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
+            D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL);
+    ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
+            D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL);
+    ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1,
+            D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
+    ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr);
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
+            D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL);
+    ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr);
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1,
+            D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
+    ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+    if (SUCCEEDED(hr)) {
+        D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
+
+        ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name);
+        D3DXMatrixIdentity(&transform);
+        check_matrix(&frame_hier->TransformationMatrix, &transform);
+
+        ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
+        ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
+           D3DXMESHTYPE_MESH, container->MeshData.Type);
+        mesh = U(container->MeshData).pMesh;
+        check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf);
+        check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer));
+        check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
+        hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
+        ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+        frame_hier = NULL;
+    }
+
+    hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1,
+            D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL);
+    ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+    if (SUCCEEDED(hr)) {
+        D3DXMESHCONTAINER *container = frame_hier->pMeshContainer;
+        int i;
+
+        ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name);
+        /* last frame transform replaces the first */
+        D3DXMatrixIdentity(&transform);
+        U(transform).m[3][2] = 3.0;
+        check_matrix(&frame_hier->TransformationMatrix, &transform);
+
+        for (i = 0; i < 3; i++) {
+            ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name);
+            ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n",
+               D3DXMESHTYPE_MESH, container->MeshData.Type);
+            mesh = U(container->MeshData).pMesh;
+            check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf);
+            check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer));
+            check_generated_adjacency(mesh, container->pAdjacency, 0.0f);
+            container = container->pNextMeshContainer;
+        }
+        ok(container == NULL, "Expected NULL, got %p\n", container);
+        hr = D3DXFrameDestroy(frame_hier, &alloc_hier);
+        ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+        frame_hier = NULL;
+    }
+
+cleanup:
+    if (device) IDirect3DDevice9_Release(device);
+    if (d3d) IDirect3D9_Release(d3d);
+    if (wnd) DestroyWindow(wnd);
+}
+
 static void D3DXCreateBoxTest(void)
 {
     HRESULT hr;
@@ -3314,6 +3875,7 @@ START_TEST(mesh)
     D3DXIntersectTriTest();
     D3DXCreateMeshTest();
     D3DXCreateMeshFVFTest();
+    D3DXLoadMeshTest();
     D3DXCreateBoxTest();
     D3DXCreateSphereTest();
     D3DXCreateCylinderTest();
-- 
1.7.4.1




More information about the wine-patches mailing list