diff --git a/dlls/d3d9/cubetexture.c b/dlls/d3d9/cubetexture.c index e140b2e103e..c3723143987 100644 --- a/dlls/d3d9/cubetexture.c +++ b/dlls/d3d9/cubetexture.c @@ -60,7 +60,7 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 ifa 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 5aa7ea69505..0555b3a4b13 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_CreateRenderTarget(IUnknown *device, IUnknown *pSup 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 bd96b10411c..82fe762266f 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1011,8 +1011,20 @@ HRESULT WINAPI D3D9CB_CreateSurface(IUnknown *device, IUnknown *pSuperior, UINT *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 e95354049d9..c2f94a691c2 100644 --- a/dlls/d3d9/surface.c +++ b/dlls/d3d9/surface.c @@ -43,15 +43,13 @@ static HRESULT WINAPI IDirect3DSurface9Impl_QueryInterface(LPDIRECT3DSURFACE9 if 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 IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) { 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 a1336f219c7..de8f66196c8 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 427a7a2d80e..7eecacd3d79 100644 --- a/dlls/d3d9/texture.c +++ b/dlls/d3d9/texture.c @@ -59,7 +59,7 @@ static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) { 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); }