Henri Verbeet : ddraw: Destroy the swapchain in ddraw_destroy() if it still exists.

Alexandre Julliard julliard at winehq.org
Tue Oct 18 12:56:26 CDT 2011


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

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Mon Oct 17 21:06:22 2011 +0200

ddraw: Destroy the swapchain in ddraw_destroy() if it still exists.

---

 dlls/ddraw/ddraw.c         |   55 +++++++++++++++++++++++++++++++++++++++++++-
 dlls/ddraw/ddraw_private.h |    1 +
 dlls/ddraw/surface.c       |   41 +--------------------------------
 3 files changed, 56 insertions(+), 41 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 17f1900..0801976 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -410,6 +410,50 @@ static ULONG WINAPI d3d1_AddRef(IDirect3D *iface)
     return ddraw1_AddRef(&This->IDirectDraw_iface);
 }
 
+void ddraw_destroy_swapchain(IDirectDrawImpl *ddraw)
+{
+    TRACE("Destroying the swapchain.\n");
+
+    wined3d_swapchain_decref(ddraw->wined3d_swapchain);
+    ddraw->wined3d_swapchain = NULL;
+
+    if (DefaultSurfaceType == SURFACE_OPENGL)
+    {
+        UINT i;
+
+        for (i = 0; i < ddraw->numConvertedDecls; ++i)
+        {
+            wined3d_vertex_declaration_decref(ddraw->decls[i].decl);
+        }
+        HeapFree(GetProcessHeap(), 0, ddraw->decls);
+        ddraw->numConvertedDecls = 0;
+
+        if (FAILED(wined3d_device_uninit_3d(ddraw->wined3d_device)))
+        {
+            ERR("Failed to uninit 3D.\n");
+        }
+        else
+        {
+            /* Free the d3d window if one was created. */
+            if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window)
+            {
+                TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
+                DestroyWindow(ddraw->d3d_window);
+                ddraw->d3d_window = 0;
+            }
+        }
+
+        ddraw->d3d_initialized = FALSE;
+        ddraw->d3d_target = NULL;
+    }
+    else
+    {
+        wined3d_device_uninit_gdi(ddraw->wined3d_device);
+    }
+
+    TRACE("Swapchain destroyed.\n");
+}
+
 /*****************************************************************************
  * ddraw_destroy
  *
@@ -437,7 +481,16 @@ static void ddraw_destroy(IDirectDrawImpl *This)
     list_remove(&This->ddraw_list_entry);
     LeaveCriticalSection(&ddraw_cs);
 
-    /* Release the attached WineD3D stuff */
+    /* This can happen more or less legitimately for ddraw 1 and 2, where
+     * surfaces don't keep a reference to the ddraw object. The surfaces
+     * will of course be broken after this, (and on native trying to do
+     * anything with them in that state results in an access violation), but
+     * the release of the ddraw object should succeed without crashing. */
+    if (This->wined3d_swapchain)
+    {
+        WARN("DirectDraw object is being destroyed while the swapchain still exists.\n");
+        ddraw_destroy_swapchain(This);
+    }
     wined3d_device_decref(This->wined3d_device);
     wined3d_decref(This->wineD3D);
 
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 7b0d608..2f8b609 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -127,6 +127,7 @@ struct IDirectDrawImpl
 #define DDRAW_WINDOW_CLASS_NAME "ddraw_wc"
 
 HRESULT ddraw_init(IDirectDrawImpl *ddraw, WINED3DDEVTYPE device_type) DECLSPEC_HIDDEN;
+void ddraw_destroy_swapchain(IDirectDrawImpl *ddraw) DECLSPEC_HIDDEN;
 
 /* Utility functions */
 void DDRAW_Convert_DDSCAPS_1_To_2(const DDSCAPS *pIn, DDSCAPS2 *pOut) DECLSPEC_HIDDEN;
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 976f557..561bca7 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -430,46 +430,7 @@ static void ddraw_surface_cleanup(IDirectDrawSurfaceImpl *surface)
     ddraw_surface_destroy(surface);
 
     if (ddraw->wined3d_swapchain && destroy_swapchain)
-    {
-        TRACE("Destroying the swapchain.\n");
-
-        wined3d_swapchain_decref(ddraw->wined3d_swapchain);
-        ddraw->wined3d_swapchain = NULL;
-
-        if (DefaultSurfaceType == SURFACE_OPENGL)
-        {
-            for (i = 0; i < ddraw->numConvertedDecls; ++i)
-            {
-                wined3d_vertex_declaration_decref(ddraw->decls[i].decl);
-            }
-            HeapFree(GetProcessHeap(), 0, ddraw->decls);
-            ddraw->numConvertedDecls = 0;
-
-            if (FAILED(wined3d_device_uninit_3d(ddraw->wined3d_device)))
-            {
-                ERR("Failed to uninit 3D.\n");
-            }
-            else
-            {
-                /* Free the d3d window if one was created. */
-                if (ddraw->d3d_window && ddraw->d3d_window != ddraw->dest_window)
-                {
-                    TRACE("Destroying the hidden render window %p.\n", ddraw->d3d_window);
-                    DestroyWindow(ddraw->d3d_window);
-                    ddraw->d3d_window = 0;
-                }
-            }
-
-            ddraw->d3d_initialized = FALSE;
-            ddraw->d3d_target = NULL;
-        }
-        else
-        {
-            wined3d_device_uninit_gdi(ddraw->wined3d_device);
-        }
-
-        TRACE("Swapchain destroyed.\n");
-    }
+        ddraw_destroy_swapchain(ddraw);
 
     /* Reduce the ddraw refcount */
     if (ifaceToRelease)




More information about the wine-cvs mailing list