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

This commit is contained in:
Henri Verbeet 2011-04-20 22:09:26 +02:00 committed by Alexandre Julliard
parent cbf78c5d49
commit 6ff226f502
3 changed files with 52 additions and 46 deletions

View File

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

View File

@ -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 */

View File

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