[PATCH 2/5] d3d9: Store wined3d vertex declarations in the fvf lookup table.
Henri Verbeet
hverbeet at codeweavers.com
Wed Apr 11 15:52:03 CDT 2012
This also implicitly gets rid of the convFVF hack in
IDirect3DVertexDeclaration9Impl_Release().
---
dlls/d3d9/d3d9_private.h | 11 ++-
dlls/d3d9/device.c | 159 ++++++++++++++++++++++-------------------
dlls/d3d9/vertexdeclaration.c | 35 +++-------
3 files changed, 103 insertions(+), 102 deletions(-)
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 6ad6eed..485ee12 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -156,6 +156,12 @@ typedef struct IDirect3D9Impl
void filter_caps(D3DCAPS9* pCaps) DECLSPEC_HIDDEN;
+struct fvf_declaration
+{
+ struct wined3d_vertex_declaration *decl;
+ DWORD fvf;
+};
+
/*****************************************************************************
* IDirect3DDevice9 implementation structure
*/
@@ -169,8 +175,8 @@ typedef struct IDirect3DDevice9Impl
/* Avoids recursion with nested ReleaseRef to 0 */
BOOL inDestruction;
- IDirect3DVertexDeclaration9 **convertedDecls;
- unsigned int numConvertedDecls, declArraySize;
+ struct fvf_declaration *fvf_decls;
+ UINT fvf_decl_count, fvf_decl_size;
BOOL notreset;
BOOL in_scene;
@@ -394,7 +400,6 @@ typedef struct IDirect3DVertexDeclaration9Impl {
LPDIRECT3DDEVICE9EX parentDevice;
} IDirect3DVertexDeclaration9Impl;
-void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) DECLSPEC_HIDDEN;
HRESULT d3d9_vertex_declaration_create(IDirect3DDevice9Impl *device,
const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9Impl **declaration) DECLSPEC_HIDDEN;
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index 3aeb437..440533c 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -234,36 +234,38 @@ static ULONG WINAPI IDirect3DDevice9Impl_AddRef(IDirect3DDevice9Ex *iface)
static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(IDirect3DDevice9Ex *iface)
{
- IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
+ IDirect3DDevice9Impl *device = impl_from_IDirect3DDevice9Ex(iface);
ULONG ref;
- if (This->inDestruction) return 0;
- ref = InterlockedDecrement(&This->ref);
+ if (device->inDestruction)
+ return 0;
+
+ ref = InterlockedDecrement(&device->ref);
TRACE("%p decreasing refcount to %u.\n", iface, ref);
- if (ref == 0) {
- unsigned i;
- This->inDestruction = TRUE;
+ if (!ref)
+ {
+ unsigned i;
+ device->inDestruction = TRUE;
- wined3d_mutex_lock();
- for(i = 0; i < This->numConvertedDecls; i++) {
- /* Unless Wine is buggy or the app has a bug the refcount will be 0, because decls hold a reference to the
- * device
- */
- IDirect3DVertexDeclaration9Impl_Destroy(This->convertedDecls[i]);
- }
- HeapFree(GetProcessHeap(), 0, This->convertedDecls);
+ wined3d_mutex_lock();
+ for (i = 0; i < device->fvf_decl_count; ++i)
+ {
+ wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
+ }
+ HeapFree(GetProcessHeap(), 0, device->fvf_decls);
- wined3d_device_uninit_3d(This->wined3d_device);
- wined3d_device_release_focus_window(This->wined3d_device);
- wined3d_device_decref(This->wined3d_device);
- wined3d_mutex_unlock();
+ wined3d_device_uninit_3d(device->wined3d_device);
+ wined3d_device_release_focus_window(device->wined3d_device);
+ wined3d_device_decref(device->wined3d_device);
+ wined3d_mutex_unlock();
- IDirect3D9Ex_Release(&This->d3d_parent->IDirect3D9Ex_iface);
+ IDirect3D9Ex_Release(&device->d3d_parent->IDirect3D9Ex_iface);
- HeapFree(GetProcessHeap(), 0, This);
+ HeapFree(GetProcessHeap(), 0, device);
}
+
return ref;
}
@@ -2136,91 +2138,100 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(IDirect3DDevice9
return hr;
}
-static IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD fvf) {
- HRESULT hr;
- D3DVERTEXELEMENT9* elements = NULL;
- IDirect3DVertexDeclaration9* pDecl = NULL;
+static struct wined3d_vertex_declaration *device_get_fvf_declaration(IDirect3DDevice9Impl *device, DWORD fvf)
+{
+ struct wined3d_vertex_declaration *wined3d_declaration;
+ struct fvf_declaration *fvf_decls = device->fvf_decls;
+ IDirect3DVertexDeclaration9Impl *d3d9_declaration;
+ D3DVERTEXELEMENT9 *elements;
int p, low, high; /* deliberately signed */
- IDirect3DVertexDeclaration9 **convertedDecls = This->convertedDecls;
+ HRESULT hr;
TRACE("Searching for declaration for fvf %08x... ", fvf);
low = 0;
- high = This->numConvertedDecls - 1;
- while(low <= high) {
+ high = device->fvf_decl_count - 1;
+ while (low <= high)
+ {
p = (low + high) >> 1;
TRACE("%d ", p);
- if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF == fvf) {
- TRACE("found %p\n", convertedDecls[p]);
- return convertedDecls[p];
- } else if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF < fvf) {
+
+ if (fvf_decls[p].fvf == fvf)
+ {
+ TRACE("found %p.\n", fvf_decls[p].decl);
+ return fvf_decls[p].decl;
+ }
+
+ if (fvf_decls[p].fvf < fvf)
low = p + 1;
- } else {
+ else
high = p - 1;
- }
}
TRACE("not found. Creating and inserting at position %d.\n", low);
- hr = vdecl_convert_fvf(fvf, &elements);
- if (hr != S_OK) return NULL;
-
- hr = IDirect3DDevice9Impl_CreateVertexDeclaration(&This->IDirect3DDevice9Ex_iface, elements,
- &pDecl);
- HeapFree(GetProcessHeap(), 0, elements); /* CreateVertexDeclaration makes a copy */
- if (hr != S_OK) return NULL;
-
- if(This->declArraySize == This->numConvertedDecls) {
- int grow = max(This->declArraySize / 2, 8);
- convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
- sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
- if(!convertedDecls) {
- /* This will destroy it */
- IDirect3DVertexDeclaration9_Release(pDecl);
+ if (FAILED(hr = vdecl_convert_fvf(fvf, &elements)))
+ return NULL;
+
+ hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
+ HeapFree(GetProcessHeap(), 0, elements);
+ if (FAILED(hr))
+ return NULL;
+
+ if (device->fvf_decl_size == device->fvf_decl_count)
+ {
+ UINT grow = max(device->fvf_decl_size / 2, 8);
+
+ fvf_decls = HeapReAlloc(GetProcessHeap(), 0, fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow));
+ if (!fvf_decls)
+ {
+ IDirect3DVertexDeclaration9_Release((IDirect3DVertexDeclaration9 *)d3d9_declaration);
return NULL;
}
- This->convertedDecls = convertedDecls;
- This->declArraySize += grow;
+ device->fvf_decls = fvf_decls;
+ device->fvf_decl_size += grow;
}
- memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(IDirect3DVertexDeclaration9Impl *) * (This->numConvertedDecls - low));
- convertedDecls[low] = pDecl;
- This->numConvertedDecls++;
+ d3d9_declaration->convFVF = fvf;
+ wined3d_declaration = d3d9_declaration->wineD3DVertexDeclaration;
+ wined3d_vertex_declaration_incref(wined3d_declaration);
+ IDirect3DVertexDeclaration9_Release((IDirect3DVertexDeclaration9 *)d3d9_declaration);
+
+ memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
+ fvf_decls[low].decl = wined3d_declaration;
+ fvf_decls[low].fvf = fvf;
+ ++device->fvf_decl_count;
- /* Will prevent the decl from being destroyed */
- ((IDirect3DVertexDeclaration9Impl *) pDecl)->convFVF = fvf;
- IDirect3DVertexDeclaration9_Release(pDecl); /* Does not destroy now */
+ TRACE("Returning %p. %u declatations in array.\n", wined3d_declaration, device->fvf_decl_count);
- TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
- return pDecl;
+ return wined3d_declaration;
}
-static HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(IDirect3DDevice9Ex *iface, DWORD FVF)
+static HRESULT WINAPI IDirect3DDevice9Impl_SetFVF(IDirect3DDevice9Ex *iface, DWORD fvf)
{
IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
- IDirect3DVertexDeclaration9 *decl;
+ struct wined3d_vertex_declaration *decl;
HRESULT hr;
- TRACE("iface %p, fvf %#x.\n", iface, FVF);
+ TRACE("iface %p, fvf %#x.\n", iface, fvf);
- if (!FVF)
+ if (!fvf)
{
- WARN("%#x is not a valid FVF\n", FVF);
+ WARN("%#x is not a valid FVF.\n", fvf);
return D3D_OK;
}
wined3d_mutex_lock();
- decl = getConvertedDecl(This, FVF);
- wined3d_mutex_unlock();
-
- if (!decl)
+ if (!(decl = device_get_fvf_declaration(This, fvf)))
{
- /* Any situation when this should happen, except out of memory? */
- ERR("Failed to create a converted vertex declaration\n");
- return D3DERR_DRIVERINTERNALERROR;
+ wined3d_mutex_unlock();
+ ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
+ return D3DERR_DRIVERINTERNALERROR;
}
- hr = IDirect3DDevice9Impl_SetVertexDeclaration(iface, decl);
- if (FAILED(hr)) ERR("Failed to set vertex declaration\n");
+ hr = wined3d_device_set_vertex_declaration(This->wined3d_device, decl);
+ if (FAILED(hr))
+ ERR("Failed to set vertex declaration.\n");
+ wined3d_mutex_unlock();
return hr;
}
@@ -3466,8 +3477,8 @@ HRESULT device_init(IDirect3DDevice9Impl *device, IDirect3D9Impl *parent, struct
/* Initialize the converted declaration array. This creates a valid pointer
* and when adding decls HeapReAlloc() can be used without further checking. */
- device->convertedDecls = HeapAlloc(GetProcessHeap(), 0, 0);
- if (!device->convertedDecls)
+ device->fvf_decls = HeapAlloc(GetProcessHeap(), 0, 0);
+ if (!device->fvf_decls)
{
ERR("Failed to allocate FVF vertex declaration map memory.\n");
wined3d_mutex_lock();
diff --git a/dlls/d3d9/vertexdeclaration.c b/dlls/d3d9/vertexdeclaration.c
index a003d88..4636b14 100644
--- a/dlls/d3d9/vertexdeclaration.c
+++ b/dlls/d3d9/vertexdeclaration.c
@@ -219,44 +219,29 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_AddRef(LPDIRECT3DVERTEXDECLA
TRACE("%p increasing refcount to %u.\n", iface, ref);
- if(ref == 1) {
+ if (ref == 1)
+ {
IDirect3DDevice9Ex_AddRef(This->parentDevice);
- if (!This->convFVF)
- {
- wined3d_mutex_lock();
- wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration);
- wined3d_mutex_unlock();
- }
+ wined3d_mutex_lock();
+ wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration);
+ wined3d_mutex_unlock();
}
return ref;
}
-void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) {
- IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
-
- if(This->ref != 0) {
- /* Should not happen unless wine has a bug or the application releases references it does not own */
- ERR("Destroying vdecl with ref != 0\n");
- }
-
- wined3d_mutex_lock();
- wined3d_vertex_declaration_decref(This->wineD3DVertexDeclaration);
- wined3d_mutex_unlock();
-}
-
static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECLARATION9 iface) {
IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("%p decreasing refcount to %u.\n", iface, ref);
- if (ref == 0) {
+ if (!ref)
+ {
IDirect3DDevice9Ex *parentDevice = This->parentDevice;
-
- if(!This->convFVF) {
- IDirect3DVertexDeclaration9Impl_Destroy(iface);
- }
+ wined3d_mutex_lock();
+ wined3d_vertex_declaration_decref(This->wineD3DVertexDeclaration);
+ wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */
IDirect3DDevice9Ex_Release(parentDevice);
--
1.7.3.4
More information about the wine-patches
mailing list