[cogl] cogl-journal: Use a pool of vertex arrays



commit efadc439a46206252c279a1cef72cdaab673107c
Author: Neil Roberts <neil linux intel com>
Date:   Wed Jun 1 14:30:45 2011 +0100

    cogl-journal: Use a pool of vertex arrays
    
    Previously whenever the journal is flushed a new vertex array would be
    created to contain the vertices. To avoid the overhead of reallocating
    a buffer every time, this patch makes it use a pool of 8 buffers which
    are cycled in turn. The buffers are never destroyed but instead the
    data is replaced. The journal should only ever be using one buffer at
    a time but we cache more than one buffer anyway in case the GL driver
    is internally using the buffer in which case mapping the buffer may
    cause it to create a new buffer anyway.

 cogl/cogl-journal-private.h |   12 +++++++++
 cogl/cogl-journal.c         |   58 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 63 insertions(+), 7 deletions(-)
---
diff --git a/cogl/cogl-journal-private.h b/cogl/cogl-journal-private.h
index 7212dca..6eb7a2d 100644
--- a/cogl/cogl-journal-private.h
+++ b/cogl/cogl-journal-private.h
@@ -28,6 +28,8 @@
 #include "cogl-handle.h"
 #include "cogl-clip-stack.h"
 
+#define COGL_JOURNAL_VBO_POOL_SIZE 8
+
 typedef struct _CoglJournal
 {
   CoglObject _parent;
@@ -36,6 +38,16 @@ typedef struct _CoglJournal
   GArray *vertices;
   size_t needed_vbo_len;
 
+  /* A pool of attribute buffers is used so that we can avoid repeatedly
+     reallocating buffers. Only one of these buffers at a time will be
+     used by Cogl but we keep more than one alive anyway in case the
+     GL driver is internally using the buffer and it would have to
+     allocate a new one when we start writing to it */
+  CoglAttributeBuffer *vbo_pool[COGL_JOURNAL_VBO_POOL_SIZE];
+  /* The next vbo to use from the pool. We just cycle through them in
+     order */
+  unsigned int next_vbo_in_pool;
+
   int fast_read_pixel_count;
 
 } CoglJournal;
diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
index a2180be..cb378bb 100644
--- a/cogl/cogl-journal.c
+++ b/cogl/cogl-journal.c
@@ -125,10 +125,17 @@ COGL_OBJECT_DEFINE (Journal, journal);
 static void
 _cogl_journal_free (CoglJournal *journal)
 {
+  int i;
+
   if (journal->entries)
     g_array_free (journal->entries, TRUE);
   if (journal->vertices)
     g_array_free (journal->vertices, TRUE);
+
+  for (i = 0; i < COGL_JOURNAL_VBO_POOL_SIZE; i++)
+    if (journal->vbo_pool[i])
+      cogl_object_unref (journal->vbo_pool[i]);
+
   g_slice_free (CoglJournal, journal);
 }
 
@@ -1095,8 +1102,44 @@ compare_entry_clip_stacks (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
   return entry0->clip_stack == entry1->clip_stack;
 }
 
+/* Gets a new vertex array from the pool. A reference is taken on the
+   array so it can be treated as if it was just newly allocated */
+static CoglAttributeBuffer *
+create_attribute_buffer (CoglJournal *journal,
+                         gsize n_bytes)
+{
+  CoglAttributeBuffer *vbo;
+
+  /* If CoglBuffers are being emulated with malloc then there's not
+     really any point in using the pool so we'll just allocate the
+     buffer directly */
+  if (!cogl_features_available (COGL_FEATURE_VBOS))
+    return cogl_attribute_buffer_new (n_bytes, NULL);
+
+  vbo = journal->vbo_pool[journal->next_vbo_in_pool];
+
+  if (vbo == NULL)
+    {
+      vbo = cogl_attribute_buffer_new (n_bytes, NULL);
+      journal->vbo_pool[journal->next_vbo_in_pool] = vbo;
+    }
+  else if (cogl_buffer_get_size (COGL_BUFFER (vbo)) < n_bytes)
+    {
+      /* If the buffer is too small then we'll just recreate it */
+      cogl_object_unref (vbo);
+      vbo = cogl_attribute_buffer_new (n_bytes, NULL);
+      journal->vbo_pool[journal->next_vbo_in_pool] = vbo;
+    }
+
+  journal->next_vbo_in_pool = ((journal->next_vbo_in_pool + 1) %
+                               COGL_JOURNAL_VBO_POOL_SIZE);
+
+  return cogl_object_ref (vbo);
+}
+
 static CoglAttributeBuffer *
-upload_vertices (const CoglJournalEntry *entries,
+upload_vertices (CoglJournal            *journal,
+                 const CoglJournalEntry *entries,
                  int                     n_entries,
                  size_t                  needed_vbo_len,
                  GArray                 *vertices)
@@ -1110,7 +1153,7 @@ upload_vertices (const CoglJournalEntry *entries,
 
   g_assert (needed_vbo_len);
 
-  attribute_buffer = cogl_attribute_buffer_new (needed_vbo_len * 4, NULL);
+  attribute_buffer = create_attribute_buffer (journal, needed_vbo_len * 4);
   buffer = COGL_BUFFER (attribute_buffer);
   cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_STATIC);
 
@@ -1343,11 +1386,12 @@ _cogl_journal_flush (CoglJournal *journal,
 
   /* We upload the vertices after the clip stack pass in case it
      modifies the entries */
-  state.attribute_buffer = upload_vertices (&g_array_index (journal->entries,
-                                                        CoglJournalEntry, 0),
-                                        journal->entries->len,
-                                        journal->needed_vbo_len,
-                                        journal->vertices);
+  state.attribute_buffer =
+    upload_vertices (journal,
+                     &g_array_index (journal->entries, CoglJournalEntry, 0),
+                     journal->entries->len,
+                     journal->needed_vbo_len,
+                     journal->vertices);
   state.array_offset = 0;
 
   /* batch_and_call() batches a list of journal entries according to some



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]