Henri Verbeet : ddraw: Destroy the ddraw surface after the wined3d surface is destroyed.

Alexandre Julliard julliard at winehq.org
Thu Apr 21 11:17:47 CDT 2011


Module: wine
Branch: master
Commit: 6ff226f502c8a0fd4e3d9307e3070b6a960f756e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6ff226f502c8a0fd4e3d9307e3070b6a960f756e

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Wed Apr 20 22:09:26 2011 +0200

ddraw: Destroy the ddraw surface after the wined3d surface is destroyed.

---

 dlls/ddraw/ddraw.c         |    2 +-
 dlls/ddraw/ddraw_private.h |    1 +
 dlls/ddraw/surface.c       |   95 +++++++++++++++++++++++---------------------
 3 files changed, 52 insertions(+), 46 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index c2ea683..564f2f3 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -2548,7 +2548,7 @@ HRESULT WINAPI ddraw_recreate_surfaces_cb(IDirectDrawSurface7 *surf, DDSURFACEDE
     hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice, wined3d_desc.width, wined3d_desc.height,
             wined3d_desc.format, TRUE, FALSE, surfImpl->mipmap_level, wined3d_desc.usage, wined3d_desc.pool,
             wined3d_desc.multisample_type, wined3d_desc.multisample_quality, This->ImplType,
-            parent, &ddraw_null_wined3d_parent_ops, &surfImpl->WineD3DSurface);
+            parent, &ddraw_surface_wined3d_parent_ops, &surfImpl->WineD3DSurface);
     if (FAILED(hr))
     {
         surfImpl->WineD3DSurface = wineD3DSurface;
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 988d127..e75e4bc 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -37,6 +37,7 @@
 #include "wine/list.h"
 #include "wine/wined3d.h"
 
+extern const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops DECLSPEC_HIDDEN;
 extern const struct wined3d_parent_ops ddraw_null_wined3d_parent_ops DECLSPEC_HIDDEN;
 
 /* Typdef the interfaces */
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 0105848..16b831a 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -246,50 +246,6 @@ void ddraw_surface_destroy(IDirectDrawSurfaceImpl *This)
 
     if (This->WineD3DSurface)
         IWineD3DSurface_Release(This->WineD3DSurface);
-
-    /* Check for attached surfaces and detach them */
-    if(This->first_attached != This)
-    {
-        /* Well, this shouldn't happen: The surface being attached is addref()ed
-          * in AddAttachedSurface, so it shouldn't be released until DeleteAttachedSurface
-          * is called, because the refcount is held. It looks like the app released()
-          * it often enough to force this
-          */
-        IDirectDrawSurface7 *root = (IDirectDrawSurface7 *)This->first_attached;
-        IDirectDrawSurface7 *detach = (IDirectDrawSurface7 *)This;
-
-        FIXME("(%p) Freeing a surface that is attached to surface %p\n", This, This->first_attached);
-
-        /* The refcount will drop to -1 here */
-        if(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach) != DD_OK)
-        {
-            ERR("(%p) DeleteAttachedSurface failed!\n", This);
-        }
-    }
-
-    while(This->next_attached != NULL)
-    {
-        IDirectDrawSurface7 *root = (IDirectDrawSurface7 *)This;
-        IDirectDrawSurface7 *detach = (IDirectDrawSurface7 *)This->next_attached;
-
-        if(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach) != DD_OK)
-        {
-            ERR("(%p) DeleteAttachedSurface failed!\n", This);
-            assert(0);
-        }
-    }
-
-    /* Having a texture handle set implies that the device still exists */
-    if(This->Handle)
-    {
-        ddraw_free_handle(&This->ddraw->d3ddevice->handle_table, This->Handle - 1, DDRAW_HANDLE_SURFACE);
-    }
-
-    /* Reduce the ddraw surface count */
-    InterlockedDecrement(&This->ddraw->surfaces);
-    list_remove(&This->surface_list_entry);
-
-    HeapFree(GetProcessHeap(), 0, This);
 }
 
 static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
@@ -3486,6 +3442,55 @@ static const struct IDirect3DTextureVtbl d3d_texture1_vtbl =
     d3d_texture1_Unload,
 };
 
+static void STDMETHODCALLTYPE ddraw_surface_wined3d_object_destroyed(void *parent)
+{
+    IDirectDrawSurfaceImpl *surface = parent;
+
+    TRACE("surface %p.\n", surface);
+
+    /* Check for attached surfaces and detach them. */
+    if (surface->first_attached != surface)
+    {
+        IDirectDrawSurface7 *root = (IDirectDrawSurface7 *)surface->first_attached;
+        IDirectDrawSurface7 *detach = (IDirectDrawSurface7 *)surface;
+
+        /* Well, this shouldn't happen: The surface being attached is
+         * referenced in AddAttachedSurface(), so it shouldn't be released
+         * until DeleteAttachedSurface() is called, because the refcount is
+         * held. It looks like the application released it often enough to
+         * force this. */
+        WARN("Surface is still attached to surface %p.\n", surface->first_attached);
+
+        /* The refcount will drop to -1 here */
+        if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach)))
+            ERR("DeleteAttachedSurface failed.\n");
+    }
+
+    while (surface->next_attached)
+    {
+        IDirectDrawSurface7 *root = (IDirectDrawSurface7 *)surface;
+        IDirectDrawSurface7 *detach = (IDirectDrawSurface7 *)surface->next_attached;
+
+        if (FAILED(IDirectDrawSurface7_DeleteAttachedSurface(root, 0, detach)))
+            ERR("DeleteAttachedSurface failed.\n");
+    }
+
+    /* Having a texture handle set implies that the device still exists. */
+    if (surface->Handle)
+        ddraw_free_handle(&surface->ddraw->d3ddevice->handle_table, surface->Handle - 1, DDRAW_HANDLE_SURFACE);
+
+    /* Reduce the ddraw surface count. */
+    InterlockedDecrement(&surface->ddraw->surfaces);
+    list_remove(&surface->surface_list_entry);
+
+    HeapFree(GetProcessHeap(), 0, surface);
+}
+
+const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
+{
+    ddraw_surface_wined3d_object_destroyed,
+};
+
 HRESULT ddraw_surface_create_texture(IDirectDrawSurfaceImpl *surface)
 {
     const DDSURFACEDESC2 *desc = &surface->surface_desc;
@@ -3599,7 +3604,7 @@ HRESULT ddraw_surface_init(IDirectDrawSurfaceImpl *surface, IDirectDrawImpl *ddr
     hr = IWineD3DDevice_CreateSurface(ddraw->wineD3DDevice, desc->dwWidth, desc->dwHeight, format,
             TRUE /* Lockable */, FALSE /* Discard */, mip_level, usage, pool,
             WINED3DMULTISAMPLE_NONE, 0 /* MultiSampleQuality */, surface_type, surface,
-            &ddraw_null_wined3d_parent_ops, &surface->WineD3DSurface);
+            &ddraw_surface_wined3d_parent_ops, &surface->WineD3DSurface);
     if (FAILED(hr))
     {
         WARN("Failed to create wined3d surface, hr %#x.\n", hr);




More information about the wine-cvs mailing list