Module: wine Branch: master Commit: 04dcffe393da66d458255c2c4bcd70ef40d72584 URL: http://source.winehq.org/git/wine.git/?a=commit;h=04dcffe393da66d458255c2c4b...
Author: Markus Amsler markus.amsler@oribi.org Date: Mon Dec 18 00:16:48 2006 +0100
d3d9: Handle surface refcount forwarding in d3d9.
---
dlls/d3d9/cubetexture.c | 2 +- dlls/d3d9/d3d9_private.h | 5 +++++ dlls/d3d9/device.c | 12 ++++++++++++ dlls/d3d9/surface.c | 18 +++++++----------- dlls/d3d9/tests/device.c | 2 +- dlls/d3d9/texture.c | 2 +- 6 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/dlls/d3d9/cubetexture.c b/dlls/d3d9/cubetexture.c index e140b2e..c372314 100644 --- a/dlls/d3d9/cubetexture.c +++ b/dlls/d3d9/cubetexture.c @@ -60,7 +60,7 @@ static ULONG WINAPI IDirect3DCubeTexture
if (ref == 0) { TRACE("Releasing child %p\n", This->wineD3DCubeTexture); - IWineD3DCubeTexture_Release(This->wineD3DCubeTexture); + IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D9CB_DestroySurface); IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); } diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index 5aa7ea6..0555b3a 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -301,6 +301,9 @@ typedef struct IDirect3DSurface9Impl
/* Parent reference */ LPDIRECT3DDEVICE9 parentDevice; + + /* If set forward refcounting to this object */ + IUnknown *forwardReference; } IDirect3DSurface9Impl;
/* ---------------------- */ @@ -543,4 +546,6 @@ extern HRESULT WINAPI D3D9CB_CreateRende
extern ULONG WINAPI D3D9CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface);
+extern ULONG WINAPI D3D9CB_DestroySurface(IWineD3DSurface *pSurface); + #endif /* __WINE_D3D9_PRIVATE_H */ diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index bd96b10..82fe762 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1011,8 +1011,20 @@ HRESULT WINAPI D3D9CB_CreateSurface(IUnk *ppSurface = d3dSurface->wineD3DSurface; IUnknown_Release(d3dSurface->parentDevice); d3dSurface->parentDevice = NULL; + d3dSurface->forwardReference = pSuperior; } else { FIXME("(%p) IDirect3DDevice9_CreateSurface failed\n", device); } return res; } + +ULONG WINAPI D3D9CB_DestroySurface(IWineD3DSurface *pSurface) { + IDirect3DSurface9Impl* surfaceParent; + TRACE("(%p) call back\n", pSurface); + + IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent); + /* GetParent's AddRef was forwarded to an object in destruction. + * Releasing it here again would cause an endless recursion. */ + surfaceParent->forwardReference = NULL; + return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent); +} diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c index e953540..c2f94a6 100644 --- a/dlls/d3d9/surface.c +++ b/dlls/d3d9/surface.c @@ -43,15 +43,13 @@ static HRESULT WINAPI IDirect3DSurface9I
static ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; - IUnknown *containerParent = NULL;
TRACE("(%p)\n", This);
- IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &containerParent); - if (containerParent) { - /* Forward to the containerParent */ - TRACE("(%p) : Forwarding to %p\n", This, containerParent); - return IUnknown_AddRef(containerParent); + if (This->forwardReference) { + /* Forward refcounting */ + TRACE("(%p) : Forwarding to %p\n", This, This->forwardReference); + return IUnknown_AddRef(This->forwardReference); } else { /* No container, handle our own refcounting */ ULONG ref = InterlockedIncrement(&This->ref); @@ -64,15 +62,13 @@ static ULONG WINAPI IDirect3DSurface9Imp
static ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) { IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface; - IUnknown *containerParent = NULL;
TRACE("(%p)\n", This);
- IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &containerParent); - if (containerParent) { + if (This->forwardReference) { /* Forward to the containerParent */ - TRACE("(%p) : Forwarding to %p\n", This, containerParent); - return IUnknown_Release(containerParent); + TRACE("(%p) : Forwarding to %p\n", This, This->forwardReference); + return IUnknown_Release(This->forwardReference); } else { /* No container, handle our own refcounting */ ULONG ref = InterlockedDecrement(&This->ref); diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index a1336f2..de8f661 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -540,7 +540,7 @@ static void test_refcount(void) /* check implicit back buffer */ hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer); todo_wine CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount); - todo_wine CHECK_REFCOUNT( pSwapChain, 1); + CHECK_REFCOUNT( pSwapChain, 1); if(pBackBuffer) { CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain); diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c index 427a7a2..7eecacd 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -59,7 +59,7 @@ static ULONG WINAPI IDirect3DTexture9Imp TRACE("(%p) : ReleaseRef to %d\n", This, ref);
if (ref == 0) { - IWineD3DTexture_Release(This->wineD3DTexture); + IWineD3DTexture_Destroy(This->wineD3DTexture, D3D9CB_DestroySurface); IUnknown_Release(This->parentDevice); HeapFree(GetProcessHeap(), 0, This); }