[PATCH 01/10] wined3d: Don't free D3D surfaces until the wined3d surface is destroyed.

Henri Verbeet hverbeet at codeweavers.com
Wed Sep 16 01:37:15 CDT 2009


This prevents for example a d3d9 depth stencil from being destroyed when it
has no external references but is still in use by the device/stateblock. A
nice side effect is that it simplifies handling of "implicit" surfaces like
the frontbuffer and backbuffers, as well as the forwarding of reference counts
for surfaces that are part of a texture.
---
 dlls/d3d10core/device.c        |    6 ++
 dlls/d3d10core/texture2d.c     |   21 +++++++-
 dlls/d3d8/cubetexture.c        |    2 +-
 dlls/d3d8/d3d8_private.h       |    6 --
 dlls/d3d8/device.c             |   23 +++-----
 dlls/d3d8/directx.c            |   20 -------
 dlls/d3d8/surface.c            |   31 ++++++++---
 dlls/d3d8/swapchain.c          |    2 +-
 dlls/d3d8/texture.c            |    2 +-
 dlls/d3d9/cubetexture.c        |    2 +-
 dlls/d3d9/d3d9_private.h       |    6 --
 dlls/d3d9/device.c             |   22 +++-----
 dlls/d3d9/directx.c            |   20 -------
 dlls/d3d9/surface.c            |   31 ++++++++---
 dlls/d3d9/swapchain.c          |    2 +-
 dlls/d3d9/texture.c            |    2 +-
 dlls/ddraw/ddraw.c             |  109 ++++++++--------------------------------
 dlls/ddraw/ddraw_private.h     |    3 -
 dlls/ddraw/main.c              |    4 --
 dlls/ddraw/surface.c           |    9 +++-
 dlls/dxgi/swapchain.c          |   14 +-----
 dlls/wined3d/cubetexture.c     |   13 +++--
 dlls/wined3d/device.c          |   31 ++++-------
 dlls/wined3d/directx.c         |   18 +++----
 dlls/wined3d/surface.c         |    6 ++-
 dlls/wined3d/surface_base.c    |    4 +-
 dlls/wined3d/swapchain.c       |   11 ++--
 dlls/wined3d/swapchain_base.c  |    2 +-
 dlls/wined3d/swapchain_gdi.c   |   13 +++--
 dlls/wined3d/texture.c         |   13 +++--
 dlls/wined3d/wined3d_private.h |    6 +-
 include/wine/wined3d.idl       |   13 +++--
 32 files changed, 188 insertions(+), 279 deletions(-)

diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c
index 9026b75..6b685b0 100644
--- a/dlls/d3d10core/device.c
+++ b/dlls/d3d10core/device.c
@@ -1379,6 +1379,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
     }
 
     *surface = texture->wined3d_surface;
+    IWineD3DSurface_AddRef(*surface);
+    ID3D10Texture2D_Release((ID3D10Texture2D *)texture);
 
     return S_OK;
 }
@@ -1418,6 +1420,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
     }
 
     *surface = texture->wined3d_surface;
+    IWineD3DSurface_AddRef(*surface);
+    ID3D10Texture2D_Release((ID3D10Texture2D *)texture);
 
     return S_OK;
 }
@@ -1457,6 +1461,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
     }
 
     *surface = texture->wined3d_surface;
+    IWineD3DSurface_AddRef(*surface);
+    ID3D10Texture2D_Release((ID3D10Texture2D *)texture);
 
     return S_OK;
 }
diff --git a/dlls/d3d10core/texture2d.c b/dlls/d3d10core/texture2d.c
index edb2329..3d5eea1 100644
--- a/dlls/d3d10core/texture2d.c
+++ b/dlls/d3d10core/texture2d.c
@@ -61,9 +61,19 @@ static ULONG STDMETHODCALLTYPE d3d10_texture2d_AddRef(ID3D10Texture2D *iface)
 
     TRACE("%p increasing refcount to %u\n", This, refcount);
 
+    if (refcount == 1 && This->wined3d_surface) IWineD3DSurface_AddRef(This->wined3d_surface);
+
     return refcount;
 }
 
+static void STDMETHODCALLTYPE d3d10_texture2d_wined3d_object_released(void *parent)
+{
+    struct d3d10_texture2d *This = parent;
+
+    if (This->dxgi_surface) IDXGISurface_Release(This->dxgi_surface);
+    HeapFree(GetProcessHeap(), 0, This);
+}
+
 static ULONG STDMETHODCALLTYPE d3d10_texture2d_Release(ID3D10Texture2D *iface)
 {
     struct d3d10_texture2d *This = (struct d3d10_texture2d *)iface;
@@ -73,9 +83,8 @@ static ULONG STDMETHODCALLTYPE d3d10_texture2d_Release(ID3D10Texture2D *iface)
 
     if (!refcount)
     {
-        if (This->dxgi_surface) IDXGISurface_Release(This->dxgi_surface);
         if (This->wined3d_surface) IWineD3DSurface_Release(This->wined3d_surface);
-        HeapFree(GetProcessHeap(), 0, This);
+        else d3d10_texture2d_wined3d_object_released(This);
     }
 
     return refcount;
@@ -182,6 +191,11 @@ static const struct ID3D10Texture2DVtbl d3d10_texture2d_vtbl =
     d3d10_texture2d_GetDesc,
 };
 
+static const struct wined3d_parent_ops d3d10_texture2d_wined3d_parent_ops =
+{
+    d3d10_texture2d_wined3d_object_released,
+};
+
 HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_device *device,
         const D3D10_TEXTURE2D_DESC *desc)
 {
@@ -217,7 +231,8 @@ HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_devic
                 wined3dformat_from_dxgi_format(desc->Format), FALSE, FALSE, 0,
                 &texture->wined3d_surface, desc->Usage, WINED3DPOOL_DEFAULT,
                 desc->SampleDesc.Count > 1 ? desc->SampleDesc.Count : WINED3DMULTISAMPLE_NONE,
-                desc->SampleDesc.Quality, SURFACE_OPENGL, (IUnknown *)texture);
+                desc->SampleDesc.Quality, SURFACE_OPENGL, (IUnknown *)texture,
+                &d3d10_texture2d_wined3d_parent_ops);
         if (FAILED(hr))
         {
             ERR("CreateSurface failed, returning %#x\n", hr);
diff --git a/dlls/d3d8/cubetexture.c b/dlls/d3d8/cubetexture.c
index d0b8f72..4377693 100644
--- a/dlls/d3d8/cubetexture.c
+++ b/dlls/d3d8/cubetexture.c
@@ -59,7 +59,7 @@ static ULONG WINAPI IDirect3DCubeTexture8Impl_Release(LPDIRECT3DCUBETEXTURE8 ifa
         TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
 
         wined3d_mutex_lock();
-        IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D8CB_DestroySurface);
+        IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture);
         wined3d_mutex_unlock();
 
         IUnknown_Release(This->parentDevice);
diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h
index ba58cc3..af5b77a 100644
--- a/dlls/d3d8/d3d8_private.h
+++ b/dlls/d3d8/d3d8_private.h
@@ -284,9 +284,6 @@ struct IDirect3DSurface8Impl
 
     /* If set forward refcounting to this object */
     IUnknown                    *forwardReference;
-
-    /* Flags an implicit surface */
-    BOOL                        isImplicit;
 };
 
 HRESULT surface_init(IDirect3DSurface8Impl *surface, IDirect3DDevice8Impl *device,
@@ -650,9 +647,6 @@ size_t parse_token(const DWORD* pToken);
 
 /* Callbacks */
 extern ULONG WINAPI D3D8CB_DestroySwapChain (IWineD3DSwapChain *pSwapChain);
-extern ULONG WINAPI D3D8CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface);
-extern ULONG WINAPI D3D8CB_DestroyRenderTarget (IWineD3DSurface *pSurface);
-extern ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface);
 extern ULONG WINAPI D3D8CB_DestroyVolume(IWineD3DVolume *pVolume);
 
 #endif /* __WINE_D3DX8_PRIVATE_H */
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index 76cfe88..95425e5 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -309,7 +309,7 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
         }
         HeapFree(GetProcessHeap(), 0, This->decls);
 
-        IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D8CB_DestroyDepthStencilSurface, D3D8CB_DestroySwapChain);
+        IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D8CB_DestroySwapChain);
         IWineD3DDevice_Release(This->WineD3DDevice);
         HeapFree(GetProcessHeap(), 0, This->handle_table.entries);
         HeapFree(GetProcessHeap(), 0, This);
@@ -2602,17 +2602,6 @@ const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
     IDirect3DDevice8Impl_DeletePatch
 };
 
-ULONG WINAPI D3D8CB_DestroySurface(IWineD3DSurface *pSurface) {
-    IDirect3DSurface8Impl* 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 IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
-}
-
 /* IWineD3DDeviceParent IUnknown methods */
 
 static inline struct IDirect3DDevice8Impl *device_from_device_parent(IWineD3DDeviceParent *iface)
@@ -2672,9 +2661,13 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
     }
 
     *surface = d3d_surface->wineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
+
     d3d_surface->container = superior;
     IUnknown_Release(d3d_surface->parentDevice);
     d3d_surface->parentDevice = NULL;
+
+    IDirect3DSurface8_Release((IDirect3DSurface8 *)d3d_surface);
     d3d_surface->forwardReference = superior;
 
     return hr;
@@ -2701,8 +2694,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
     }
 
     *surface = d3d_surface->wineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
+
     d3d_surface->container = (IUnknown *)This;
-    d3d_surface->isImplicit = TRUE;
     /* Implicit surfaces are created with an refcount of 0 */
     IUnknown_Release((IUnknown *)d3d_surface);
 
@@ -2730,8 +2724,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
     }
 
     *surface = d3d_surface->wineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
+
     d3d_surface->container = (IUnknown *)This;
-    d3d_surface->isImplicit = TRUE;
     /* Implicit surfaces are created with an refcount of 0 */
     IUnknown_Release((IUnknown *)d3d_surface);
 
diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c
index 3368794..1ad7aef 100644
--- a/dlls/d3d8/directx.c
+++ b/dlls/d3d8/directx.c
@@ -312,16 +312,6 @@ static HMONITOR WINAPI  IDirect3D8Impl_GetAdapterMonitor(LPDIRECT3D8 iface, UINT
     return ret;
 }
 
-ULONG WINAPI D3D8CB_DestroyRenderTarget(IWineD3DSurface *pSurface) {
-    IDirect3DSurface8Impl* surfaceParent;
-    TRACE("(%p) call back\n", pSurface);
-
-    IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
-    surfaceParent->isImplicit = FALSE;
-    /* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
-    return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
-}
-
 ULONG WINAPI D3D8CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
     IUnknown* swapChainParent;
     TRACE("(%p) call back\n", pSwapChain);
@@ -331,16 +321,6 @@ ULONG WINAPI D3D8CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
     return IUnknown_Release(swapChainParent);
 }
 
-ULONG WINAPI D3D8CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) {
-    IDirect3DSurface8Impl* surfaceParent;
-    TRACE("(%p) call back\n", pSurface);
-
-    IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
-    surfaceParent->isImplicit = FALSE;
-    /* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
-    return IDirect3DSurface8_Release((IDirect3DSurface8*) surfaceParent);
-}
-
 static HRESULT WINAPI IDirect3D8Impl_CreateDevice(LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
                                             DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
                                             IDirect3DDevice8** ppReturnedDeviceInterface) {
diff --git a/dlls/d3d8/surface.c b/dlls/d3d8/surface.c
index 4cbe1c6..2d00fce 100644
--- a/dlls/d3d8/surface.c
+++ b/dlls/d3d8/surface.c
@@ -52,7 +52,13 @@ static ULONG WINAPI IDirect3DSurface8Impl_AddRef(LPDIRECT3DSURFACE8 iface) {
     } else {
         /* No container, handle our own refcounting */
         ULONG ref = InterlockedIncrement(&This->ref);
-        if(ref == 1 && This->parentDevice) IUnknown_AddRef(This->parentDevice);
+        if (ref == 1)
+        {
+            if (This->parentDevice) IUnknown_AddRef(This->parentDevice);
+            wined3d_mutex_lock();
+            IUnknown_AddRef(This->wineD3DSurface);
+            wined3d_mutex_unlock();
+        }
         TRACE("(%p) : AddRef from %d\n", This, ref - 1);
         return ref;
     }
@@ -75,13 +81,9 @@ static ULONG WINAPI IDirect3DSurface8Impl_Release(LPDIRECT3DSURFACE8 iface) {
         if (ref == 0) {
             if (This->parentDevice) IUnknown_Release(This->parentDevice);
             /* Implicit surfaces are destroyed with the device, not if refcount reaches 0. */
-            if (!This->isImplicit) {
-                wined3d_mutex_lock();
-                IWineD3DSurface_Release(This->wineD3DSurface);
-                wined3d_mutex_unlock();
-
-                HeapFree(GetProcessHeap(), 0, This);
-            }
+            wined3d_mutex_lock();
+            IWineD3DSurface_Release(This->wineD3DSurface);
+            wined3d_mutex_unlock();
         }
 
         return ref;
@@ -247,6 +249,16 @@ static const IDirect3DSurface8Vtbl Direct3DSurface8_Vtbl =
     IDirect3DSurface8Impl_UnlockRect
 };
 
+static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d8_surface_wined3d_parent_ops =
+{
+    surface_wined3d_object_destroyed,
+};
+
 HRESULT surface_init(IDirect3DSurface8Impl *surface, IDirect3DDevice8Impl *device,
         UINT width, UINT height, D3DFORMAT format, BOOL lockable, BOOL discard, UINT level,
         DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
@@ -266,7 +278,8 @@ HRESULT surface_init(IDirect3DSurface8Impl *surface, IDirect3DDevice8Impl *devic
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateSurface(device->WineD3DDevice, width, height, wined3dformat_from_d3dformat(format),
             lockable, discard, level, &surface->wineD3DSurface, usage & WINED3DUSAGE_MASK, (WINED3DPOOL)pool,
-            multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface);
+            multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface,
+            &d3d8_surface_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/d3d8/swapchain.c b/dlls/d3d8/swapchain.c
index 67f3429..e851548 100644
--- a/dlls/d3d8/swapchain.c
+++ b/dlls/d3d8/swapchain.c
@@ -57,7 +57,7 @@ static ULONG WINAPI IDirect3DSwapChain8Impl_Release(LPDIRECT3DSWAPCHAIN8 iface)
 
     if (ref == 0) {
         wined3d_mutex_lock();
-        IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D8CB_DestroyRenderTarget);
+        IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
         wined3d_mutex_unlock();
 
         if (This->parentDevice) IUnknown_Release(This->parentDevice);
diff --git a/dlls/d3d8/texture.c b/dlls/d3d8/texture.c
index c22c491..b4c4a5b 100644
--- a/dlls/d3d8/texture.c
+++ b/dlls/d3d8/texture.c
@@ -58,7 +58,7 @@ static ULONG WINAPI IDirect3DTexture8Impl_Release(LPDIRECT3DTEXTURE8 iface) {
 
     if (ref == 0) {
         wined3d_mutex_lock();
-        IWineD3DTexture_Destroy(This->wineD3DTexture, D3D8CB_DestroySurface);
+        IWineD3DTexture_Destroy(This->wineD3DTexture);
         wined3d_mutex_unlock();
 
         IUnknown_Release(This->parentDevice);
diff --git a/dlls/d3d9/cubetexture.c b/dlls/d3d9/cubetexture.c
index 8209d0b..8ab29fd 100644
--- a/dlls/d3d9/cubetexture.c
+++ b/dlls/d3d9/cubetexture.c
@@ -62,7 +62,7 @@ static ULONG WINAPI IDirect3DCubeTexture9Impl_Release(LPDIRECT3DCUBETEXTURE9 ifa
         TRACE("Releasing child %p\n", This->wineD3DCubeTexture);
 
         wined3d_mutex_lock();
-        IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture, D3D9CB_DestroySurface);
+        IWineD3DCubeTexture_Destroy(This->wineD3DCubeTexture);
         IDirect3DDevice9Ex_Release(This->parentDevice);
         wined3d_mutex_unlock();
 
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h
index 5c30024..494a6f3 100644
--- a/dlls/d3d9/d3d9_private.h
+++ b/dlls/d3d9/d3d9_private.h
@@ -301,9 +301,6 @@ typedef struct IDirect3DSurface9Impl
     /* If set forward refcounting to this object */
     IUnknown                    *forwardReference;
 
-    /* Flags an implicit surface */
-    BOOL                        isImplicit;
-
     BOOL                        getdc_supported;
 } IDirect3DSurface9Impl;
 
@@ -539,9 +536,6 @@ typedef struct IDirect3DQuery9Impl {
 
 /* Callbacks */
 extern ULONG WINAPI D3D9CB_DestroySwapChain (IWineD3DSwapChain *pSwapChain);
-extern ULONG WINAPI D3D9CB_DestroyDepthStencilSurface (IWineD3DSurface *pSurface);
-extern ULONG WINAPI D3D9CB_DestroyRenderTarget (IWineD3DSurface *pSurface);
-extern ULONG WINAPI D3D9CB_DestroySurface(IWineD3DSurface *pSurface);
 extern ULONG WINAPI D3D9CB_DestroyVolume(IWineD3DVolume *pVolume);
 
 #endif /* __WINE_D3D9_PRIVATE_H */
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index f57eb4d..e681542 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -257,7 +257,7 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9EX iface) {
       }
       HeapFree(GetProcessHeap(), 0, This->convertedDecls);
 
-      IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D9CB_DestroyDepthStencilSurface, D3D9CB_DestroySwapChain);
+      IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D9CB_DestroySwapChain);
       IWineD3DDevice_Release(This->WineD3DDevice);
       wined3d_mutex_unlock();
 
@@ -1997,17 +1997,6 @@ const IDirect3DDevice9ExVtbl Direct3DDevice9_Vtbl =
     IDirect3DDevice9ExImpl_GetDisplayModeEx
 };
 
-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);
-}
-
 /* IWineD3DDeviceParent IUnknown methods */
 
 static inline struct IDirect3DDevice9Impl *device_from_device_parent(IWineD3DDeviceParent *iface)
@@ -2067,9 +2056,13 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
     }
 
     *surface = d3d_surface->wineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
+
     d3d_surface->container = superior;
     IDirect3DDevice9Ex_Release(d3d_surface->parentDevice);
     d3d_surface->parentDevice = NULL;
+
+    IDirect3DSurface9_Release((IDirect3DSurface9 *)d3d_surface);
     d3d_surface->forwardReference = superior;
 
     return hr;
@@ -2097,8 +2090,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
     }
 
     *surface = d3d_surface->wineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
+
     d3d_surface->container = superior;
-    d3d_surface->isImplicit = TRUE;
     /* Implicit surfaces are created with an refcount of 0 */
     IDirect3DSurface9_Release((IDirect3DSurface9 *)d3d_surface);
 
@@ -2127,8 +2121,8 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
     }
 
     *surface = d3d_surface->wineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
     d3d_surface->container = (IUnknown *)This;
-    d3d_surface->isImplicit = TRUE;
     /* Implicit surfaces are created with an refcount of 0 */
     IDirect3DSurface9_Release((IDirect3DSurface9 *)d3d_surface);
 
diff --git a/dlls/d3d9/directx.c b/dlls/d3d9/directx.c
index fe22916..aba3362 100644
--- a/dlls/d3d9/directx.c
+++ b/dlls/d3d9/directx.c
@@ -383,16 +383,6 @@ static HMONITOR WINAPI IDirect3D9Impl_GetAdapterMonitor(LPDIRECT3D9EX iface, UIN
     return ret;
 }
 
-ULONG WINAPI D3D9CB_DestroyRenderTarget(IWineD3DSurface *pSurface) {
-    IDirect3DSurface9Impl* surfaceParent;
-    TRACE("(%p) call back\n", pSurface);
-
-    IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
-    surfaceParent->isImplicit = FALSE;
-    /* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
-    return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
-}
-
 ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
     IDirect3DSwapChain9Impl* swapChainParent;
     TRACE("(%p) call back\n", pSwapChain);
@@ -403,16 +393,6 @@ ULONG WINAPI D3D9CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
     return IDirect3DSwapChain9_Release((IDirect3DSwapChain9*) swapChainParent);
 }
 
-ULONG WINAPI D3D9CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) {
-    IDirect3DSurface9Impl* surfaceParent;
-    TRACE("(%p) call back\n", pSurface);
-
-    IWineD3DSurface_GetParent(pSurface, (IUnknown **) &surfaceParent);
-    surfaceParent->isImplicit = FALSE;
-    /* Surface had refcount of 0 GetParent addrefed to 1, so 1 Release is enough */
-    return IDirect3DSurface9_Release((IDirect3DSurface9*) surfaceParent);
-}
-
 static HRESULT WINAPI IDirect3D9Impl_CreateDevice(LPDIRECT3D9EX iface, UINT Adapter, D3DDEVTYPE DeviceType,
                                                   HWND hFocusWindow, DWORD BehaviourFlags,
                                                   D3DPRESENT_PARAMETERS* pPresentationParameters,
diff --git a/dlls/d3d9/surface.c b/dlls/d3d9/surface.c
index adb0420..f9b2794 100644
--- a/dlls/d3d9/surface.c
+++ b/dlls/d3d9/surface.c
@@ -53,7 +53,13 @@ static ULONG WINAPI IDirect3DSurface9Impl_AddRef(LPDIRECT3DSURFACE9 iface) {
     } else {
         /* No container, handle our own refcounting */
         ULONG ref = InterlockedIncrement(&This->ref);
-        if(ref == 1 && This->parentDevice) IDirect3DDevice9Ex_AddRef(This->parentDevice);
+        if (ref == 1)
+        {
+            if (This->parentDevice) IDirect3DDevice9Ex_AddRef(This->parentDevice);
+            wined3d_mutex_lock();
+            IWineD3DSurface_AddRef(This->wineD3DSurface);
+            wined3d_mutex_unlock();
+        }
         TRACE("(%p) : AddRef from %d\n", This, ref - 1);
 
         return ref;
@@ -77,13 +83,9 @@ static ULONG WINAPI IDirect3DSurface9Impl_Release(LPDIRECT3DSURFACE9 iface) {
 
         if (ref == 0) {
             if (This->parentDevice) IDirect3DDevice9Ex_Release(This->parentDevice);
-            if (!This->isImplicit) {
-                wined3d_mutex_lock();
-                IWineD3DSurface_Release(This->wineD3DSurface);
-                wined3d_mutex_unlock();
-
-                HeapFree(GetProcessHeap(), 0, This);
-            }
+            wined3d_mutex_lock();
+            IWineD3DSurface_Release(This->wineD3DSurface);
+            wined3d_mutex_unlock();
         }
 
         return ref;
@@ -322,6 +324,16 @@ static const IDirect3DSurface9Vtbl Direct3DSurface9_Vtbl =
     IDirect3DSurface9Impl_ReleaseDC
 };
 
+static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent)
+{
+    HeapFree(GetProcessHeap(), 0, parent);
+}
+
+static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
+{
+    surface_wined3d_object_destroyed,
+};
+
 HRESULT surface_init(IDirect3DSurface9Impl *surface, IDirect3DDevice9Impl *device,
         UINT width, UINT height, D3DFORMAT format, BOOL lockable, BOOL discard, UINT level,
         DWORD usage, D3DPOOL pool, D3DMULTISAMPLE_TYPE multisample_type, DWORD multisample_quality)
@@ -357,7 +369,8 @@ HRESULT surface_init(IDirect3DSurface9Impl *surface, IDirect3DDevice9Impl *devic
     wined3d_mutex_lock();
     hr = IWineD3DDevice_CreateSurface(device->WineD3DDevice, width, height, wined3dformat_from_d3dformat(format),
             lockable, discard, level, &surface->wineD3DSurface, usage & WINED3DUSAGE_MASK, (WINED3DPOOL)pool,
-            multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface);
+            multisample_type, multisample_quality, SURFACE_OPENGL, (IUnknown *)surface,
+            &d3d9_surface_wined3d_parent_ops);
     wined3d_mutex_unlock();
     if (FAILED(hr))
     {
diff --git a/dlls/d3d9/swapchain.c b/dlls/d3d9/swapchain.c
index fb66807..e63e343 100644
--- a/dlls/d3d9/swapchain.c
+++ b/dlls/d3d9/swapchain.c
@@ -63,7 +63,7 @@ static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface)
         if (This->parentDevice) IDirect3DDevice9Ex_Release(This->parentDevice);
         if (!This->isImplicit) {
             wined3d_mutex_lock();
-            IWineD3DSwapChain_Destroy(This->wineD3DSwapChain, D3D9CB_DestroyRenderTarget);
+            IWineD3DSwapChain_Destroy(This->wineD3DSwapChain);
             wined3d_mutex_unlock();
 
             HeapFree(GetProcessHeap(), 0, This);
diff --git a/dlls/d3d9/texture.c b/dlls/d3d9/texture.c
index 7db7037..ea1cde8 100644
--- a/dlls/d3d9/texture.c
+++ b/dlls/d3d9/texture.c
@@ -60,7 +60,7 @@ static ULONG WINAPI IDirect3DTexture9Impl_Release(LPDIRECT3DTEXTURE9 iface) {
 
     if (ref == 0) {
         wined3d_mutex_lock();
-        IWineD3DTexture_Destroy(This->wineD3DTexture, D3D9CB_DestroySurface);
+        IWineD3DTexture_Destroy(This->wineD3DTexture);
         wined3d_mutex_unlock();
 
         IDirect3DDevice9Ex_Release(This->parentDevice);
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 9f9a157..98c30b4 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -62,6 +62,13 @@ static const DDDEVICEIDENTIFIER2 deviceidentifier =
     0
 };
 
+static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
+
+static const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops =
+{
+    ddraw_null_wined3d_object_destroyed,
+};
+
 /*****************************************************************************
  * IUnknown Methods
  *****************************************************************************/
@@ -1655,11 +1662,9 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
     IDirectDrawSurfaceImpl *surfImpl = (IDirectDrawSurfaceImpl *)surf;
     IDirectDrawImpl *This = surfImpl->ddraw;
     IUnknown *Parent;
-    IParentImpl *parImpl = NULL;
     IWineD3DSurface *wineD3DSurface;
     IWineD3DSwapChain *swapchain;
     HRESULT hr;
-    void *tmp;
     IWineD3DClipper *clipper = NULL;
 
     WINED3DSURFACE_DESC     Desc;
@@ -1683,18 +1688,6 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
     swapchain = surfImpl->wineD3DSwapChain;
     surfImpl->wineD3DSwapChain = NULL;
     wineD3DSurface = surfImpl->WineD3DSurface;
-    IWineD3DSurface_GetParent(wineD3DSurface, &Parent);
-    IUnknown_Release(Parent); /* For the getParent */
-
-    /* Is the parent an IParent interface? */
-    if(IUnknown_QueryInterface(Parent, &IID_IParent, &tmp) == S_OK)
-    {
-        /* It is a IParent interface! */
-        IUnknown_Release(Parent); /* For the QueryInterface */
-        parImpl = (IParentImpl *)Parent;
-        /* Release the reference the parent interface is holding */
-        IWineD3DSurface_Release(wineD3DSurface);
-    }
 
     /* get the clipper */
     IWineD3DSurface_GetClipper(wineD3DSurface, &clipper);
@@ -1711,34 +1704,19 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
     Width = Desc.width;
     Height = Desc.height;
 
-    if(swapchain) {
-        /* If there's a swapchain, it owns the IParent interface. Create a new one for the
-         * new surface
-         */
-        parImpl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*parImpl));
-        parImpl->lpVtbl = &IParent_Vtbl;
-        parImpl->ref = 1;
-
-        Parent = (IUnknown *) parImpl;
-    }
+    IWineD3DSurface_GetParent(wineD3DSurface, &Parent);
 
     /* Create the new surface */
     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, Width, Height, Format,
-            TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface,
-            Usage, Pool, MultiSampleType, MultiSampleQuality, This->ImplType, Parent);
+            TRUE /* Lockable */, FALSE /* Discard */, surfImpl->mipmap_level, &surfImpl->WineD3DSurface, Usage, Pool,
+            MultiSampleType, MultiSampleQuality, This->ImplType, Parent, &ddraw_null_wined3d_parent_ops);
+    IUnknown_Release(Parent);
 
     if(hr != D3D_OK)
         return hr;
 
     IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper);
 
-    /* Update the IParent if it exists */
-    if(parImpl)
-    {
-        parImpl->child = (IUnknown *) surfImpl->WineD3DSurface;
-        /* Add a reference for the IParent */
-        IWineD3DSurface_AddRef(surfImpl->WineD3DSurface);
-    }
     /* TODO: Copy the surface content, except for render targets */
 
     /* If there's a swapchain, it owns the wined3d surfaces. So Destroy
@@ -1787,7 +1765,7 @@ IDirectDrawImpl_RecreateAllSurfaces(IDirectDrawImpl *This)
         /* Should happen almost never */
         FIXME("(%p) Switching to non-opengl surfaces with d3d started. Is this a bug?\n", This);
         /* Shutdown d3d */
-        IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroyDepthStencilSurface, D3D7CB_DestroySwapChain);
+        IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroySwapChain);
     }
     /* Contrary: D3D starting is handled by the caller, because it knows the render target */
 
@@ -1806,15 +1784,6 @@ ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain) {
     return IUnknown_Release(swapChainParent);
 }
 
-ULONG WINAPI D3D7CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface) {
-    IUnknown* surfaceParent;
-    TRACE("(%p) call back\n", pSurface);
-
-    IWineD3DSurface_GetParent(pSurface, &surfaceParent);
-    IUnknown_Release(surfaceParent);
-    return IUnknown_Release(surfaceParent);
-}
-
 /*****************************************************************************
  * IDirectDrawImpl_CreateNewSurface
  *
@@ -1841,8 +1810,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
     DWORD Usage = 0;
     WINED3DSURFTYPE ImplType = This->ImplType;
     WINED3DSURFACE_DESC Desc;
-    IUnknown *Parent;
-    IParentImpl *parImpl = NULL;
     WINED3DPOOL Pool = WINED3DPOOL_DEFAULT;
 
     if (TRACE_ON(ddraw))
@@ -1990,34 +1957,11 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
     /* A trace message for debugging */
     TRACE("(%p) Created IDirectDrawSurface implementation structure at %p\n", This, *ppSurf);
 
-    if(pDDSD->ddsCaps.dwCaps & ( DDSCAPS_PRIMARYSURFACE | DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE) )
-    {
-        /* Render targets and textures need a IParent interface,
-         * because WineD3D will destroy them when the swapchain
-         * is released
-         */
-        parImpl = HeapAlloc(GetProcessHeap(), 0, sizeof(IParentImpl));
-        if(!parImpl)
-        {
-            ERR("Out of memory when allocating memory for a IParent implementation\n");
-            return DDERR_OUTOFMEMORY;
-        }
-        parImpl->ref = 1;
-        parImpl->lpVtbl = &IParent_Vtbl;
-        Parent = (IUnknown *)parImpl;
-        TRACE("Using IParent interface %p as parent\n", parImpl);
-    }
-    else
-    {
-        /* Use the surface as parent */
-        Parent = (IUnknown *)*ppSurf;
-        TRACE("Using Surface interface %p as parent\n", *ppSurf);
-    }
-
     /* Now create the WineD3D Surface */
     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, pDDSD->dwWidth, pDDSD->dwHeight, Format,
             TRUE /* Lockable */, FALSE /* Discard */, level, &(*ppSurf)->WineD3DSurface,
-            Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType, Parent);
+            Usage, Pool, WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, ImplType,
+            (IUnknown *)*ppSurf, &ddraw_null_wined3d_parent_ops);
 
     if(hr != D3D_OK)
     {
@@ -2025,16 +1969,6 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This,
         return hr;
     }
 
-    /* Set the child of the parent implementation if it exists */
-    if(parImpl)
-    {
-        parImpl->child = (IUnknown *) (*ppSurf)->WineD3DSurface;
-        /* The IParent releases the WineD3DSurface, and
-         * the ddraw surface does that too. Hold a reference
-         */
-        IWineD3DSurface_AddRef((*ppSurf)->WineD3DSurface);
-    }
-
     /* Increase the surface counter, and attach the surface */
     InterlockedIncrement(&This->surfaces);
     list_add_head(&This->surface_list, &(*ppSurf)->surface_list_entry);
@@ -3032,9 +2966,7 @@ IDirectDrawImpl_AttachD3DDevice(IDirectDrawImpl *This,
     {
         ERR("Error allocating an array for the converted vertex decls\n");
         This->declArraySize = 0;
-        hr = IWineD3DDevice_Uninit3D(This->wineD3DDevice,
-                                     D3D7CB_DestroyDepthStencilSurface,
-                                     D3D7CB_DestroySwapChain);
+        hr = IWineD3DDevice_Uninit3D(This->wineD3DDevice, D3D7CB_DestroySwapChain);
         return E_OUTOFMEMORY;
     }
 
@@ -3436,6 +3368,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateSurface(IWineD3DDeviceParen
 
     /* Return the surface */
     *surface = surf->WineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
 
     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, surf);
 
@@ -3472,6 +3405,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateRenderTarget(IWineD3DDevice
     /* TODO: Return failure if the dimensions do not match, but this shouldn't happen */
 
     *surface = target->WineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
     target->isRenderTarget = TRUE;
 
     TRACE("Returning wineD3DSurface %p, it belongs to surface %p\n", *surface, d3d_surface);
@@ -3484,7 +3418,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
         DWORD multisample_quality, BOOL discard, IWineD3DSurface **surface)
 {
     struct IDirectDrawImpl *This = ddraw_from_device_parent(iface);
-    /* Create a Depth Stencil surface to make WineD3D happy */
+    IDirectDrawSurfaceImpl *ddraw_surface;
     DDSURFACEDESC2 ddsd;
     HRESULT hr;
 
@@ -3512,8 +3446,7 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
     }
 
     This->depthstencil = TRUE;
-    hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This,
-            &ddsd, (IDirectDrawSurface7 **)&This->DepthStencilBuffer, NULL);
+    hr = IDirectDraw7_CreateSurface((IDirectDraw7 *)This, &ddsd, (IDirectDrawSurface7 **)&ddraw_surface, NULL);
     This->depthstencil = FALSE;
     if(FAILED(hr))
     {
@@ -3521,7 +3454,9 @@ static HRESULT STDMETHODCALLTYPE device_parent_CreateDepthStencilSurface(IWineD3
         return hr;
     }
 
-    *surface = This->DepthStencilBuffer->WineD3DSurface;
+    *surface = ddraw_surface->WineD3DSurface;
+    IWineD3DSurface_AddRef(*surface);
+    IDirectDrawSurface7_Release((IDirectDrawSurface7 *)ddraw_surface);
 
     return D3D_OK;
 }
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 72dfff5..7c2883e 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -79,8 +79,6 @@ typedef struct IParentImpl                IParentImpl;
 /* Callbacks for implicit object destruction */
 extern ULONG WINAPI D3D7CB_DestroySwapChain(IWineD3DSwapChain *pSwapChain);
 
-extern ULONG WINAPI D3D7CB_DestroyDepthStencilSurface(IWineD3DSurface *pSurface);
-
 /* Global critical section */
 extern CRITICAL_SECTION ddraw_cs;
 
@@ -115,7 +113,6 @@ struct IDirectDrawImpl
     /* WineD3D linkage */
     IWineD3D                *wineD3D;
     IWineD3DDevice          *wineD3DDevice;
-    IDirectDrawSurfaceImpl  *DepthStencilBuffer;
     BOOL                    d3d_initialized;
 
     /* Misc ddraw fields */
diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c
index 6908a62..b7eed02 100644
--- a/dlls/ddraw/main.c
+++ b/dlls/ddraw/main.c
@@ -748,7 +748,6 @@ DestroyCallback(IDirectDrawSurface7 *surf,
                 void *context)
 {
     IDirectDrawSurfaceImpl *Impl = (IDirectDrawSurfaceImpl *)surf;
-    IDirectDrawImpl *ddraw = context;
     ULONG ref;
 
     ref = IDirectDrawSurface7_Release(surf);  /* For the EnumSurfaces */
@@ -760,9 +759,6 @@ DestroyCallback(IDirectDrawSurface7 *surf,
      */
     if( (!Impl->is_complex_root) || (Impl->first_attached != Impl) )
         return DDENUMRET_OK;
-    /* Skip our depth stencil surface, it will be released with the render target */
-    if( Impl == ddraw->DepthStencilBuffer)
-        return DDENUMRET_OK;
 
     /* Destroy the surface */
     while(ref) ref = IDirectDrawSurface7_Release(surf);
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index b59d01a..24246c7 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -159,6 +159,13 @@ IDirectDrawSurfaceImpl_AddRef(IDirectDrawSurface7 *iface)
     IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
     ULONG refCount = InterlockedIncrement(&This->ref);
 
+    if (refCount == 1 && This->WineD3DSurface)
+    {
+        EnterCriticalSection(&ddraw_cs);
+        IWineD3DSurface_AddRef(This->WineD3DSurface);
+        LeaveCriticalSection(&ddraw_cs);
+    }
+
     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
     return refCount;
 }
@@ -320,7 +327,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
                 HeapFree(GetProcessHeap(), 0, ddraw->decls);
                 ddraw->numConvertedDecls = 0;
 
-                if(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroyDepthStencilSurface, D3D7CB_DestroySwapChain) != D3D_OK)
+                if (FAILED(IWineD3DDevice_Uninit3D(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain)))
                 {
                     /* Not good */
                     ERR("(%p) Failed to uninit 3D\n", This);
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index 8b4fe75..a76cb12 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -56,18 +56,6 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_AddRef(IDXGISwapChain *iface)
     return refcount;
 }
 
-static ULONG STDMETHODCALLTYPE destroy_surface(IWineD3DSurface *surface)
-{
-    IDXGISurface *dxgi_surface;
-
-    TRACE("surface %p\n", surface);
-
-    IWineD3DSurface_GetParent(surface, (IUnknown **)&dxgi_surface);
-    IDXGISurface_Release(dxgi_surface);
-
-    return IDXGISurface_Release(dxgi_surface);
-}
-
 static ULONG STDMETHODCALLTYPE destroy_swapchain(IWineD3DSwapChain *swapchain)
 {
     TRACE("swapchain %p\n", swapchain);
@@ -96,7 +84,7 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_Release(IDXGISwapChain *iface)
         }
         else
         {
-            hr = IWineD3DDevice_Uninit3D(wined3d_device, destroy_surface, destroy_swapchain);
+            hr = IWineD3DDevice_Uninit3D(wined3d_device, destroy_swapchain);
             IWineD3DDevice_Release(wined3d_device);
             if (FAILED(hr))
             {
diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c
index 4b6900a..eb01e96 100644
--- a/dlls/wined3d/cubetexture.c
+++ b/dlls/wined3d/cubetexture.c
@@ -110,7 +110,7 @@ static void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3
     *dirty = FALSE;
 }
 
-static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This, D3DCB_DESTROYSURFACEFN surface_destroy_cb)
+static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This)
 {
     unsigned int i, j;
 
@@ -130,7 +130,7 @@ static void cubetexture_cleanup(IWineD3DCubeTextureImpl *This, D3DCB_DESTROYSURF
                 surface_set_texture_name(surface, 0, FALSE);
                 surface_set_texture_target(surface, 0);
                 IWineD3DSurface_SetContainer(surface, NULL);
-                surface_destroy_cb(surface);
+                IWineD3DSurface_Release(surface);
             }
         }
     }
@@ -237,7 +237,7 @@ HRESULT cubetexture_init(IWineD3DCubeTextureImpl *texture, UINT edge_length, UIN
             {
                 FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr);
                 texture->surfaces[j][i] = NULL;
-                cubetexture_cleanup(texture, D3DCB_DefaultDestroySurface);
+                cubetexture_cleanup(texture);
                 return hr;
             }
 
@@ -289,7 +289,7 @@ static ULONG WINAPI IWineD3DCubeTextureImpl_Release(IWineD3DCubeTexture *iface)
     TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
     ref = InterlockedDecrement(&This->resource.ref);
     if (ref == 0) {
-        IWineD3DCubeTexture_Destroy(iface, D3DCB_DefaultDestroySurface);
+        IWineD3DCubeTexture_Destroy(iface);
     }
     return ref;
 }
@@ -432,10 +432,11 @@ static BOOL WINAPI IWineD3DCubeTextureImpl_IsCondNP2(IWineD3DCubeTexture *iface)
 /* *******************************************
    IWineD3DCubeTexture IWineD3DCubeTexture parts follow
    ******************************************* */
-static void WINAPI IWineD3DCubeTextureImpl_Destroy(IWineD3DCubeTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) {
+static void WINAPI IWineD3DCubeTextureImpl_Destroy(IWineD3DCubeTexture *iface)
+{
     IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface;
 
-    cubetexture_cleanup(This, D3DCB_DestroySurface);
+    cubetexture_cleanup(This);
     /* finally delete the object */
     HeapFree(GetProcessHeap(), 0, This);
 }
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index aab45a0..a30a9b1 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -901,7 +901,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height,
         WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,
         DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality,
-        WINED3DSURFTYPE Impl, IUnknown *parent)
+        WINED3DSURFTYPE Impl, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     IWineD3DSurfaceImpl *object;
@@ -924,7 +924,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UI
     }
 
     hr = surface_init(object, Impl, This->surface_alignment, Width, Height, Level, Lockable,
-            Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent);
+            Discard, MultiSample, MultisampleQuality, This, Usage, Format, Pool, parent, parent_ops);
     if (FAILED(hr))
     {
         WARN("Failed to initialize surface, returning %#x.\n", hr);
@@ -1343,7 +1343,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
     HDC                     hDc;
     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
     HRESULT                 hr;
-    IUnknown               *bufferParent;
     BOOL                    displaymode_set = FALSE;
     WINED3DDISPLAYMODE      Mode;
     const struct GlPixelFormatDesc *format_desc;
@@ -1604,26 +1603,14 @@ error:
     if (object->backBuffer) {
         UINT i;
         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
-            if(object->backBuffer[i]) {
-                IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
-                IUnknown_Release(bufferParent); /* once for the get parent */
-                if (IUnknown_Release(bufferParent) > 0) {
-                    FIXME("(%p) Something's still holding the back buffer\n",This);
-                }
-            }
+            if (object->backBuffer[i]) IWineD3DSurface_Release(object->backBuffer[i]);
         }
         HeapFree(GetProcessHeap(), 0, object->backBuffer);
         object->backBuffer = NULL;
     }
     if(object->context && object->context[0])
         DestroyContext(This, object->context[0]);
-    if(object->frontBuffer) {
-        IWineD3DSurface_GetParent(object->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);
-        }
-    }
+    if (object->frontBuffer) IWineD3DSurface_Release(object->frontBuffer);
     HeapFree(GetProcessHeap(), 0, object);
     return hr;
 }
@@ -1983,7 +1970,8 @@ static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl *This, const char *fi
     }
 
     hr = IWineD3DDevice_CreateSurface((IWineD3DDevice *) This, bm.bmWidth, bm.bmHeight, WINED3DFMT_R5G6B5, TRUE,
-            FALSE, 0, &This->logo_surface, 0, WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL, NULL);
+            FALSE, 0, &This->logo_surface, 0, WINED3DPOOL_DEFAULT, WINED3DMULTISAMPLE_NONE, 0, SURFACE_OPENGL,
+            NULL, &wined3d_null_parent_ops);
     if(FAILED(hr)) {
         ERR("Wine logo requested, but failed to create surface\n");
         goto out;
@@ -2287,7 +2275,9 @@ static HRESULT WINAPI device_unload_resource(IWineD3DResource *resource, void *c
     return WINED3D_OK;
 }
 
-static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
+static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface,
+        D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain)
+{
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
     int sampler;
     UINT i;
@@ -2399,7 +2389,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D
     This->render_targets[0] = NULL;
 
     if (This->auto_depth_stencil_buffer) {
-        if(D3DCB_DestroyDepthStencilSurface(This->auto_depth_stencil_buffer) > 0) {
+        if (IWineD3DSurface_Release(This->auto_depth_stencil_buffer) > 0)
+        {
             FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This);
         }
         This->auto_depth_stencil_buffer = NULL;
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 1ac8b11..6b92c0c 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -6,6 +6,7 @@
  * Copyright 2004 Christian Costa
  * Copyright 2005 Oliver Stieber
  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
+ * Copyright 2009 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -4316,16 +4317,6 @@ static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent
     return WINED3D_OK;
 }
 
-ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
-    IUnknown* surfaceParent;
-    TRACE("(%p) call back\n", pSurface);
-
-    /* Now, release the parent, which will take care of cleaning up the surface for us */
-    IWineD3DSurface_GetParent(pSurface, &surfaceParent);
-    IUnknown_Release(surfaceParent);
-    return IUnknown_Release(surfaceParent);
-}
-
 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
     IUnknown* volumeParent;
     TRACE("(%p) call back\n", pVolume);
@@ -4830,3 +4821,10 @@ const IWineD3DVtbl IWineD3D_Vtbl =
     IWineD3DImpl_GetDeviceCaps,
     IWineD3DImpl_CreateDevice
 };
+
+static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
+
+const struct wined3d_parent_ops wined3d_null_parent_ops =
+{
+    wined3d_null_wined3d_object_destroyed,
+};
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index a8f6c4b..c3aff86 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -10,6 +10,7 @@
  * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
  * Copyright 2007-2008 Henri Verbeet
  * Copyright 2006-2008 Roderick Colenbrander
+ * Copyright 2009 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -122,7 +123,7 @@ UINT surface_calculate_size(const struct GlPixelFormatDesc *format_desc, UINT al
 HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment,
         UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type,
         UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
-        WINED3DPOOL pool, IUnknown *parent)
+        WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
 {
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format, &GLINFO_LOCATION);
@@ -166,6 +167,8 @@ HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type,
         return hr;
     }
 
+    surface->parent_ops = parent_ops;
+
     /* "Standalone" surface. */
     IWineD3DSurface_SetContainer((IWineD3DSurface *)surface, NULL);
 
@@ -727,6 +730,7 @@ static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface)
     if (!ref)
     {
         surface_cleanup(This);
+        This->parent_ops->wined3d_object_destroyed(This->resource.parent);
 
         TRACE("(%p) Released.\n", This);
         HeapFree(GetProcessHeap(), 0, This);
diff --git a/dlls/wined3d/surface_base.c b/dlls/wined3d/surface_base.c
index c45533b..51a80a5 100644
--- a/dlls/wined3d/surface_base.c
+++ b/dlls/wined3d/surface_base.c
@@ -10,6 +10,7 @@
  * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
  * Copyright 2007 Henri Verbeet
  * Copyright 2006-2007 Roderick Colenbrander
+ * Copyright 2009 Henri Verbeet for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -799,7 +800,8 @@ static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source,
     IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.wineD3DDevice, source->currentDesc.Width,
             source->currentDesc.Height, to_fmt, TRUE /* lockable */, TRUE /* discard  */, 0 /* level */, &ret,
             0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */,
-            0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source), NULL /* parent */);
+            0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source),
+            NULL /* parent */, &wined3d_null_parent_ops);
     if(!ret) {
         ERR("Failed to create a destination surface for conversion\n");
         return NULL;
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index d8d3733..38cdf46 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -36,7 +36,8 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
 #define GLINFO_LOCATION This->wineD3DDevice->adapter->gl_info
 
 /*IWineD3DSwapChain parts follow: */
-static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderTarget) {
+static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface)
+{
     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
     WINED3DDISPLAYMODE mode;
     unsigned int i;
@@ -50,9 +51,9 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
     if (This->frontBuffer)
     {
         IWineD3DSurface_SetContainer(This->frontBuffer, 0);
-        if (D3DCB_DestroyRenderTarget(This->frontBuffer))
+        if (IWineD3DSurface_Release(This->frontBuffer))
         {
-            FIXME("(%p) Something's still holding the front buffer (%p).\n",
+            WARN("(%p) Something's still holding the front buffer (%p).\n",
                     This, This->frontBuffer);
         }
         This->frontBuffer = NULL;
@@ -65,8 +66,8 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
         while (i--)
         {
             IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
-            if (D3DCB_DestroyRenderTarget(This->backBuffer[i]))
-                FIXME("(%p) Something's still holding back buffer %u (%p).\n",
+            if (IWineD3DSurface_Release(This->backBuffer[i]))
+                WARN("(%p) Something's still holding back buffer %u (%p).\n",
                         This, i, This->backBuffer[i]);
         }
         HeapFree(GetProcessHeap(), 0, This->backBuffer);
diff --git a/dlls/wined3d/swapchain_base.c b/dlls/wined3d/swapchain_base.c
index 7272c95..31b9d07 100644
--- a/dlls/wined3d/swapchain_base.c
+++ b/dlls/wined3d/swapchain_base.c
@@ -59,7 +59,7 @@ ULONG WINAPI IWineD3DBaseSwapChainImpl_Release(IWineD3DSwapChain *iface) {
     refCount = InterlockedDecrement(&This->ref);
     TRACE("(%p) : ReleaseRef to %d\n", This, refCount);
     if (refCount == 0) {
-        IWineD3DSwapChain_Destroy(iface, D3DCB_DefaultDestroySurface);
+        IWineD3DSwapChain_Destroy(iface);
     }
     return refCount;
 }
diff --git a/dlls/wined3d/swapchain_gdi.c b/dlls/wined3d/swapchain_gdi.c
index 5968201..f4909bc 100644
--- a/dlls/wined3d/swapchain_gdi.c
+++ b/dlls/wined3d/swapchain_gdi.c
@@ -27,7 +27,8 @@
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
 WINE_DECLARE_DEBUG_CHANNEL(fps);
 
-static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderback) {
+static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface)
+{
     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
     WINED3DDISPLAYMODE mode;
 
@@ -38,8 +39,9 @@ static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
     /* release the ref to the front and back buffer parents */
     if(This->frontBuffer) {
         IWineD3DSurface_SetContainer(This->frontBuffer, 0);
-        if(D3DCB_DestroyRenderback(This->frontBuffer) > 0) {
-            FIXME("(%p) Something's still holding the front buffer\n",This);
+        if (IWineD3DSurface_Release(This->frontBuffer) > 0)
+        {
+            WARN("(%p) Something's still holding the front buffer\n",This);
         }
     }
 
@@ -47,8 +49,9 @@ static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
         UINT i;
         for(i = 0; i < This->presentParms.BackBufferCount; i++) {
             IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
-            if(D3DCB_DestroyRenderback(This->backBuffer[i]) > 0) {
-                FIXME("(%p) Something's still holding the back buffer\n",This);
+            if (IWineD3DSurface_Release(This->backBuffer[i]) > 0)
+            {
+                WARN("(%p) Something's still holding the back buffer\n",This);
             }
         }
         HeapFree(GetProcessHeap(), 0, This->backBuffer);
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index dd8f32e..ddca452 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -100,7 +100,7 @@ static void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRG
     *dirty = FALSE;
 }
 
-static void texture_cleanup(IWineD3DTextureImpl *This, D3DCB_DESTROYSURFACEFN surface_destroy_cb)
+static void texture_cleanup(IWineD3DTextureImpl *This)
 {
     unsigned int i;
 
@@ -116,7 +116,7 @@ static void texture_cleanup(IWineD3DTextureImpl *This, D3DCB_DESTROYSURFACEFN su
             surface_set_texture_name(This->surfaces[i], 0, FALSE);
             surface_set_texture_target(This->surfaces[i], 0);
             IWineD3DSurface_SetContainer(This->surfaces[i], 0);
-            surface_destroy_cb(This->surfaces[i]);
+            IWineD3DSurface_Release(This->surfaces[i]);
         }
     }
 
@@ -266,7 +266,7 @@ HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT
         {
             FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
             texture->surfaces[i] = NULL;
-            texture_cleanup(texture, D3DCB_DefaultDestroySurface);
+            texture_cleanup(texture);
             return hr;
         }
 
@@ -319,7 +319,7 @@ static ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
     TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
     ref = InterlockedDecrement(&This->resource.ref);
     if (ref == 0) {
-        IWineD3DTexture_Destroy(iface, D3DCB_DefaultDestroySurface);
+        IWineD3DTexture_Destroy(iface);
     }
     return ref;
 }
@@ -480,10 +480,11 @@ static BOOL WINAPI IWineD3DTextureImpl_IsCondNP2(IWineD3DTexture *iface) {
 /* *******************************************
    IWineD3DTexture IWineD3DTexture parts follow
    ******************************************* */
-static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroySurface) {
+static void WINAPI IWineD3DTextureImpl_Destroy(IWineD3DTexture *iface)
+{
     IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
 
-    texture_cleanup(This, D3DCB_DestroySurface);
+    texture_cleanup(This);
     /* free the object */
     HeapFree(GetProcessHeap(), 0, This);
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index b65c0b5..cb6fa84 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1337,8 +1337,6 @@ HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain *
 #define WINE_D3D9_CAPABLE(gl_info) WINE_D3D8_CAPABLE(gl_info) && (gl_info->supported[ARB_FRAGMENT_PROGRAM] && gl_info->supported[ARB_VERTEX_SHADER])
 
 /* Default callbacks for implicit object destruction */
-extern ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) DECLSPEC_HIDDEN;
-
 extern ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pSurface) DECLSPEC_HIDDEN;
 
 /*****************************************************************************
@@ -1467,6 +1465,7 @@ struct ffp_frag_desc
 };
 
 extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions DECLSPEC_HIDDEN;
+extern const struct wined3d_parent_ops wined3d_null_parent_ops DECLSPEC_HIDDEN;
 
 void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_settings *settings,
         BOOL ignore_textype) DECLSPEC_HIDDEN;
@@ -1958,6 +1957,7 @@ struct IWineD3DSurfaceImpl
     IWineD3DResourceClass     resource;
 
     /* IWineD3DSurface fields */
+    const struct wined3d_parent_ops *parent_ops;
     IWineD3DBase              *container;
     WINED3DSURFACET_DESC      currentDesc;
     IWineD3DPaletteImpl       *palette; /* D3D7 style palette handling */
@@ -2023,7 +2023,7 @@ void surface_gdi_cleanup(IWineD3DSurfaceImpl *This) DECLSPEC_HIDDEN;
 HRESULT surface_init(IWineD3DSurfaceImpl *surface, WINED3DSURFTYPE surface_type, UINT alignment,
         UINT width, UINT height, UINT level, BOOL lockable, BOOL discard, WINED3DMULTISAMPLE_TYPE multisample_type,
         UINT multisample_quality, IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format,
-        WINED3DPOOL pool, IUnknown *parent) DECLSPEC_HIDDEN;
+        WINED3DPOOL pool, IUnknown *parent, const struct wined3d_parent_ops *parent_ops) DECLSPEC_HIDDEN;
 
 /* Predeclare the shared Surface functions */
 HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface,
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index 77e1fb2..46d2335 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -2143,6 +2143,11 @@ struct wined3d_shader_signature
     char *string_data;
 };
 
+struct wined3d_parent_ops
+{
+    void (*wined3d_object_destroyed)(void *parent);
+};
+
 interface IWineD3DResource;
 interface IWineD3DSurface;
 interface IWineD3DVolume;
@@ -2210,7 +2215,6 @@ interface IWineD3DDeviceParent : IUnknown
         [out] IWineD3DSwapChain **swapchain
     );
 }
-typedef ULONG (*D3DCB_DESTROYSURFACEFN)(IWineD3DSurface *pSurface);
 typedef ULONG (*D3DCB_DESTROYVOLUMEFN)(IWineD3DVolume *pVolume);
 typedef ULONG (*D3DCB_DESTROYSWAPCHAINFN)(IWineD3DSwapChain *pSwapChain);
 typedef HRESULT (*D3DCB_ENUMRESOURCES)(IWineD3DResource *resource, void *pData);
@@ -2619,7 +2623,6 @@ interface IWineD3DBaseTexture : IWineD3DResource
 interface IWineD3DTexture : IWineD3DBaseTexture
 {
     void Destroy(
-        [in] D3DCB_DESTROYSURFACEFN destroy_surface_callback
     );
     HRESULT GetLevelDesc(
         [in] UINT level,
@@ -2651,7 +2654,6 @@ interface IWineD3DTexture : IWineD3DBaseTexture
 interface IWineD3DCubeTexture : IWineD3DBaseTexture
 {
     void Destroy(
-        [in] D3DCB_DESTROYSURFACEFN destroy_surface_callback
     );
     HRESULT GetLevelDesc(
         [in] UINT level,
@@ -2773,7 +2775,6 @@ interface IWineD3DQuery : IWineD3DBase
 interface IWineD3DSwapChain : IWineD3DBase
 {
     void Destroy(
-        [in] D3DCB_DESTROYSURFACEFN destroy_surface_callback
     );
     HRESULT GetDevice(
         [out] IWineD3DDevice **device
@@ -2930,7 +2931,8 @@ interface IWineD3DDevice : IWineD3DBase
         [in] WINED3DMULTISAMPLE_TYPE multisample_type,
         [in] DWORD multisample_quality,
         [in] WINED3DSURFTYPE surface_type,
-        [in] IUnknown *parent
+        [in] IUnknown *parent,
+        [in] const struct wined3d_parent_ops *parent_ops
     );
     HRESULT CreateRendertargetView(
         [in] IWineD3DResource *resource,
@@ -3024,7 +3026,6 @@ interface IWineD3DDevice : IWineD3DBase
         [in] WINED3DPRESENT_PARAMETERS *present_parameters
     );
     HRESULT Uninit3D(
-        [in] D3DCB_DESTROYSURFACEFN destroy_surface_callback,
         [in] D3DCB_DESTROYSWAPCHAINFN destroy_swapchain_callback
     );
     HRESULT UninitGDI(
-- 
1.6.0.6




More information about the wine-patches mailing list