diff options
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r-- | src/mesa/state_tracker/st_manager.c | 95 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_manager.h | 5 |
2 files changed, 99 insertions, 1 deletions
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index cb816de8025..ebc7ca8b133 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -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" @@ -59,6 +60,10 @@ #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; } diff --git a/src/mesa/state_tracker/st_manager.h b/src/mesa/state_tracker/st_manager.h index 68adf2fa1a4..c54f29e2941 100644 --- a/src/mesa/state_tracker/st_manager.h +++ b/src/mesa/state_tracker/st_manager.h @@ -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 */ |