From 5fc17b84d01c1a38607f3d2501fe28b8fe1fc9ab Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 11 Apr 2012 22:52:03 +0200 Subject: [PATCH] d3d9: Store wined3d vertex declarations in the fvf lookup table. 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 6ad6eedc833..485ee12430a 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 3aeb437dbdf..440533c7d3f 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 a003d885a35..4636b141313 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); -- 2.11.4.GIT