Markus Amsler : d3d9: Handle surface refcount forwarding in d3d9.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Dec 18 05:34:38 CST 2006
Module: wine
Branch: master
Commit: 04dcffe393da66d458255c2c4bcd70ef40d72584
URL: http://source.winehq.org/git/wine.git/?a=commit;h=04dcffe393da66d458255c2c4bcd70ef40d72584
Author: Markus Amsler <markus.amsler at 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);
}
More information about the wine-cvs
mailing list