From: Henri Verbeet Subject: [PATCH 2/5] wined3d: Forward surface refcounts to the container. Message-Id: <1302885220-16558-2-git-send-email-hverbeet@codeweavers.com> Date: Fri, 15 Apr 2011 18:33:37 +0200 This will prevent textures from being released if one of its surfaces is still in use by the stateblock. We have similar constructions in d3d8 and d3d9, but those won't prevent the wined3d texture from being released. --- dlls/wined3d/surface.c | 37 ++++++++++++++++++++++++++++--------- dlls/wined3d/surface_base.c | 31 ++++++++++++++++++++++++++----- dlls/wined3d/surface_gdi.c | 39 ++++++++++++++++++++++++++++++--------- 3 files changed, 84 insertions(+), 23 deletions(-) diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 4a72183..c7a3571 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1376,20 +1376,39 @@ HRESULT surface_load(IWineD3DSurfaceImpl *surface, BOOL srgb) /* Do not call while under the GL lock. */ static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - ULONG ref = InterlockedDecrement(&This->resource.ref); - TRACE("(%p) : Releasing from %d\n", This, ref + 1); + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + ULONG refcount; + + TRACE("Surface %p, container %p of type %#x.\n", + surface, surface->container.u.base, surface->container.type); + + switch (surface->container.type) + { + case WINED3D_CONTAINER_TEXTURE: + return wined3d_texture_decref(surface->container.u.texture); + + case WINED3D_CONTAINER_SWAPCHAIN: + return wined3d_swapchain_decref(surface->container.u.swapchain); + + default: + ERR("Unhandled container type %#x.\n", surface->container.type); + case WINED3D_CONTAINER_NONE: + break; + } + + refcount = InterlockedDecrement(&surface->resource.ref); + TRACE("%p decreasing refcount to %u.\n", surface, refcount); - if (!ref) + if (!refcount) { - surface_cleanup(This); - This->resource.parent_ops->wined3d_object_destroyed(This->resource.parent); + surface_cleanup(surface); + surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent); - TRACE("(%p) Released.\n", This); - HeapFree(GetProcessHeap(), 0, This); + TRACE("Destroyed surface %p.\n", surface); + HeapFree(GetProcessHeap(), 0, surface); } - return ref; + return refcount; } /* **************************************************** diff --git a/dlls/wined3d/surface_base.c b/dlls/wined3d/surface_base.c index 906c7ef..0705719 100644 --- a/dlls/wined3d/surface_base.c +++ b/dlls/wined3d/surface_base.c @@ -102,11 +102,32 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, RE return E_NOINTERFACE; } -ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - ULONG ref = InterlockedIncrement(&This->resource.ref); - TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1); - return ref; +ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + ULONG refcount; + + TRACE("Surface %p, container %p of type %#x.\n", + surface, surface->container.u.base, surface->container.type); + + switch (surface->container.type) + { + case WINED3D_CONTAINER_TEXTURE: + return wined3d_texture_incref(surface->container.u.texture); + + case WINED3D_CONTAINER_SWAPCHAIN: + return wined3d_swapchain_incref(surface->container.u.swapchain); + + default: + ERR("Unhandled container type %#x.\n", surface->container.type); + case WINED3D_CONTAINER_NONE: + break; + } + + refcount = InterlockedIncrement(&surface->resource.ref); + TRACE("%p increasing refcount to %u.\n", surface, refcount); + + return refcount; } HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c index db9cf8b..0cb675b 100644 --- a/dlls/wined3d/surface_gdi.c +++ b/dlls/wined3d/surface_gdi.c @@ -114,20 +114,41 @@ static const struct wined3d_surface_ops gdi_surface_ops = * to destroy all the GL things. * *****************************************************************************/ -static ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) { - IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - ULONG ref = InterlockedDecrement(&This->resource.ref); - TRACE("(%p) : Releasing from %d\n", This, ref + 1); +static ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) +{ + IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)iface; + ULONG refcount; + + TRACE("Surface %p, container %p of type %#x.\n", + surface, surface->container.u.base, surface->container.type); + + switch (surface->container.type) + { + case WINED3D_CONTAINER_TEXTURE: + return wined3d_texture_decref(surface->container.u.texture); + + case WINED3D_CONTAINER_SWAPCHAIN: + return wined3d_swapchain_decref(surface->container.u.swapchain); + + default: + ERR("Unhandled container type %#x.\n", surface->container.type); + case WINED3D_CONTAINER_NONE: + break; + } + + refcount = InterlockedDecrement(&surface->resource.ref); + TRACE("%p decreasing refcount to %u.\n", surface, refcount); - if (!ref) + if (!refcount) { - surface_gdi_cleanup(This); + surface_gdi_cleanup(surface); + surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent); - TRACE("(%p) Released.\n", This); - HeapFree(GetProcessHeap(), 0, This); + TRACE("Destroyed surface %p.\n", surface); + HeapFree(GetProcessHeap(), 0, surface); } - return ref; + return refcount; } /***************************************************************************** -- 1.7.3.4