[Mesa-dev] [PATCH] gallium: Deallocate screens and buffers on exit.

Ricardo Barreira rsf at google.com
Wed Dec 13 12:18:47 UTC 2017


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



More information about the mesa-dev mailing list