d3d9: Store wined3d vertex declarations in the fvf lookup table.
This also implicitly gets rid of the convFVF hack in IDirect3DVertexDeclaration9Impl_Release().
This commit is contained in:
parent
ba67df7a60
commit
5fc17b84d0
|
@ -156,6 +156,12 @@ typedef struct IDirect3D9Impl
|
||||||
|
|
||||||
void filter_caps(D3DCAPS9* pCaps) DECLSPEC_HIDDEN;
|
void filter_caps(D3DCAPS9* pCaps) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
struct fvf_declaration
|
||||||
|
{
|
||||||
|
struct wined3d_vertex_declaration *decl;
|
||||||
|
DWORD fvf;
|
||||||
|
};
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* IDirect3DDevice9 implementation structure
|
* IDirect3DDevice9 implementation structure
|
||||||
*/
|
*/
|
||||||
|
@ -169,8 +175,8 @@ typedef struct IDirect3DDevice9Impl
|
||||||
/* Avoids recursion with nested ReleaseRef to 0 */
|
/* Avoids recursion with nested ReleaseRef to 0 */
|
||||||
BOOL inDestruction;
|
BOOL inDestruction;
|
||||||
|
|
||||||
IDirect3DVertexDeclaration9 **convertedDecls;
|
struct fvf_declaration *fvf_decls;
|
||||||
unsigned int numConvertedDecls, declArraySize;
|
UINT fvf_decl_count, fvf_decl_size;
|
||||||
|
|
||||||
BOOL notreset;
|
BOOL notreset;
|
||||||
BOOL in_scene;
|
BOOL in_scene;
|
||||||
|
@ -394,7 +400,6 @@ typedef struct IDirect3DVertexDeclaration9Impl {
|
||||||
LPDIRECT3DDEVICE9EX parentDevice;
|
LPDIRECT3DDEVICE9EX parentDevice;
|
||||||
} IDirect3DVertexDeclaration9Impl;
|
} IDirect3DVertexDeclaration9Impl;
|
||||||
|
|
||||||
void IDirect3DVertexDeclaration9Impl_Destroy(LPDIRECT3DVERTEXDECLARATION9 iface) DECLSPEC_HIDDEN;
|
|
||||||
HRESULT d3d9_vertex_declaration_create(IDirect3DDevice9Impl *device,
|
HRESULT d3d9_vertex_declaration_create(IDirect3DDevice9Impl *device,
|
||||||
const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9Impl **declaration) DECLSPEC_HIDDEN;
|
const D3DVERTEXELEMENT9 *elements, IDirect3DVertexDeclaration9Impl **declaration) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
|
@ -234,36 +234,38 @@ static ULONG WINAPI IDirect3DDevice9Impl_AddRef(IDirect3DDevice9Ex *iface)
|
||||||
|
|
||||||
static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(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;
|
ULONG ref;
|
||||||
|
|
||||||
if (This->inDestruction) return 0;
|
if (device->inDestruction)
|
||||||
ref = InterlockedDecrement(&This->ref);
|
return 0;
|
||||||
|
|
||||||
|
ref = InterlockedDecrement(&device->ref);
|
||||||
|
|
||||||
TRACE("%p decreasing refcount to %u.\n", iface, ref);
|
TRACE("%p decreasing refcount to %u.\n", iface, ref);
|
||||||
|
|
||||||
if (ref == 0) {
|
if (!ref)
|
||||||
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
This->inDestruction = TRUE;
|
device->inDestruction = TRUE;
|
||||||
|
|
||||||
wined3d_mutex_lock();
|
wined3d_mutex_lock();
|
||||||
for(i = 0; i < This->numConvertedDecls; i++) {
|
for (i = 0; i < device->fvf_decl_count; ++i)
|
||||||
/* Unless Wine is buggy or the app has a bug the refcount will be 0, because decls hold a reference to the
|
{
|
||||||
* device
|
wined3d_vertex_declaration_decref(device->fvf_decls[i].decl);
|
||||||
*/
|
|
||||||
IDirect3DVertexDeclaration9Impl_Destroy(This->convertedDecls[i]);
|
|
||||||
}
|
}
|
||||||
HeapFree(GetProcessHeap(), 0, This->convertedDecls);
|
HeapFree(GetProcessHeap(), 0, device->fvf_decls);
|
||||||
|
|
||||||
wined3d_device_uninit_3d(This->wined3d_device);
|
wined3d_device_uninit_3d(device->wined3d_device);
|
||||||
wined3d_device_release_focus_window(This->wined3d_device);
|
wined3d_device_release_focus_window(device->wined3d_device);
|
||||||
wined3d_device_decref(This->wined3d_device);
|
wined3d_device_decref(device->wined3d_device);
|
||||||
wined3d_mutex_unlock();
|
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;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2136,91 +2138,100 @@ static HRESULT WINAPI IDirect3DDevice9Impl_GetVertexDeclaration(IDirect3DDevice9
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IDirect3DVertexDeclaration9 *getConvertedDecl(IDirect3DDevice9Impl *This, DWORD fvf) {
|
static struct wined3d_vertex_declaration *device_get_fvf_declaration(IDirect3DDevice9Impl *device, DWORD fvf)
|
||||||
HRESULT hr;
|
{
|
||||||
D3DVERTEXELEMENT9* elements = NULL;
|
struct wined3d_vertex_declaration *wined3d_declaration;
|
||||||
IDirect3DVertexDeclaration9* pDecl = NULL;
|
struct fvf_declaration *fvf_decls = device->fvf_decls;
|
||||||
|
IDirect3DVertexDeclaration9Impl *d3d9_declaration;
|
||||||
|
D3DVERTEXELEMENT9 *elements;
|
||||||
int p, low, high; /* deliberately signed */
|
int p, low, high; /* deliberately signed */
|
||||||
IDirect3DVertexDeclaration9 **convertedDecls = This->convertedDecls;
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("Searching for declaration for fvf %08x... ", fvf);
|
TRACE("Searching for declaration for fvf %08x... ", fvf);
|
||||||
|
|
||||||
low = 0;
|
low = 0;
|
||||||
high = This->numConvertedDecls - 1;
|
high = device->fvf_decl_count - 1;
|
||||||
while(low <= high) {
|
while (low <= high)
|
||||||
|
{
|
||||||
p = (low + high) >> 1;
|
p = (low + high) >> 1;
|
||||||
TRACE("%d ", p);
|
TRACE("%d ", p);
|
||||||
if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF == fvf) {
|
|
||||||
TRACE("found %p\n", convertedDecls[p]);
|
if (fvf_decls[p].fvf == fvf)
|
||||||
return convertedDecls[p];
|
{
|
||||||
} else if(((IDirect3DVertexDeclaration9Impl *) convertedDecls[p])->convFVF < fvf) {
|
TRACE("found %p.\n", fvf_decls[p].decl);
|
||||||
low = p + 1;
|
return fvf_decls[p].decl;
|
||||||
} else {
|
|
||||||
high = p - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fvf_decls[p].fvf < fvf)
|
||||||
|
low = p + 1;
|
||||||
|
else
|
||||||
|
high = p - 1;
|
||||||
}
|
}
|
||||||
TRACE("not found. Creating and inserting at position %d.\n", low);
|
TRACE("not found. Creating and inserting at position %d.\n", low);
|
||||||
|
|
||||||
hr = vdecl_convert_fvf(fvf, &elements);
|
if (FAILED(hr = vdecl_convert_fvf(fvf, &elements)))
|
||||||
if (hr != S_OK) return NULL;
|
return NULL;
|
||||||
|
|
||||||
hr = IDirect3DDevice9Impl_CreateVertexDeclaration(&This->IDirect3DDevice9Ex_iface, elements,
|
hr = d3d9_vertex_declaration_create(device, elements, &d3d9_declaration);
|
||||||
&pDecl);
|
HeapFree(GetProcessHeap(), 0, elements);
|
||||||
HeapFree(GetProcessHeap(), 0, elements); /* CreateVertexDeclaration makes a copy */
|
if (FAILED(hr))
|
||||||
if (hr != S_OK) return NULL;
|
return NULL;
|
||||||
|
|
||||||
if(This->declArraySize == This->numConvertedDecls) {
|
if (device->fvf_decl_size == device->fvf_decl_count)
|
||||||
int grow = max(This->declArraySize / 2, 8);
|
{
|
||||||
convertedDecls = HeapReAlloc(GetProcessHeap(), 0, convertedDecls,
|
UINT grow = max(device->fvf_decl_size / 2, 8);
|
||||||
sizeof(convertedDecls[0]) * (This->numConvertedDecls + grow));
|
|
||||||
if(!convertedDecls) {
|
fvf_decls = HeapReAlloc(GetProcessHeap(), 0, fvf_decls, sizeof(*fvf_decls) * (device->fvf_decl_size + grow));
|
||||||
/* This will destroy it */
|
if (!fvf_decls)
|
||||||
IDirect3DVertexDeclaration9_Release(pDecl);
|
{
|
||||||
|
IDirect3DVertexDeclaration9_Release((IDirect3DVertexDeclaration9 *)d3d9_declaration);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
This->convertedDecls = convertedDecls;
|
device->fvf_decls = fvf_decls;
|
||||||
This->declArraySize += grow;
|
device->fvf_decl_size += grow;
|
||||||
}
|
}
|
||||||
|
|
||||||
memmove(convertedDecls + low + 1, convertedDecls + low, sizeof(IDirect3DVertexDeclaration9Impl *) * (This->numConvertedDecls - low));
|
d3d9_declaration->convFVF = fvf;
|
||||||
convertedDecls[low] = pDecl;
|
wined3d_declaration = d3d9_declaration->wineD3DVertexDeclaration;
|
||||||
This->numConvertedDecls++;
|
wined3d_vertex_declaration_incref(wined3d_declaration);
|
||||||
|
IDirect3DVertexDeclaration9_Release((IDirect3DVertexDeclaration9 *)d3d9_declaration);
|
||||||
|
|
||||||
/* Will prevent the decl from being destroyed */
|
memmove(fvf_decls + low + 1, fvf_decls + low, sizeof(*fvf_decls) * (device->fvf_decl_count - low));
|
||||||
((IDirect3DVertexDeclaration9Impl *) pDecl)->convFVF = fvf;
|
fvf_decls[low].decl = wined3d_declaration;
|
||||||
IDirect3DVertexDeclaration9_Release(pDecl); /* Does not destroy now */
|
fvf_decls[low].fvf = fvf;
|
||||||
|
++device->fvf_decl_count;
|
||||||
|
|
||||||
TRACE("Returning %p. %d decls in array\n", pDecl, This->numConvertedDecls);
|
TRACE("Returning %p. %u declatations in array.\n", wined3d_declaration, device->fvf_decl_count);
|
||||||
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);
|
IDirect3DDevice9Impl *This = impl_from_IDirect3DDevice9Ex(iface);
|
||||||
IDirect3DVertexDeclaration9 *decl;
|
struct wined3d_vertex_declaration *decl;
|
||||||
HRESULT hr;
|
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;
|
return D3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
wined3d_mutex_lock();
|
wined3d_mutex_lock();
|
||||||
decl = getConvertedDecl(This, FVF);
|
if (!(decl = device_get_fvf_declaration(This, fvf)))
|
||||||
wined3d_mutex_unlock();
|
|
||||||
|
|
||||||
if (!decl)
|
|
||||||
{
|
{
|
||||||
/* Any situation when this should happen, except out of memory? */
|
wined3d_mutex_unlock();
|
||||||
ERR("Failed to create a converted vertex declaration\n");
|
ERR("Failed to create a vertex declaration for fvf %#x.\n", fvf);
|
||||||
return D3DERR_DRIVERINTERNALERROR;
|
return D3DERR_DRIVERINTERNALERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IDirect3DDevice9Impl_SetVertexDeclaration(iface, decl);
|
hr = wined3d_device_set_vertex_declaration(This->wined3d_device, decl);
|
||||||
if (FAILED(hr)) ERR("Failed to set vertex declaration\n");
|
if (FAILED(hr))
|
||||||
|
ERR("Failed to set vertex declaration.\n");
|
||||||
|
wined3d_mutex_unlock();
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -3466,8 +3477,8 @@ HRESULT device_init(IDirect3DDevice9Impl *device, IDirect3D9Impl *parent, struct
|
||||||
|
|
||||||
/* Initialize the converted declaration array. This creates a valid pointer
|
/* Initialize the converted declaration array. This creates a valid pointer
|
||||||
* and when adding decls HeapReAlloc() can be used without further checking. */
|
* and when adding decls HeapReAlloc() can be used without further checking. */
|
||||||
device->convertedDecls = HeapAlloc(GetProcessHeap(), 0, 0);
|
device->fvf_decls = HeapAlloc(GetProcessHeap(), 0, 0);
|
||||||
if (!device->convertedDecls)
|
if (!device->fvf_decls)
|
||||||
{
|
{
|
||||||
ERR("Failed to allocate FVF vertex declaration map memory.\n");
|
ERR("Failed to allocate FVF vertex declaration map memory.\n");
|
||||||
wined3d_mutex_lock();
|
wined3d_mutex_lock();
|
||||||
|
|
|
@ -219,44 +219,29 @@ static ULONG WINAPI IDirect3DVertexDeclaration9Impl_AddRef(LPDIRECT3DVERTEXDECLA
|
||||||
|
|
||||||
TRACE("%p increasing refcount to %u.\n", iface, ref);
|
TRACE("%p increasing refcount to %u.\n", iface, ref);
|
||||||
|
|
||||||
if(ref == 1) {
|
if (ref == 1)
|
||||||
IDirect3DDevice9Ex_AddRef(This->parentDevice);
|
|
||||||
if (!This->convFVF)
|
|
||||||
{
|
{
|
||||||
|
IDirect3DDevice9Ex_AddRef(This->parentDevice);
|
||||||
wined3d_mutex_lock();
|
wined3d_mutex_lock();
|
||||||
wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration);
|
wined3d_vertex_declaration_incref(This->wineD3DVertexDeclaration);
|
||||||
wined3d_mutex_unlock();
|
wined3d_mutex_unlock();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ref;
|
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) {
|
static ULONG WINAPI IDirect3DVertexDeclaration9Impl_Release(LPDIRECT3DVERTEXDECLARATION9 iface) {
|
||||||
IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
|
IDirect3DVertexDeclaration9Impl *This = (IDirect3DVertexDeclaration9Impl *)iface;
|
||||||
ULONG ref = InterlockedDecrement(&This->ref);
|
ULONG ref = InterlockedDecrement(&This->ref);
|
||||||
|
|
||||||
TRACE("%p decreasing refcount to %u.\n", iface, ref);
|
TRACE("%p decreasing refcount to %u.\n", iface, ref);
|
||||||
|
|
||||||
if (ref == 0) {
|
if (!ref)
|
||||||
|
{
|
||||||
IDirect3DDevice9Ex *parentDevice = This->parentDevice;
|
IDirect3DDevice9Ex *parentDevice = This->parentDevice;
|
||||||
|
wined3d_mutex_lock();
|
||||||
if(!This->convFVF) {
|
wined3d_vertex_declaration_decref(This->wineD3DVertexDeclaration);
|
||||||
IDirect3DVertexDeclaration9Impl_Destroy(iface);
|
wined3d_mutex_unlock();
|
||||||
}
|
|
||||||
|
|
||||||
/* Release the device last, as it may cause the device to be destroyed. */
|
/* Release the device last, as it may cause the device to be destroyed. */
|
||||||
IDirect3DDevice9Ex_Release(parentDevice);
|
IDirect3DDevice9Ex_Release(parentDevice);
|
||||||
|
|
Loading…
Reference in New Issue