D3D: Fix the relation between surfaces and their container.
H. Verbeet
hverbeet at gmail.com
Mon Mar 6 12:28:03 CST 2006
Based on a suggestion by Stefan Dösinger. Fix the relation between
surfaces and their container, as described here:
http://www.winehq.org/pipermail/wine-devel/2006-February/044857.html
Changelog:
- Fix the relation between surfaces and their container.
-------------- next part --------------
diff --git a/dlls/d3d8/surface.c b/dlls/d3d8/surface.c
index 5443411..587e20f 100644
--- a/dlls/d3d8/surface.c
+++ b/dlls/d3d8/surface.c
@@ -41,24 +41,46 @@ HRESULT WINAPI IDirect3DSurface8Impl_Que
ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) {
IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
- ULONG ref = InterlockedIncrement(&This->ref);
+ IUnknown *containerParent = NULL;
- TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
+ TRACE("(%p)\n", This);
- return ref;
+ IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &containerParent);
+ if (containerParent) {
+ /* Forward to the containerParent */
+ TRACE("(%p) : Forwarding to %p\n", This, containerParent);
+ return IUnknown_AddRef(containerParent);
+ } else {
+ /* No container, handle our own refcounting */
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
+ return ref;
+ }
}
ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) {
IDirect3DSurface8Impl *This = (IDirect3DSurface8Impl *)iface;
- ULONG ref = InterlockedDecrement(&This->ref);
+ IUnknown *containerParent = NULL;
+
+ TRACE("(%p)\n", This);
- TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
+ IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &containerParent);
+ if (containerParent) {
+ /* Forward to the containerParent */
+ TRACE("(%p) : Forwarding to %p\n", This, containerParent);
+ return IUnknown_Release(containerParent);
+ } else {
+ /* No container, handle our own refcounting */
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
+
+ if (ref == 0) {
+ IWineD3DSurface_Release(This->wineD3DSurface);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
- if (ref == 0) {
- IWineD3DSurface_Release(This->wineD3DSurface);
- HeapFree(GetProcessHeap(), 0, This);
+ return ref;
}
- return ref;
}
/* IDirect3DSurface8 IDirect3DResource8 Interface follow: */
diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c
index 62c99c7..479bcae 100644
--- a/dlls/d3d9/surface.c
+++ b/dlls/d3d9/surface.c
@@ -42,24 +42,48 @@ HRESULT WINAPI IDirect3DSurface9Impl_Que
ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) {
IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
- ULONG ref = InterlockedIncrement(&This->ref);
+ IUnknown *containerParent = NULL;
- TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
+ 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);
+ } else {
+ /* No container, handle our own refcounting */
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
+
+ return ref;
+ }
- return ref;
}
ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) {
IDirect3DSurface9Impl *This = (IDirect3DSurface9Impl *)iface;
- ULONG ref = InterlockedDecrement(&This->ref);
+ IUnknown *containerParent = NULL;
+
+ TRACE("(%p)\n", This);
- TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
+ IWineD3DSurface_GetContainerParent(This->wineD3DSurface, &containerParent);
+ if (containerParent) {
+ /* Forward to the containerParent */
+ TRACE("(%p) : Forwarding to %p\n", This, containerParent);
+ return IUnknown_Release(containerParent);
+ } else {
+ /* No container, handle our own refcounting */
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
+
+ if (ref == 0) {
+ IWineD3DSurface_Release(This->wineD3DSurface);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
- if (ref == 0) {
- IWineD3DSurface_Release(This->wineD3DSurface);
- HeapFree(GetProcessHeap(), 0, This);
+ return ref;
}
- return ref;
}
/* IDirect3DSurface9 IDirect3DResource9 Interface follow: */
diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c
index 966d8c2..9313b52 100644
--- a/dlls/wined3d/cubetexture.c
+++ b/dlls/wined3d/cubetexture.c
@@ -84,6 +84,9 @@ ULONG WINAPI IWineD3DCubeTextureImpl_Rel
IUnknown* surfaceParent;
/* Clean out the texture name we gave to the suface so that the surface doesn't try and release it */
IWineD3DSurface_SetGlTextureDesc(This->surfaces[j][i], 0, 0);
+ /* Cleanup the container */
+ IWineD3DSurface_SetContainer(This->surfaces[j][i], 0);
+ /* Now, release the parent, which will take care of cleaning up the surface for us */
TRACE("(%p) : Releasing surface%d %d %p\n", This, j, i, This->surfaces[j][i]);
IWineD3DSurface_GetParent(This->surfaces[j][i], &surfaceParent);
IUnknown_Release(surfaceParent);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 00c17e0..6b8a17f 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1433,7 +1433,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_Create
&This->depthStencilBuffer,
NULL /* pShared (always null)*/ );
if (This->depthStencilBuffer != NULL)
- IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IWineD3DBase *)iface);
+ IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
}
/** TODO: A check on width, height and multisample types
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index f8e6abf..c03587e 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -173,6 +173,29 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetPa
IWineD3DSurface IWineD3DSurface parts follow
****************************************************** */
+HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
+ IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
+
+ TRACE("(%p) : ppContainerParent %p)\n", This, ppContainerParent);
+
+ if (!ppContainerParent) {
+ ERR("(%p) : Called without a valid ppContainerParent.\n", This);
+ }
+
+ if (This->container) {
+ IWineD3DBase_GetParent(This->container, ppContainerParent);
+ if (!ppContainerParent) {
+ /* WineD3D objects should always have a parent */
+ ERR("(%p) : GetParent returned NULL\n", This);
+ }
+ IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */
+ } else {
+ *ppContainerParent = NULL;
+ }
+
+ return D3D_OK;
+}
+
HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DBase *container = 0;
@@ -1439,6 +1462,7 @@ const IWineD3DSurfaceVtbl IWineD3DSurfac
IWineD3DSurfaceImpl_PreLoad,
IWineD3DSurfaceImpl_GetType,
/* IWineD3DSurface */
+ IWineD3DSurfaceImpl_GetContainerParent,
IWineD3DSurfaceImpl_GetContainer,
IWineD3DSurfaceImpl_GetDesc,
IWineD3DSurfaceImpl_LockRect,
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 72effcd..02a8d2e 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -93,12 +93,14 @@ ULONG WINAPI IWineD3DSwapChainImpl_Relea
IWineD3DDevice_SwapChainReleased((IWineD3DDevice *)This->wineD3DDevice, iface);
/* release the ref to the front and back buffer parents */
+ IWineD3DSurface_SetContainer(This->frontBuffer, 0);
IWineD3DSurface_GetParent(This->frontBuffer, &bufferParent);
IUnknown_Release(bufferParent); /* once for the get parent */
if(IUnknown_Release(bufferParent) > 0){
FIXME("(%p) Something's still holding the front buffer\n",This);
}
+ IWineD3DSurface_SetContainer(This->backBuffer, 0);
IWineD3DSurface_GetParent(This->backBuffer, &bufferParent);
IUnknown_Release(bufferParent); /* once for the get parent */
if(IUnknown_Release(bufferParent) > 0){
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index e9d4600..125f81b 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -66,6 +66,9 @@ ULONG WINAPI IWineD3DTextureImpl_Release
IUnknown* surfaceParent;
/* Clean out the texture name we gave to the suface so that the surface doesn't try and release it */
IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], 0, 0);
+ /* Cleanup the container */
+ IWineD3DSurface_SetContainer(This->surfaces[i], 0);
+ /* Now, release the parent, which will take care of cleaning up the surface for us */
IWineD3DSurface_GetParent(This->surfaces[i], &surfaceParent);
IUnknown_Release(surfaceParent);
IUnknown_Release(surfaceParent);
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index 6947183..4184fee 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -1045,6 +1045,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWine
STDMETHOD_(void,PreLoad)(THIS) PURE;
STDMETHOD_(D3DRESOURCETYPE,GetType)(THIS) PURE;
/*** IWineD3DSurface methods ***/
+ STDMETHOD(GetContainerParent)(THIS_ IUnknown **ppContainerParent) PURE;
STDMETHOD(GetContainer)(THIS_ REFIID riid, void ** ppContainer) PURE;
STDMETHOD(GetDesc)(THIS_ WINED3DSURFACE_DESC * pDesc) PURE;
STDMETHOD(LockRect)(THIS_ D3DLOCKED_RECT * pLockedRect, CONST RECT * pRect,DWORD Flags) PURE;
@@ -1082,6 +1083,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWine
#define IWineD3DSurface_PreLoad(p) (p)->lpVtbl->PreLoad(p)
#define IWineD3DSurface_GetType(p) (p)->lpVtbl->GetType(p)
/*** IWineD3DSurface methods ***/
+#define IWineD3DSurface_GetContainerParent(p,a) (p)->lpVtbl->GetContainerParent(p,a)
#define IWineD3DSurface_GetContainer(p,a,b) (p)->lpVtbl->GetContainer(p,a,b)
#define IWineD3DSurface_GetDesc(p,a) (p)->lpVtbl->GetDesc(p,a)
#define IWineD3DSurface_LockRect(p,a,b,c) (p)->lpVtbl->LockRect(p,a,b,c)
More information about the wine-patches
mailing list