Module: wine Branch: master Commit: e62a4276ed381525f58e531b3a6f73c52f37d1f9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e62a4276ed381525f58e531b3a...
Author: Dylan Smith dylan.ah.smith@gmail.com Date: Mon May 9 06:30:34 2011 -0400
d3dx9: Implement ID3DXMesh::CloneMesh without vertex buffer conversion.
---
dlls/d3dx9_36/mesh.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 96 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c index 4dffa62..cfb19bc 100644 --- a/dlls/d3dx9_36/mesh.c +++ b/dlls/d3dx9_36/mesh.c @@ -25,6 +25,7 @@ #include "config.h" #include "wine/port.h"
+#define COBJMACROS #define NONAMELESSUNION #include "windef.h" #include "wingdi.h" @@ -232,20 +233,110 @@ static HRESULT WINAPI ID3DXMeshImpl_GetDevice(ID3DXMesh *iface, LPDIRECT3DDEVICE static HRESULT WINAPI ID3DXMeshImpl_CloneMeshFVF(ID3DXMesh *iface, DWORD options, DWORD fvf, LPDIRECT3DDEVICE9 device, LPD3DXMESH *clone_mesh) { ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface); + HRESULT hr; + D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE];
- FIXME("(%p)->(%u,%u,%p,%p): stub\n", This, options, fvf, device, clone_mesh); + TRACE("(%p)->(%x,%x,%p,%p)\n", This, options, fvf, device, clone_mesh);
- return E_NOTIMPL; + hr = D3DXDeclaratorFromFVF(fvf, declaration); + if (FAILED(hr)) return hr; + + return iface->lpVtbl->CloneMesh(iface, options, declaration, device, clone_mesh); }
static HRESULT WINAPI ID3DXMeshImpl_CloneMesh(ID3DXMesh *iface, DWORD options, CONST D3DVERTEXELEMENT9 *declaration, LPDIRECT3DDEVICE9 device, - LPD3DXMESH *clone_mesh) + LPD3DXMESH *clone_mesh_out) { ID3DXMeshImpl *This = impl_from_ID3DXMesh(iface); + ID3DXMeshImpl *cloned_this; + ID3DXMesh *clone_mesh; + D3DVERTEXELEMENT9 orig_declaration[MAX_FVF_DECL_SIZE] = { D3DDECL_END() }; + void *data_in, *data_out; + DWORD vertex_size; + HRESULT hr; + int i;
- FIXME("(%p)->(%u,%p,%p,%p): stub\n", This, options, declaration, device, clone_mesh); + TRACE("(%p)->(%x,%p,%p,%p)\n", This, options, declaration, device, clone_mesh_out);
- return E_NOTIMPL; + if (!clone_mesh_out) + return D3DERR_INVALIDCALL; + + hr = iface->lpVtbl->GetDeclaration(iface, orig_declaration); + if (FAILED(hr)) return hr; + + for (i = 0; orig_declaration[i].Stream != 0xff; i++) { + if (memcmp(&orig_declaration[i], &declaration[i], sizeof(*declaration))) + { + FIXME("Vertex buffer conversion not implemented.\n"); + return E_NOTIMPL; + } + } + + hr = D3DXCreateMesh(This->numfaces, This->numvertices, options & ~D3DXMESH_VB_SHARE, + declaration, device, &clone_mesh); + if (FAILED(hr)) return hr; + + cloned_this = impl_from_ID3DXMesh(clone_mesh); + vertex_size = clone_mesh->lpVtbl->GetNumBytesPerVertex(clone_mesh); + + if (options & D3DXMESH_VB_SHARE) { + IDirect3DVertexBuffer9_AddRef(This->vertex_buffer); + /* FIXME: refactor to avoid creating a new vertex buffer */ + IDirect3DVertexBuffer9_Release(cloned_this->vertex_buffer); + cloned_this->vertex_buffer = This->vertex_buffer; + } else { + hr = iface->lpVtbl->LockVertexBuffer(iface, D3DLOCK_READONLY, &data_in); + if (FAILED(hr)) goto error; + hr = clone_mesh->lpVtbl->LockVertexBuffer(clone_mesh, D3DLOCK_DISCARD, &data_out); + if (FAILED(hr)) { + iface->lpVtbl->UnlockVertexBuffer(iface); + goto error; + } + memcpy(data_out, data_in, This->numvertices * vertex_size); + clone_mesh->lpVtbl->UnlockVertexBuffer(clone_mesh); + iface->lpVtbl->UnlockVertexBuffer(iface); + } + + hr = iface->lpVtbl->LockIndexBuffer(iface, D3DLOCK_READONLY, &data_in); + if (FAILED(hr)) goto error; + hr = clone_mesh->lpVtbl->LockIndexBuffer(clone_mesh, D3DLOCK_DISCARD, &data_out); + if (FAILED(hr)) { + iface->lpVtbl->UnlockIndexBuffer(iface); + goto error; + } + if ((options ^ This->options) & D3DXMESH_32BIT) { + if (options & D3DXMESH_32BIT) { + for (i = 0; i < This->numfaces * 3; i++) + ((DWORD*)data_out)[i] = ((WORD*)data_in)[i]; + } else { + for (i = 0; i < This->numfaces * 3; i++) + ((WORD*)data_out)[i] = ((DWORD*)data_in)[i]; + } + } else { + memcpy(data_out, data_in, This->numfaces * 3 * (options & D3DXMESH_32BIT ? 4 : 2)); + } + clone_mesh->lpVtbl->UnlockIndexBuffer(clone_mesh); + iface->lpVtbl->UnlockIndexBuffer(iface); + + memcpy(cloned_this->attrib_buffer, This->attrib_buffer, This->numfaces * sizeof(*This->attrib_buffer)); + + if (This->attrib_table_size) + { + cloned_this->attrib_table_size = This->attrib_table_size; + cloned_this->attrib_table = HeapAlloc(GetProcessHeap(), 0, This->attrib_table_size * sizeof(*This->attrib_table)); + if (!cloned_this->attrib_table) { + hr = E_OUTOFMEMORY; + goto error; + } + memcpy(cloned_this->attrib_table, This->attrib_table, This->attrib_table_size * sizeof(*This->attrib_table)); + } + + *clone_mesh_out = clone_mesh; + + return D3D_OK; +error: + IUnknown_Release(clone_mesh); + return hr; }
static HRESULT WINAPI ID3DXMeshImpl_GetVertexBuffer(ID3DXMesh *iface, LPDIRECT3DVERTEXBUFFER9 *vertex_buffer)