st/osmesa: re-use buffers in OSMesaMakeCurrent()
authorBrian Paul <brianp@vmware.com>
Tue, 9 Apr 2013 14:47:00 +0000 (08:47 -0600)
committerBrian Paul <brianp@vmware.com>
Wed, 10 Apr 2013 00:30:23 +0000 (18:30 -0600)
Rather than creating a new buffer each time.  Fixes problems found
with vtk.

Tested-by: Kevin H. Hobbs <hobbsk@ohio.edu>
src/gallium/state_trackers/osmesa/osmesa.c

index fdd0eda1996c75d2749410e86fa76deaf4b1f6cf..533fb53e4c71c4e0afeee3d7954786aa44aa5044 100644 (file)
@@ -80,6 +80,8 @@ struct osmesa_buffer
    struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
 
    void *map;
+
+   struct osmesa_buffer *next;  /**< next in linked list */
 };
 
 
@@ -99,6 +101,16 @@ struct osmesa_context
 };
 
 
+/**
+ * Linked list of all osmesa_buffers.
+ * We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to
+ * the next unless the color/depth/stencil/accum formats change.
+ * We have to do this to be compatible with the original OSMesa implementation
+ * because some apps call OSMesaMakeCurrent() several times during rendering
+ * a frame.
+ */
+static struct osmesa_buffer *BufferList = NULL;
+
 
 /**
  * Called from the ST manager.
@@ -400,6 +412,9 @@ osmesa_create_st_framebuffer(void)
 }
 
 
+/**
+ * Create new buffer and add to linked list.
+ */
 static struct osmesa_buffer *
 osmesa_create_buffer(enum pipe_format color_format,
                      enum pipe_format ds_format,
@@ -414,11 +429,38 @@ osmesa_create_buffer(enum pipe_format color_format,
 
       osmesa_init_st_visual(&osbuffer->visual, color_format,
                             ds_format, accum_format);
+
+      /* insert into linked list */
+      osbuffer->next = BufferList;
+      BufferList = osbuffer;
    }
+
    return osbuffer;
 }
 
 
+/**
+ * Search linked list for a buffer with matching pixel formats.
+ */
+static struct osmesa_buffer *
+osmesa_find_buffer(enum pipe_format color_format,
+                   enum pipe_format ds_format,
+                   enum pipe_format accum_format)
+{
+   struct osmesa_buffer *b;
+
+   /* Check if we already have a suitable buffer for the given formats */
+   for (b = BufferList; b; b = b->next) {
+      if (b->visual.color_format == color_format &&
+          b->visual.depth_stencil_format == ds_format &&
+          b->visual.accum_format == accum_format) {
+         return b;
+      }
+   }
+   return NULL;
+}
+
+
 static void
 osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
 {
@@ -581,18 +623,23 @@ OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
       return GL_FALSE;
    }
 
-   osbuffer = osmesa_create_buffer(color_format,
-                                   osmesa->depth_stencil_format,
-                                   osmesa->accum_format);
+   /* See if we already have a buffer that uses these pixel formats */
+   osbuffer = osmesa_find_buffer(color_format,
+                                 osmesa->depth_stencil_format,
+                                 osmesa->accum_format);
+   if (!osbuffer) {
+      /* Existing buffer found, create new buffer */
+      osbuffer = osmesa_create_buffer(color_format,
+                                      osmesa->depth_stencil_format,
+                                      osmesa->accum_format);
+   }
 
    osbuffer->width = width;
    osbuffer->height = height;
    osbuffer->map = buffer;
 
-   if (osmesa->current_buffer) {
-      /* free old buffer */
-      osmesa_destroy_buffer(osmesa->current_buffer);
-   }
+   /* XXX unused for now */
+   (void) osmesa_destroy_buffer;
 
    osmesa->current_buffer = osbuffer;
    osmesa->type = type;