[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