This allows dclose()'ing this code in dynamically-linked library without leaking memory. --- src/gallium/state_trackers/osmesa/osmesa.c | 77 +++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 22 deletions(-)
diff --git a/src/gallium/state_trackers/osmesa/osmesa.c b/src/gallium/state_trackers/osmesa/osmesa.c index 8baec0a0e4..7336dbd0c5 100644 --- a/src/gallium/state_trackers/osmesa/osmesa.c +++ b/src/gallium/state_trackers/osmesa/osmesa.c @@ -113,6 +113,11 @@ struct osmesa_context struct pp_queue_t *pp; }; +/** + * Singleton st_manager object (see get_st_manager / destroy_st_manager + * functions). + */ +static struct st_manager *stmgr = NULL; /** * Linked list of all osmesa_buffers. @@ -123,7 +128,11 @@ struct osmesa_context * a frame. */ static struct osmesa_buffer *BufferList = NULL; - +/* + * Indicates whether the cleanup function for BufferList has already been + * registered with atexit(). + */ +static boolean destroy_buffers_registered = FALSE; /** * Called from the ST manager. @@ -149,6 +158,19 @@ get_st_api(void) return stapi; } +/** + * Destroy singleton st_manager object. + */ +static void +destroy_st_manager(void) +{ + if (stmgr) { + if (stmgr->screen) { + stmgr->screen->destroy(stmgr->screen); + } + FREE(stmgr); + } +} /** * Create/return a singleton st_manager object. @@ -156,8 +178,10 @@ get_st_api(void) static struct st_manager * get_st_manager(void) { - static struct st_manager *stmgr = NULL; if (!stmgr) { + if (atexit(destroy_st_manager) != 0) { + return NULL; + } stmgr = CALLOC_STRUCT(st_manager); if (stmgr) { stmgr->screen = osmesa_create_screen(); @@ -457,6 +481,24 @@ osmesa_create_st_framebuffer(void) return stfbi; } +static void +osmesa_destroy_buffer(struct osmesa_buffer *osbuffer) +{ + FREE(osbuffer->stfb); + FREE(osbuffer); +} + +static void +destroy_buffers(void) +{ + struct osmesa_buffer *buffer; + struct osmesa_buffer *next_buffer; + + for (buffer = BufferList; buffer; buffer = next_buffer) { + next_buffer = buffer->next; + osmesa_destroy_buffer(buffer); + } +} /** * Create new buffer and add to linked list. @@ -466,7 +508,17 @@ osmesa_create_buffer(enum pipe_format color_format, enum pipe_format ds_format, enum pipe_format accum_format) { - struct osmesa_buffer *osbuffer = CALLOC_STRUCT(osmesa_buffer); + struct osmesa_buffer *osbuffer; + + if (!destroy_buffers_registered) { + if (atexit(destroy_buffers) != 0) { + return NULL; + } + + destroy_buffers_registered = TRUE; + } + + osbuffer = CALLOC_STRUCT(osmesa_buffer); if (osbuffer) { osbuffer->stfb = osmesa_create_st_framebuffer(); @@ -510,22 +562,6 @@ osmesa_find_buffer(enum pipe_format color_format, } -static void -osmesa_destroy_buffer(struct osmesa_buffer *osbuffer) -{ - struct st_api *stapi = get_st_api(); - - /* - * Notify the state manager that the associated framebuffer interface - * is no longer valid. - */ - stapi->destroy_drawable(stapi, osbuffer->stfb); - - FREE(osbuffer->stfb); - FREE(osbuffer); -} - - /**********************************************************************/ /***** Public Functions *****/ @@ -790,9 +826,6 @@ OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type, osbuffer->height = height; osbuffer->map = buffer; - /* XXX unused for now */ - (void) osmesa_destroy_buffer; - osmesa->current_buffer = osbuffer; osmesa->type = type; -- 2.15.1.504.g5279b80103-goog _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev