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

This commit is contained in:
Henri Verbeet 2011-10-17 21:06:22 +02:00 committed by Alexandre Julliard
parent 68e1484bec
commit 14ca56ed97
3 changed files with 56 additions and 41 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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)