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