[PATCH 7/9] glamor: Extract the streamed vertex data code used by Render.

Eric Anholt eric at anholt.net
Sat Mar 8 20:07:08 PST 2014


We should be uploading any vertex data using this kind of upload
style, since it saves a bunch of extra copies of our vertex data.

v2:
  - Add a simple comment about what the function does.
  - Use get_vbo_space()'s return in trapezoids, instead of dereffing
    glamor_priv->vb (by Markus Wick).
  - Fix the double-unmapping by moving put_vbo_space() outside of
    flush_composite_rects().
  - Remove the rest of the composite_vbo_offset usage, and just always
    use get_vbo_space()'s return value.
v3:
  - Fix failure to put_vbo_space in traps when no prims were
    generated.
  - Unbind the VBO from put_vbo_space().  Keeps callers from
    forgetting to do so.
v4:
  - Split out some changes into the previous 3 commits while trying to
    track down a regression.
  - Fix regression due to rebase fail where glamor_priv->vbo_offset
    wasn't incremented.
v5:
  - Fix GLES2 VBO sizing.
  - Add a comment about resize behavior.
  - Move glamor_vbo.c init code to glamor_vbo.c from
    glamor_render.c. (Derived from Markus's changes, but the GLES2 fix
    dropped almost all of the code in the functions).

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 glamor/Makefile.am        |   1 +
 glamor/glamor.c           |   2 +
 glamor/glamor.h           |   1 +
 glamor/glamor_priv.h      |  18 ++++++
 glamor/glamor_render.c    |  66 +++-------------------
 glamor/glamor_trapezoid.c |  72 +++++-------------------
 glamor/glamor_vbo.c       | 138 ++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 184 insertions(+), 114 deletions(-)
 create mode 100644 glamor/glamor_vbo.c

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 77492bc..ffc8c23 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -34,6 +34,7 @@ libglamor_la_SOURCES = \
 	glamor_pixmap.c\
 	glamor_largepixmap.c\
 	glamor_picture.c\
+	glamor_vbo.c \
 	glamor_window.c\
 	glamor_fbo.c\
 	glamor_compositerects.c\
diff --git a/glamor/glamor.c b/glamor/glamor.c
index fe9f761..dc69c72 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -439,6 +439,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     ps->DestroyPicture = glamor_destroy_picture;
     glamor_init_composite_shaders(screen);
 #endif
+    glamor_init_vbo(screen);
     glamor_init_pixmap_fbo(screen);
     glamor_init_solid_shader(screen);
     glamor_init_tile_shader(screen);
@@ -478,6 +479,7 @@ glamor_release_screen_priv(ScreenPtr screen)
 #ifdef RENDER
     glamor_fini_composite_shaders(screen);
 #endif
+    glamor_fini_vbo(screen);
     glamor_fini_pixmap_fbo(screen);
     glamor_fini_solid_shader(screen);
     glamor_fini_tile_shader(screen);
diff --git a/glamor/glamor.h b/glamor/glamor.h
index e12f497..e25dc73 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -324,6 +324,7 @@ extern _X_EXPORT int glamor_create_gc(GCPtr gc);
 
 extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes,
                                          DrawablePtr drawable);
+
 /* Glamor rendering/drawing functions with XXX_nf.
  * nf means no fallback within glamor internal if possible. If glamor
  * fail to accelerate the operation, glamor will return a false, and the
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index b23c12b..986e729 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -220,8 +220,15 @@ typedef struct glamor_screen_private {
 
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
+    /** Next offset within the VBO that glamor_get_vbo_space() will use. */
     int vbo_offset;
     int vbo_size;
+    /**
+     * Pointer to glamor_get_vbo_space()'s current VBO mapping.
+     *
+     * Note that this is not necessarily equal to the pointer returned
+     * by glamor_get_vbo_space(), so it can't be used in place of that.
+     */
     char *vb;
     int vb_stride;
     Bool has_source_coords, has_mask_coords;
@@ -744,6 +751,17 @@ void glamor_triangles(CARD8 op,
 void glamor_pixmap_init(ScreenPtr screen);
 void glamor_pixmap_fini(ScreenPtr screen);
 
+/* glamor_vbo.c */
+
+void glamor_init_vbo(ScreenPtr screen);
+void glamor_fini_vbo(ScreenPtr screen);
+
+void *
+glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset);
+
+void
+glamor_put_vbo_space(ScreenPtr screen);
+
 /** 
  * Download a pixmap's texture to cpu memory. If success,
  * One copy of current pixmap's texture will be put into
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 69a22d9..7829977 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -403,12 +403,10 @@ glamor_init_composite_shaders(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
     unsigned short *eb;
-    float *vb = NULL;
     int eb_size;
 
     glamor_priv = glamor_get_screen_private(screen);
     glamor_get_context(glamor_priv);
-    glGenBuffers(1, &glamor_priv->vbo);
     glGenBuffers(1, &glamor_priv->ebo);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
@@ -419,9 +417,6 @@ glamor_init_composite_shaders(ScreenPtr screen)
         eb = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
     }
     else {
-        vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2);
-        if (vb == NULL)
-            FatalError("Failed to allocate vb memory.\n");
         eb = malloc(eb_size);
     }
 
@@ -438,14 +433,7 @@ glamor_init_composite_shaders(ScreenPtr screen)
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        glBufferData(GL_ARRAY_BUFFER,
-                     GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) *
-                     2, NULL, GL_DYNAMIC_DRAW);
-        glBindBuffer(GL_ARRAY_BUFFER, 0);
-
         free(eb);
-        glamor_priv->vb = (char *) vb;
     }
 
     glamor_put_context(glamor_priv);
@@ -460,7 +448,6 @@ glamor_fini_composite_shaders(ScreenPtr screen)
 
     glamor_priv = glamor_get_screen_private(screen);
     glamor_get_context(glamor_priv);
-    glDeleteBuffers(1, &glamor_priv->vbo);
     glDeleteBuffers(1, &glamor_priv->ebo);
 
     for (i = 0; i < SHADER_SOURCE_COUNT; i++)
@@ -470,8 +457,6 @@ glamor_fini_composite_shaders(ScreenPtr screen)
                 if (shader->prog)
                     glDeleteProgram(shader->prog);
             }
-    if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && glamor_priv->vb)
-        free(glamor_priv->vb);
 
     glamor_put_context(glamor_priv);
 }
@@ -706,6 +691,8 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     int vert_size;
+    char *vbo_offset;
+    float *vb;
 
     glamor_priv->render_nr_verts = 0;
     glamor_priv->vb_stride = 2 * sizeof(float);
@@ -717,56 +704,32 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
     vert_size = n_verts * glamor_priv->vb_stride;
 
     glamor_get_context(glamor_priv);
-    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) {
-            glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT *
-                glamor_priv->vb_stride;
-            glamor_priv->vbo_offset = 0;
-            glBufferData(GL_ARRAY_BUFFER,
-                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
-        }
-
-        glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER,
-                                           glamor_priv->vbo_offset,
-                                           vert_size,
-                                           GL_MAP_WRITE_BIT |
-                                           GL_MAP_UNSYNCHRONIZED_BIT |
-                                           GL_MAP_INVALIDATE_RANGE_BIT);
-        assert(glamor_priv->vb != NULL);
-        glamor_priv->vb -= glamor_priv->vbo_offset;
-    }
-    else
-        glamor_priv->vbo_offset = 0;
+    vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
-                          glamor_priv->vb_stride,
-                          (void *) ((long)
-                                    glamor_priv->vbo_offset));
+                          glamor_priv->vb_stride, vbo_offset);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     if (glamor_priv->has_source_coords) {
         glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
                               GL_FLOAT, GL_FALSE,
                               glamor_priv->vb_stride,
-                              (void *) ((long) glamor_priv->vbo_offset +
-                                        2 * sizeof(float)));
+                              vbo_offset + 2 * sizeof(float));
         glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     }
 
     if (glamor_priv->has_mask_coords) {
         glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE,
                               glamor_priv->vb_stride,
-                              (void *) ((long) glamor_priv->vbo_offset +
-                                        (glamor_priv->has_source_coords ?
-                                         4 : 2) * sizeof(float)));
+                              vbo_offset + (glamor_priv->has_source_coords ?
+                                            4 : 2) * sizeof(float));
         glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
     }
     glamor_put_context(glamor_priv);
 
-    return glamor_priv->vb + glamor_priv->vbo_offset;
+    return vb;
 }
 
 static void
@@ -775,14 +738,6 @@ glamor_flush_composite_rects(ScreenPtr screen)
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     glamor_get_context(glamor_priv);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        glUnmapBuffer(GL_ARRAY_BUFFER);
-    else {
-
-        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
-                     glamor_priv->vb, GL_DYNAMIC_DRAW);
-    }
 
     if (!glamor_priv->render_nr_verts)
         return;
@@ -1334,8 +1289,6 @@ glamor_composite_with_shader(CARD8 op,
                  x_dest, y_dest, x_source, y_source, x_mask, y_mask, width,
                  height);
 
-            assert(glamor_priv->vbo_offset <
-                   glamor_priv->vbo_size - glamor_priv->vb_stride);
             glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale,
                                              dst_yscale, x_dest, y_dest,
                                              x_dest + width, y_dest + height,
@@ -1366,12 +1319,12 @@ glamor_composite_with_shader(CARD8 op,
                 vertices += 2;
             }
             glamor_priv->render_nr_verts += 4;
-            glamor_priv->vbo_offset += glamor_priv->vb_stride * 4;
             rects++;
 
             /* We've incremented by one of our 4 verts, now do the other 3. */
             vertices += 3 * vb_stride;
         }
+        glamor_put_vbo_space(screen);
         glamor_flush_composite_rects(screen);
         nrect -= rect_processed;
         if (two_pass_ca) {
@@ -1384,7 +1337,6 @@ glamor_composite_with_shader(CARD8 op,
         }
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 4d2360d..115ad33 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -213,7 +213,6 @@ glamor_emit_composite_vert(ScreenPtr screen,
     }
 
     glamor_priv->render_nr_verts++;
-    glamor_priv->vbo_offset += glamor_priv->vb_stride;
 }
 
 static void
@@ -237,14 +236,7 @@ glamor_flush_composite_triangles(ScreenPtr screen)
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     glamor_get_context(glamor_priv);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        glUnmapBuffer(GL_ARRAY_BUFFER);
-    else {
-
-        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
-                     glamor_priv->vb, GL_DYNAMIC_DRAW);
-    }
+    glamor_put_vbo_space(screen);
 
     if (!glamor_priv->render_nr_verts)
         return;
@@ -613,6 +605,8 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     int stride;
     int vert_size;
+    char *vbo_offset;
+    void *vb;
 
     glamor_priv->render_nr_verts = 0;
 
@@ -641,68 +635,43 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
     glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
     glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
-    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) {
-            glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT *
-                glamor_priv->vb_stride;
-            glamor_priv->vbo_offset = 0;
-            glBufferData(GL_ARRAY_BUFFER,
-                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
-        }
-
-        glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER,
-                                                     glamor_priv->vbo_offset,
-                                                     vert_size,
-                                                     GL_MAP_WRITE_BIT |
-                                                     GL_MAP_UNSYNCHRONIZED_BIT);
-
-        assert(glamor_priv->vb != NULL);
-        glamor_priv->vb -= glamor_priv->vbo_offset;
-    }
-    else {
-        glamor_priv->vbo_offset = 0;
-    }
+    vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
     /* Set the vertex pointer. */
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, glamor_priv->vb_stride,
-                          (void *) ((long) glamor_priv->vbo_offset));
+                          vbo_offset);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
     stride = 2;
 
     glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
                           GL_FALSE, glamor_priv->vb_stride,
-                          (void *) ((long) glamor_priv->vbo_offset +
-                                    stride * sizeof(float)));
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     stride += 2;
 
     glVertexAttribPointer(GLAMOR_VERTEX_TOP_BOTTOM, 2, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset +
-                                              stride * sizeof(float)));
+                          GL_FALSE, glamor_priv->vb_stride,
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
     stride += 2;
 
     glVertexAttribPointer(GLAMOR_VERTEX_LEFT_PARAM, 4, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset +
-                                              stride * sizeof(float)));
+                          GL_FALSE, glamor_priv->vb_stride,
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
     stride += 4;
 
     glVertexAttribPointer(GLAMOR_VERTEX_RIGHT_PARAM, 4, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset +
-                                              stride * sizeof(float)));
+                          GL_FALSE, glamor_priv->vb_stride,
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
     glamor_put_context(glamor_priv);
 
-    return glamor_priv->vb + glamor_priv->vbo_offset;
+    return vb;
 }
 
 static Bool
@@ -1008,7 +977,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     ret = TRUE;
 
  TRAPEZOID_RESET_GL:
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
@@ -1450,7 +1418,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
 
     pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale));
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     /* Now draw the Trapezoid mask. */
@@ -1575,25 +1542,17 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
                    ((float) ptrap->right.p1.y) / 65536, right_slope);
 
             glamor_priv->render_nr_verts += 4;
-            glamor_priv->vbo_offset += glamor_priv->vb_stride * 4;
-
             vertices += 3 * stride;
         }
 
         i += mrect;
 
+        glamor_put_vbo_space(screen);
+
         /* Now rendering. */
         if (!glamor_priv->render_nr_verts)
             continue;
 
-        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-            glUnmapBuffer(GL_ARRAY_BUFFER);
-        else {
-            glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-            glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
-                         glamor_priv->vb, GL_DYNAMIC_DRAW);
-        }
-
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
             glDrawRangeElements(GL_TRIANGLES, 0,
                                 glamor_priv->render_nr_verts,
@@ -1606,7 +1565,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
         }
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glBlendFunc(GL_ONE, GL_ZERO);
     glDisable(GL_BLEND);
diff --git a/glamor/glamor_vbo.c b/glamor/glamor_vbo.c
new file mode 100644
index 0000000..be2c2af
--- /dev/null
+++ b/glamor/glamor_vbo.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/**
+ * @file glamor_vbo.c
+ *
+ * Helpers for managing streamed vertex bufffers used in glamor.
+ */
+
+#include "glamor_priv.h"
+
+/** Default size of the VBO, in bytes.
+ *
+ * If a single request is larger than this size, we'll resize the VBO
+ * and return an appropriate mapping, but we'll resize back down after
+ * that to avoid hogging that memory forever.  We don't anticipate
+ * normal usage actually requiring larger VBO sizes.
+ */
+#define GLAMOR_VBO_SIZE (64 * 1024)
+
+/**
+ * Returns a pointer to @size bytes of VBO storage, which should be
+ * accessed by the GL using vbo_offset within the VBO.
+ */
+void *
+glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    void *data;
+
+    glamor_get_context(glamor_priv);
+
+    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) {
+            glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
+            glamor_priv->vbo_offset = 0;
+            glBufferData(GL_ARRAY_BUFFER,
+                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
+        }
+
+        data = glMapBufferRange(GL_ARRAY_BUFFER,
+                                glamor_priv->vbo_offset,
+                                size,
+                                GL_MAP_WRITE_BIT |
+                                GL_MAP_UNSYNCHRONIZED_BIT |
+                                GL_MAP_INVALIDATE_RANGE_BIT);
+        assert(data != NULL);
+        *vbo_offset = (void *)(uintptr_t)glamor_priv->vbo_offset;
+        glamor_priv->vbo_offset += size;
+    } else {
+        /* Return a pointer to the statically allocated non-VBO
+         * memory. We'll upload it through glBufferData() later.
+         */
+        if (glamor_priv->vbo_size < size) {
+            glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
+
+            glBufferData(GL_ARRAY_BUFFER,
+                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
+
+            free(glamor_priv->vb);
+            glamor_priv->vb = XNFalloc(size);
+        }
+        *vbo_offset = NULL;
+        glamor_priv->vbo_offset = 0;
+        data = glamor_priv->vb;
+    }
+
+    glamor_put_context(glamor_priv);
+
+    return data;
+}
+
+void
+glamor_put_vbo_space(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_get_context(glamor_priv);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        glUnmapBuffer(GL_ARRAY_BUFFER);
+    } else {
+        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
+                     glamor_priv->vb, GL_DYNAMIC_DRAW);
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    glamor_put_context(glamor_priv);
+}
+
+void
+glamor_init_vbo(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_get_context(glamor_priv);
+
+    glGenBuffers(1, &glamor_priv->vbo);
+
+    glamor_put_context(glamor_priv);
+}
+
+void
+glamor_fini_vbo(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_get_context(glamor_priv);
+
+    glDeleteBuffers(1, &glamor_priv->vbo);
+    if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP)
+        free(glamor_priv->vb);
+
+    glamor_put_context(glamor_priv);
+}
-- 
1.9.0



More information about the xorg-devel mailing list