st/mesa: add destroy_drawable interface
authorCharmaine Lee <charmainel@vmware.com>
Thu, 20 Jul 2017 18:04:14 +0000 (11:04 -0700)
committerCharmaine Lee <charmainel@vmware.com>
Fri, 21 Jul 2017 00:34:34 +0000 (17:34 -0700)
With this patch, the st manager will maintain a hash table for
the active framebuffer interface objects. A destroy_drawable interface
is added to allow the state tracker to notify the st manager to remove
the associated framebuffer interface object from the hash table,
so the associated framebuffer and its resources can be deleted
at framebuffers purge time.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101829
Fixes: 147d7fb772a ("st/mesa: add a winsys buffers list in st_context")
Tested-by: Brad King <brad.king@kitware.com>
Tested-by: Gert Wollny <gw.fossdev@gmail.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/gallium/include/state_tracker/st_api.h
src/gallium/state_trackers/dri/dri_drawable.c
src/gallium/state_trackers/glx/xlib/xm_api.c
src/gallium/state_trackers/glx/xlib/xm_st.c
src/gallium/state_trackers/wgl/stw_st.c
src/mesa/state_tracker/st_manager.c
src/mesa/state_tracker/st_manager.h

index 30a4866a7af60e4cb066acba7f5eb57043ad445b..9b660f74c938e9d28ebbc752db8335b8e3f6231c 100644 (file)
@@ -552,6 +552,13 @@ struct st_api
     * Get the currently bound context in the calling thread.
     */
    struct st_context_iface *(*get_current)(struct st_api *stapi);
+
+   /**
+    * Notify the st manager the framebuffer interface object
+    * is no longer valid.
+    */
+   void (*destroy_drawable)(struct st_api *stapi,
+                            struct st_framebuffer_iface *stfbi);
 };
 
 /**
index 0cfdc305583957ad52351f0efc6af55f29964e2a..c7df0f6332709085d1b97129fc9783737d8f5b72 100644 (file)
@@ -169,6 +169,8 @@ void
 dri_destroy_buffer(__DRIdrawable * dPriv)
 {
    struct dri_drawable *drawable = dri_drawable(dPriv);
+   struct dri_screen *screen = drawable->screen;
+   struct st_api *stapi = screen->st_api;
    int i;
 
    pipe_surface_reference(&drawable->drisw_surface, NULL);
@@ -180,7 +182,9 @@ dri_destroy_buffer(__DRIdrawable * dPriv)
 
    swap_fences_unref(drawable);
 
-   drawable->base.ID = 0;
+   /* Notify the st manager that this drawable is no longer valid */
+   stapi->destroy_drawable(stapi, &drawable->base);
+
    FREE(drawable);
 }
 
index 881dd44323245d95a4f634410154e7d8c3344c58..e4b1e9dd4de3503dac34e4bc0d2796e9d8546c76 100644 (file)
@@ -595,6 +595,11 @@ xmesa_free_buffer(XMesaBuffer buffer)
           */
          b->ws.drawable = 0;
 
+         /* Notify the st manager that the associated framebuffer interface
+          * object is no longer valid.
+          */
+         stapi->destroy_drawable(stapi, buffer->stfb);
+
          /* XXX we should move the buffer to a delete-pending list and destroy
           * the buffer until it is no longer current.
           */
index 9e30efad60dc7125fa789bcd5b9224fbbf5ad4ff..6a0f4aad7d82111c2d620c312bed9253f9984ce8 100644 (file)
@@ -273,6 +273,7 @@ xmesa_st_framebuffer_flush_front(struct st_context_iface *stctx,
    return ret;
 }
 
+static uint32_t xmesa_stfbi_ID = 0;
 
 struct st_framebuffer_iface *
 xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b)
@@ -302,6 +303,7 @@ xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b)
    stfbi->visual = &xstfb->stvis;
    stfbi->flush_front = xmesa_st_framebuffer_flush_front;
    stfbi->validate = xmesa_st_framebuffer_validate;
+   stfbi->ID = p_atomic_inc_return(&xmesa_stfbi_ID);
    p_atomic_set(&stfbi->stamp, 1);
    stfbi->st_manager_private = (void *) xstfb;
 
index c2844b04c4ee59fdd69327b8ebb1a52d7cc97613..85a8b1743eaa603336f8227e8c76eb390593e3a5 100644 (file)
@@ -256,7 +256,11 @@ stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb)
    for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
       pipe_resource_reference(&stwfb->textures[i], NULL);
 
-   stwfb->base.ID = 0;
+   /* Notify the st manager that the framebuffer interface is no
+    * longer valid.
+    */
+   stw_dev->stapi->destroy_drawable(stw_dev->stapi, &stwfb->base);
+
    FREE(stwfb);
 }
 
index cb816de80259c8c7209619d8f036198a616e6c69..ebc7ca8b13354584b1aaf0998d49ffb0469688ce 100644 (file)
@@ -38,6 +38,7 @@
 #include "main/fbobject.h"
 #include "main/renderbuffer.h"
 #include "main/version.h"
+#include "util/hash_table.h"
 #include "st_texture.h"
 
 #include "st_context.h"
 #include "util/u_surface.h"
 #include "util/list.h"
 
+struct hash_table;
+static struct hash_table *st_fbi_ht; /* framebuffer iface objects hash table */
+
+static mtx_t st_mutex = _MTX_INITIALIZER_NP;
 
 /**
  * Map an attachment to a buffer index.
@@ -490,6 +495,76 @@ st_framebuffer_reference(struct st_framebuffer **ptr,
    _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb);
 }
 
+
+static uint32_t
+st_framebuffer_iface_hash(const void *key)
+{
+   return (uintptr_t)key;
+}
+
+
+static bool
+st_framebuffer_iface_equal(const void *a, const void *b)
+{
+   return (struct st_framebuffer_iface *)a == (struct st_framebuffer_iface *)b;
+}
+
+
+static boolean
+st_framebuffer_iface_lookup(const struct st_framebuffer_iface *stfbi)
+{
+   struct hash_entry *entry;
+
+   mtx_lock(&st_mutex);
+   entry = _mesa_hash_table_search(st_fbi_ht, stfbi);
+   mtx_unlock(&st_mutex);
+
+   return entry != NULL;
+}
+
+
+static boolean
+st_framebuffer_iface_insert(struct st_framebuffer_iface *stfbi)
+{
+   struct hash_entry *entry;
+
+   mtx_lock(&st_mutex);
+   entry = _mesa_hash_table_insert(st_fbi_ht, stfbi, stfbi);
+   mtx_unlock(&st_mutex);
+
+   return entry != NULL;
+}
+
+
+static void
+st_framebuffer_iface_remove(struct st_framebuffer_iface *stfbi)
+{
+   struct hash_entry *entry;
+
+   mtx_lock(&st_mutex);
+   entry = _mesa_hash_table_search(st_fbi_ht, stfbi);
+   if (!entry)
+      goto unlock;
+
+   _mesa_hash_table_remove(st_fbi_ht, entry);
+
+unlock:
+   mtx_unlock(&st_mutex);
+}
+
+
+/**
+ * The framebuffer interface object is no longer valid.
+ * Remove the object from the framebuffer interface hash table.
+ */
+static void
+st_api_destroy_drawable(struct st_api *stapi,
+                        struct st_framebuffer_iface *stfbi)
+{
+   st_framebuffer_iface_remove(stfbi);
+}
+
+
 /**
  * Purge the winsys buffers list to remove any references to
  * non-existing framebuffer interface objects.
@@ -506,7 +581,7 @@ st_framebuffers_purge(struct st_context *st)
        * and unreference the framebuffer object, so its resources can be
        * deleted.
        */
-      if (stfb->iface->ID != stfb->iface_ID) {
+      if (!st_framebuffer_iface_lookup(stfb->iface)) {
          LIST_DEL(&stfb->head);
          st_framebuffer_reference(&stfb, NULL);
       }
@@ -810,6 +885,14 @@ st_framebuffer_reuse_or_create(struct st_context *st,
       cur = st_framebuffer_create(st, stfbi);
 
       if (cur) {
+         /* add the referenced framebuffer interface object to
+          * the framebuffer interface object hash table.
+          */
+         if (!st_framebuffer_iface_insert(stfbi)) {
+            st_framebuffer_reference(&cur, NULL);
+            return NULL;
+         }
+
          /* add to the context's winsys buffers list */
          LIST_ADD(&cur->head, &st->winsys_buffers);
 
@@ -881,6 +964,8 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
 static void
 st_api_destroy(struct st_api *stapi)
 {
+   _mesa_hash_table_destroy(st_fbi_ht, NULL);
+   mtx_destroy(&st_mutex);
 }
 
 /**
@@ -1015,10 +1100,18 @@ static const struct st_api st_gl_api = {
    .create_context = st_api_create_context,
    .make_current = st_api_make_current,
    .get_current = st_api_get_current,
+   .destroy_drawable = st_api_destroy_drawable,
 };
 
 struct st_api *
 st_gl_api_create(void)
 {
+   /* Create a hash table for all the framebuffer interface objects */
+
+   mtx_init(&st_mutex, mtx_plain);
+   st_fbi_ht = _mesa_hash_table_create(NULL,
+                                       st_framebuffer_iface_hash,
+                                       st_framebuffer_iface_equal);
+
    return (struct st_api *) &st_gl_api;
 }
index 68adf2fa1a49d3354dd49ca0af0fc858e1c956cb..c54f29e29411d23f9b02a09486d8cbc1ed51ea16 100644 (file)
@@ -34,6 +34,7 @@
 
 struct st_context;
 struct st_framebuffer;
+struct st_framebuffer_interface;
 
 void
 st_manager_flush_frontbuffer(struct st_context *st);
@@ -48,4 +49,8 @@ st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *
 void
 st_framebuffer_reference(struct st_framebuffer **ptr,
                          struct st_framebuffer *stfb);
+
+void
+st_framebuffer_interface_destroy(struct st_framebuffer_interface *stfbi);
+
 #endif /* ST_MANAGER_H */