Henri Verbeet : wined3d: Reattach FBO attachments when any of the corresponding surfaces is unloaded .

Alexandre Julliard julliard at winehq.org
Mon Aug 16 12:24:59 CDT 2010


Module: wine
Branch: master
Commit: 5f2fcfdd6b3b7ab9c15d2c450a87527d13d144c8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5f2fcfdd6b3b7ab9c15d2c450a87527d13d144c8

Author: Henri Verbeet <hverbeet at codeweavers.com>
Date:   Sun Aug 15 23:21:42 2010 +0200

wined3d: Reattach FBO attachments when any of the corresponding surfaces is unloaded.

---

 dlls/wined3d/basetexture.c     |    2 +
 dlls/wined3d/buffer.c          |    2 +
 dlls/wined3d/context.c         |   92 ++++++++++++++++++++++++++--------------
 dlls/wined3d/device.c          |    2 +-
 dlls/wined3d/resource.c        |    6 +++
 dlls/wined3d/surface.c         |    2 +
 dlls/wined3d/volume.c          |   13 ++++--
 dlls/wined3d/wined3d_private.h |    5 ++-
 8 files changed, 85 insertions(+), 39 deletions(-)

diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c
index deab4fb..922550d 100644
--- a/dlls/wined3d/basetexture.c
+++ b/dlls/wined3d/basetexture.c
@@ -129,6 +129,8 @@ void basetexture_unload(IWineD3DBaseTexture *iface)
 
     This->baseTexture.texture_rgb.dirty = TRUE;
     This->baseTexture.texture_srgb.dirty = TRUE;
+
+    resource_unload((IWineD3DResourceImpl *)This);
 }
 
 DWORD basetexture_set_lod(IWineD3DBaseTexture *iface, DWORD LODNew)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 7c898cd..31a1492 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -720,6 +720,8 @@ static void STDMETHODCALLTYPE buffer_UnLoad(IWineD3DBuffer *iface)
         This->conversion_stride = 0;
         This->flags &= ~WINED3D_BUFFER_HASDESC;
     }
+
+    resource_unload((IWineD3DResourceImpl *)This);
 }
 
 static ULONG STDMETHODCALLTYPE buffer_Release(IWineD3DBuffer *iface)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 7e3e813..e22149c 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -650,50 +650,78 @@ void context_free_event_query(struct wined3d_event_query *query)
     context->free_event_queries[context->free_event_query_count++] = query->object;
 }
 
-void context_resource_released(IWineD3DDevice *iface, IWineD3DResource *resource, WINED3DRESOURCETYPE type)
+typedef void (context_fbo_entry_func_t)(struct wined3d_context *context, struct fbo_entry *entry);
+
+static void context_enum_surface_fbo_entries(IWineD3DDeviceImpl *device,
+        IWineD3DSurfaceImpl *surface, context_fbo_entry_func_t *callback)
 {
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     UINT i;
 
-    if (!This->d3d_initialized) return;
-
-    switch(type)
+    for (i = 0; i < device->numContexts; ++i)
     {
-        case WINED3DRTYPE_SURFACE:
+        struct wined3d_context *context = device->contexts[i];
+        const struct wined3d_gl_info *gl_info = context->gl_info;
+        struct fbo_entry *entry, *entry2;
+
+        if (context->current_rt == surface) context->current_rt = NULL;
+
+        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry)
         {
-            for (i = 0; i < This->numContexts; ++i)
-            {
-                struct wined3d_context *context = This->contexts[i];
-                const struct wined3d_gl_info *gl_info = context->gl_info;
-                struct fbo_entry *entry, *entry2;
+            UINT j;
 
-                if (context->current_rt == (IWineD3DSurfaceImpl *)resource) context->current_rt = NULL;
+            if (entry->depth_stencil == surface)
+            {
+                callback(context, entry);
+                continue;
+            }
 
-                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_list, struct fbo_entry, entry)
+            for (j = 0; j < gl_info->limits.buffers; ++j)
+            {
+                if (entry->render_targets[j] == surface)
                 {
-                    UINT j;
-
-                    if (entry->depth_stencil == (IWineD3DSurfaceImpl *)resource)
-                    {
-                        list_remove(&entry->entry);
-                        list_add_head(&context->fbo_destroy_list, &entry->entry);
-                        continue;
-                    }
-
-                    for (j = 0; j < gl_info->limits.buffers; ++j)
-                    {
-                        if (entry->render_targets[j] == (IWineD3DSurfaceImpl *)resource)
-                        {
-                            list_remove(&entry->entry);
-                            list_add_head(&context->fbo_destroy_list, &entry->entry);
-                            break;
-                        }
-                    }
+                    callback(context, entry);
+                    break;
                 }
             }
+        }
+    }
+}
 
+static void context_queue_fbo_entry_destruction(struct wined3d_context *context, struct fbo_entry *entry)
+{
+    list_remove(&entry->entry);
+    list_add_head(&context->fbo_destroy_list, &entry->entry);
+}
+
+void context_resource_released(IWineD3DDeviceImpl *device, IWineD3DResource *resource, WINED3DRESOURCETYPE type)
+{
+    if (!device->d3d_initialized) return;
+
+    switch (type)
+    {
+        case WINED3DRTYPE_SURFACE:
+            context_enum_surface_fbo_entries(device, (IWineD3DSurfaceImpl *)resource,
+                    context_queue_fbo_entry_destruction);
+            break;
+
+        default:
+            break;
+    }
+}
+
+static void context_detach_fbo_entry(struct wined3d_context *context, struct fbo_entry *entry)
+{
+    entry->attached = FALSE;
+}
+
+void context_resource_unloaded(IWineD3DDeviceImpl *device, IWineD3DResource *resource, WINED3DRESOURCETYPE type)
+{
+    switch (type)
+    {
+        case WINED3DRTYPE_SURFACE:
+            context_enum_surface_fbo_entries(device, (IWineD3DSurfaceImpl *)resource,
+                    context_detach_fbo_entry);
             break;
-        }
 
         default:
             break;
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index f4bce23..4b62170 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -6546,7 +6546,7 @@ void device_resource_released(IWineD3DDeviceImpl *This, IWineD3DResource *resour
 
     TRACE("(%p) : resource %p\n", This, resource);
 
-    context_resource_released((IWineD3DDevice *)This, resource, type);
+    context_resource_released(This, resource, type);
 
     switch (type) {
         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c
index 67622a3..11db1f8 100644
--- a/dlls/wined3d/resource.c
+++ b/dlls/wined3d/resource.c
@@ -105,6 +105,12 @@ void resource_cleanup(IWineD3DResource *iface)
     if (This->resource.device) device_resource_released(This->resource.device, iface);
 }
 
+void resource_unload(IWineD3DResourceImpl *resource)
+{
+    context_resource_unloaded(resource->resource.device, (IWineD3DResource *)resource,
+            resource->resource.resourceType);
+}
+
 static PrivateData* resource_find_private_data(IWineD3DResourceImpl *This, REFGUID tag)
 {
     PrivateData *data;
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 101c8c2..514c7b2 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -1230,6 +1230,8 @@ static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) {
     }
 
     context_release(context);
+
+    resource_unload((IWineD3DResourceImpl *)This);
 }
 
 /* ******************************************************
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 42e61e6..c22c263 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -166,11 +166,14 @@ static void WINAPI IWineD3DVolumeImpl_PreLoad(IWineD3DVolume *iface) {
     FIXME("iface %p stub!\n", iface);
 }
 
-static void WINAPI IWineD3DVolumeImpl_UnLoad(IWineD3DVolume *iface) {
-    /* The whole content is shadowed on This->resource.allocatedMemory, and the
-     * texture name is managed by the VolumeTexture container
-     */
-    TRACE("(%p): Nothing to do\n", iface);
+static void WINAPI IWineD3DVolumeImpl_UnLoad(IWineD3DVolume *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    /* The whole content is shadowed on This->resource.allocatedMemory, and
+     * the texture name is managed by the VolumeTexture container. */
+
+    resource_unload((IWineD3DResourceImpl *)iface);
 }
 
 static WINED3DRESOURCETYPE WINAPI IWineD3DVolumeImpl_GetType(IWineD3DVolume *iface) {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 08104eb..cc54228 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1177,7 +1177,9 @@ void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPE
 struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN;
 DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN;
 void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN;
-void context_resource_released(IWineD3DDevice *iface,
+void context_resource_released(IWineD3DDeviceImpl *device,
+        IWineD3DResource *resource, WINED3DRESOURCETYPE type) DECLSPEC_HIDDEN;
+void context_resource_unloaded(IWineD3DDeviceImpl *device,
         IWineD3DResource *resource, WINED3DRESOURCETYPE type) DECLSPEC_HIDDEN;
 BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN;
 void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN;
@@ -1776,6 +1778,7 @@ WINED3DRESOURCETYPE resource_get_type(IWineD3DResource *iface) DECLSPEC_HIDDEN;
 DWORD resource_set_priority(IWineD3DResource *iface, DWORD new_priority) DECLSPEC_HIDDEN;
 HRESULT resource_set_private_data(IWineD3DResource *iface, REFGUID guid,
         const void *data, DWORD data_size, DWORD flags) DECLSPEC_HIDDEN;
+void resource_unload(IWineD3DResourceImpl *resource) DECLSPEC_HIDDEN;
 
 /* Tests show that the start address of resources is 32 byte aligned */
 #define RESOURCE_ALIGNMENT 16




More information about the wine-cvs mailing list