d3dx9: Implement UpdateSemantics mesh method.
This commit is contained in:
parent
4df270a8bd
commit
39d4656b2a
|
@ -6,6 +6,7 @@
|
|||
* Copyright (C) 2009 David Adam
|
||||
* Copyright (C) 2010 Tony Wasserka
|
||||
* Copyright (C) 2011 Dylan Smith
|
||||
* Copyright (C) 2011 Michael Mc Donnell
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -52,7 +53,10 @@ typedef struct ID3DXMeshImpl
|
|||
DWORD options;
|
||||
DWORD fvf;
|
||||
IDirect3DDevice9 *device;
|
||||
D3DVERTEXELEMENT9 cached_declaration[MAX_FVF_DECL_SIZE];
|
||||
IDirect3DVertexDeclaration9 *vertex_declaration;
|
||||
UINT vertex_declaration_size;
|
||||
UINT num_elem;
|
||||
IDirect3DVertexBuffer9 *vertex_buffer;
|
||||
IDirect3DIndexBuffer9 *index_buffer;
|
||||
DWORD *attrib_buffer;
|
||||
|
@ -106,7 +110,8 @@ static ULONG WINAPI ID3DXMeshImpl_Release(ID3DXMesh *iface)
|
|||
{
|
||||
IDirect3DIndexBuffer9_Release(This->index_buffer);
|
||||
IDirect3DVertexBuffer9_Release(This->vertex_buffer);
|
||||
IDirect3DVertexDeclaration9_Release(This->vertex_declaration);
|
||||
if (This->vertex_declaration)
|
||||
IDirect3DVertexDeclaration9_Release(This->vertex_declaration);
|
||||
IDirect3DDevice9_Release(This->device);
|
||||
HeapFree(GetProcessHeap(), 0, This->attrib_buffer);
|
||||
HeapFree(GetProcessHeap(), 0, This->attrib_table);
|
||||
|
@ -127,6 +132,12 @@ static HRESULT WINAPI ID3DXMeshImpl_DrawSubset(ID3DXMesh *iface, DWORD attrib_id
|
|||
|
||||
TRACE("(%p)->(%u)\n", This, attrib_id);
|
||||
|
||||
if (!This->vertex_declaration)
|
||||
{
|
||||
WARN("Can't draw a mesh with an invalid vertex declaration.\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
vertex_size = iface->lpVtbl->GetNumBytesPerVertex(iface);
|
||||
|
||||
hr = IDirect3DDevice9_SetVertexDeclaration(This->device, This->vertex_declaration);
|
||||
|
@ -186,32 +197,31 @@ static DWORD WINAPI ID3DXMeshImpl_GetFVF(ID3DXMesh *iface)
|
|||
return This->fvf;
|
||||
}
|
||||
|
||||
static void copy_declaration(D3DVERTEXELEMENT9 *dst, const D3DVERTEXELEMENT9 *src, UINT num_elem)
|
||||
{
|
||||
memcpy(dst, src, num_elem * sizeof(*src));
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ID3DXMeshImpl_GetDeclaration(ID3DXMesh *iface, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
|
||||
{
|
||||
ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface);
|
||||
UINT numelements;
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
if (declaration == NULL) return D3DERR_INVALIDCALL;
|
||||
|
||||
return IDirect3DVertexDeclaration9_GetDeclaration(This->vertex_declaration,
|
||||
declaration,
|
||||
&numelements);
|
||||
copy_declaration(declaration, This->cached_declaration, This->num_elem);
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
static DWORD WINAPI ID3DXMeshImpl_GetNumBytesPerVertex(ID3DXMesh *iface)
|
||||
{
|
||||
ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface);
|
||||
UINT numelements;
|
||||
D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = { D3DDECL_END() };
|
||||
|
||||
TRACE("iface (%p)\n", This);
|
||||
|
||||
IDirect3DVertexDeclaration9_GetDeclaration(This->vertex_declaration,
|
||||
declaration,
|
||||
&numelements);
|
||||
return D3DXGetDeclVertexSize(declaration, 0);
|
||||
return This->vertex_declaration_size;
|
||||
}
|
||||
|
||||
static DWORD WINAPI ID3DXMeshImpl_GetOptions(ID3DXMesh *iface)
|
||||
|
@ -603,11 +613,61 @@ cleanup:
|
|||
|
||||
static HRESULT WINAPI ID3DXMeshImpl_UpdateSemantics(ID3DXMesh *iface, D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE])
|
||||
{
|
||||
HRESULT hr;
|
||||
ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface);
|
||||
UINT vertex_declaration_size;
|
||||
int i;
|
||||
|
||||
FIXME("(%p)->(%p): stub\n", This, declaration);
|
||||
TRACE("(%p)->(%p)\n", This, declaration);
|
||||
|
||||
return E_NOTIMPL;
|
||||
if (!declaration)
|
||||
{
|
||||
WARN("Invalid declaration. Can't use NULL declaration.\n");
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
/* New declaration must be same size as original */
|
||||
vertex_declaration_size = D3DXGetDeclVertexSize(declaration, declaration[0].Stream);
|
||||
if (vertex_declaration_size != This->vertex_declaration_size)
|
||||
{
|
||||
WARN("Invalid declaration. New vertex size does not match the orginal vertex size.\n");
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
/* New declaration must not contain non-zero Stream value */
|
||||
for (i = 0; declaration[i].Stream != 0xff; i++)
|
||||
{
|
||||
if (declaration[i].Stream != 0)
|
||||
{
|
||||
WARN("Invalid declaration. New declaration contains non-zero Stream value.\n");
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
}
|
||||
|
||||
This->num_elem = i + 1;
|
||||
copy_declaration(This->cached_declaration, declaration, This->num_elem);
|
||||
|
||||
if (This->vertex_declaration)
|
||||
IDirect3DVertexDeclaration9_Release(This->vertex_declaration);
|
||||
|
||||
/* An application can pass an invalid declaration to UpdateSemantics and
|
||||
* still expect D3D_OK (see tests). If the declaration is invalid, then
|
||||
* subsequent calls to DrawSubset will fail. This is handled by setting the
|
||||
* vertex declaration to NULL.
|
||||
* GetDeclaration, GetNumBytesPerVertex must, however, use the new
|
||||
* invalid declaration. This is handled by them using the cached vertex
|
||||
* declaration instead of the actual vertex declaration.
|
||||
*/
|
||||
hr = IDirect3DDevice9_CreateVertexDeclaration(This->device,
|
||||
declaration,
|
||||
&This->vertex_declaration);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WARN("Using invalid declaration. Calls to DrawSubset will fail.\n");
|
||||
This->vertex_declaration = NULL;
|
||||
}
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
/*** ID3DXMesh ***/
|
||||
|
@ -1652,6 +1712,8 @@ HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options,
|
|||
HRESULT hr;
|
||||
DWORD fvf;
|
||||
IDirect3DVertexDeclaration9 *vertex_declaration;
|
||||
UINT vertex_declaration_size;
|
||||
UINT num_elem;
|
||||
IDirect3DVertexBuffer9 *vertex_buffer;
|
||||
IDirect3DIndexBuffer9 *index_buffer;
|
||||
DWORD *attrib_buffer;
|
||||
|
@ -1674,6 +1736,7 @@ HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options,
|
|||
for (i = 0; declaration[i].Stream != 0xff; i++)
|
||||
if (declaration[i].Stream != 0)
|
||||
return D3DERR_INVALIDCALL;
|
||||
num_elem = i + 1;
|
||||
|
||||
if (options & D3DXMESH_32BIT)
|
||||
index_format = D3DFMT_INDEX32;
|
||||
|
@ -1734,10 +1797,11 @@ HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options,
|
|||
WARN("Unexpected return value %x from IDirect3DDevice9_CreateVertexDeclaration.\n",hr);
|
||||
return hr;
|
||||
}
|
||||
vertex_declaration_size = D3DXGetDeclVertexSize(declaration, declaration[0].Stream);
|
||||
|
||||
/* Create vertex buffer */
|
||||
hr = IDirect3DDevice9_CreateVertexBuffer(device,
|
||||
numvertices * D3DXGetDeclVertexSize(declaration, declaration[0].Stream),
|
||||
numvertices * vertex_declaration_size,
|
||||
vertex_usage,
|
||||
fvf,
|
||||
vertex_pool,
|
||||
|
@ -1787,7 +1851,10 @@ HRESULT WINAPI D3DXCreateMesh(DWORD numfaces, DWORD numvertices, DWORD options,
|
|||
object->device = device;
|
||||
IDirect3DDevice9_AddRef(device);
|
||||
|
||||
copy_declaration(object->cached_declaration, declaration, num_elem);
|
||||
object->vertex_declaration = vertex_declaration;
|
||||
object->vertex_declaration_size = vertex_declaration_size;
|
||||
object->num_elem = num_elem;
|
||||
object->vertex_buffer = vertex_buffer;
|
||||
object->index_buffer = index_buffer;
|
||||
object->attrib_buffer = attrib_buffer;
|
||||
|
|
|
@ -4490,7 +4490,7 @@ static void test_update_semantics(void)
|
|||
}
|
||||
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
|
||||
todo_wine ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
|
||||
ok(hr == D3D_OK, "Test UpdateSematics, got %#x expected %#x\n", hr, D3D_OK);
|
||||
|
||||
/* Check that declaration was written by getting it again */
|
||||
memset(declaration, 0, sizeof(declaration));
|
||||
|
@ -4505,8 +4505,8 @@ static void test_update_semantics(void)
|
|||
{
|
||||
if (decl_ptr->Usage == D3DDECLUSAGE_POSITION)
|
||||
{
|
||||
todo_wine ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
|
||||
decl_ptr->Offset, offset);
|
||||
ok(decl_ptr->Offset == offset, "Test UpdateSematics, got offset %d expected %d\n",
|
||||
decl_ptr->Offset, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4516,7 +4516,7 @@ static void test_update_semantics(void)
|
|||
memset(declaration, filler_a, sizeof(declaration));
|
||||
memcpy(declaration, declaration0, sizeof(declaration0));
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
|
||||
todo_wine ok(hr == D3D_OK, "Test UpdateSematics, "
|
||||
ok(hr == D3D_OK, "Test UpdateSematics, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
memset(declaration, filler_b, sizeof(declaration));
|
||||
hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
|
||||
|
@ -4549,13 +4549,13 @@ static void test_update_semantics(void)
|
|||
}
|
||||
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration);
|
||||
todo_wine ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
ok(hr == D3D_OK, "Test UpdateSematics for overlapping fields, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
|
||||
/* Set the position type to color instead of float3 */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color);
|
||||
todo_wine ok(hr == D3D_OK, "Test UpdateSematics position type color, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
ok(hr == D3D_OK, "Test UpdateSematics position type color, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
|
||||
/* The following test cases show that NULL, smaller or larger declarations,
|
||||
* and declarations with non-zero Stream values are not accepted.
|
||||
|
@ -4567,8 +4567,8 @@ static void test_update_semantics(void)
|
|||
/* Null declaration (invalid declaration) */
|
||||
mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL);
|
||||
todo_wine ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
|
||||
"got %#x expected D3DERR_INVALIDCALL\n", hr);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics null pointer declaration, "
|
||||
"got %#x expected D3DERR_INVALIDCALL\n", hr);
|
||||
vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
|
||||
ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
|
||||
vertex_size, exp_vertex_size);
|
||||
|
@ -4581,8 +4581,8 @@ static void test_update_semantics(void)
|
|||
/* Smaller vertex declaration (invalid declaration) */
|
||||
mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller);
|
||||
todo_wine ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
|
||||
"got %#x expected D3DERR_INVALIDCALL\n", hr);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for smaller vertex declaration, "
|
||||
"got %#x expected D3DERR_INVALIDCALL\n", hr);
|
||||
vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
|
||||
ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
|
||||
vertex_size, exp_vertex_size);
|
||||
|
@ -4595,8 +4595,8 @@ static void test_update_semantics(void)
|
|||
/* Larger vertex declaration (invalid declaration) */
|
||||
mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger);
|
||||
todo_wine ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
|
||||
"got %#x expected D3DERR_INVALIDCALL\n", hr);
|
||||
ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics for larger vertex declaration, "
|
||||
"got %#x expected D3DERR_INVALIDCALL\n", hr);
|
||||
vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
|
||||
ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
|
||||
vertex_size, exp_vertex_size);
|
||||
|
@ -4609,7 +4609,7 @@ static void test_update_semantics(void)
|
|||
/* Use multiple streams and keep the same vertex size (invalid declaration) */
|
||||
mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams);
|
||||
todo_wine ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
|
||||
ok(hr == D3DERR_INVALIDCALL, "Test UpdateSematics using multiple streams, "
|
||||
"got %#x expected D3DERR_INVALIDCALL\n", hr);
|
||||
vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
|
||||
ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
|
||||
|
@ -4629,8 +4629,8 @@ static void test_update_semantics(void)
|
|||
/* Double usage (invalid declaration) */
|
||||
mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage);
|
||||
todo_wine ok(hr == D3D_OK, "Test UpdateSematics double usage, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
ok(hr == D3D_OK, "Test UpdateSematics double usage, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
|
||||
ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
|
||||
vertex_size, exp_vertex_size);
|
||||
|
@ -4638,13 +4638,13 @@ static void test_update_semantics(void)
|
|||
hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
|
||||
ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
|
||||
equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage));
|
||||
todo_wine ok(equal == 0, "Vertex declarations were not equal\n");
|
||||
ok(equal == 0, "Vertex declarations were not equal\n");
|
||||
|
||||
/* Set the position to an undefined type (invalid declaration) */
|
||||
mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type);
|
||||
todo_wine ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
ok(hr == D3D_OK, "Test UpdateSematics undefined type, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
|
||||
ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
|
||||
vertex_size, exp_vertex_size);
|
||||
|
@ -4652,12 +4652,12 @@ static void test_update_semantics(void)
|
|||
hr = mesh->lpVtbl->GetDeclaration(mesh, declaration);
|
||||
ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
|
||||
equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type));
|
||||
todo_wine ok(equal == 0, "Vertex declarations were not equal\n");
|
||||
ok(equal == 0, "Vertex declarations were not equal\n");
|
||||
|
||||
/* Use a not 4 byte aligned offset (invalid declaration) */
|
||||
mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */
|
||||
hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset);
|
||||
todo_wine ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
|
||||
ok(hr == D3D_OK, "Test UpdateSematics not 4 byte aligned offset, "
|
||||
"got %#x expected D3D_OK\n", hr);
|
||||
vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh);
|
||||
ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n",
|
||||
|
@ -4667,7 +4667,7 @@ static void test_update_semantics(void)
|
|||
ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr);
|
||||
equal = memcmp(declaration, declaration_not_4_byte_aligned_offset,
|
||||
sizeof(declaration_not_4_byte_aligned_offset));
|
||||
todo_wine ok(equal == 0, "Vertex declarations were not equal\n");
|
||||
ok(equal == 0, "Vertex declarations were not equal\n");
|
||||
|
||||
cleanup:
|
||||
if (mesh)
|
||||
|
|
Loading…
Reference in New Issue