Module: wine Branch: master Commit: 6ff226f502c8a0fd4e3d9307e3070b6a960f756e URL: http://source.winehq.org/git/wine.git/?a=commit;h=6ff226f502c8a0fd4e3d9307e3...
Author: Henri Verbeet hverbeet@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);