[Glamor] [PATCH 1/2] glamor: Use buffer_storage

Grigori Goronzy greg at chown.ath.cx
Thu Jun 5 08:38:22 PDT 2014


From: Eric Anholt <eric at anholt.net>

29.5361% +/- 2.74092% improvement in x11perf -aa10text (n=489).

Pulled from Eric's xserver glamor tree.

v2: Fix fallback, return correct buffer offset, map whole buffer,
unmap conditionally.
v3: add conditional defines to make it compile with outdated headers.

Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
Signed-off-by: Grigori Goronzy <greg at chown.ath.cx>
---
 src/glamor.c      |  2 ++
 src/glamor_priv.h |  2 ++
 src/glamor_vbo.c  | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/src/glamor.c b/src/glamor.c
index eb9c0ee..5fcfefe 100644
--- a/src/glamor.c
+++ b/src/glamor.c
@@ -339,6 +339,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 	    glamor_gl_has_extension("GL_MESA_pack_invert");
 	glamor_priv->has_fbo_blit =
 	    glamor_gl_has_extension("GL_EXT_framebuffer_blit");
+	glamor_priv->has_buffer_storage =
+	    glamor_gl_has_extension("GL_ARB_buffer_storage");
 	glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE,
 					     &glamor_priv->max_fbo_size);
 #ifdef MAX_FBO_SIZE
diff --git a/src/glamor_priv.h b/src/glamor_priv.h
index f7fdb88..4d75759 100644
--- a/src/glamor_priv.h
+++ b/src/glamor_priv.h
@@ -240,6 +240,7 @@ typedef struct glamor_screen_private {
 	enum glamor_gl_flavor gl_flavor;
 	int has_pack_invert;
 	int has_fbo_blit;
+	int has_buffer_storage;
 	int max_fbo_size;
 
 	struct xorg_list fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT];
@@ -256,6 +257,7 @@ typedef struct glamor_screen_private {
 	int composite_vbo_offset;
 	int vbo_size;
 	char *vb;
+	char *vb_base;
 	int vb_stride;
 	Bool has_source_coords, has_mask_coords;
 	int render_nr_verts;
diff --git a/src/glamor_vbo.c b/src/glamor_vbo.c
index 8b1d99a..2cabca1 100644
--- a/src/glamor_vbo.c
+++ b/src/glamor_vbo.c
@@ -29,17 +29,72 @@
 
 #include "glamor_priv.h"
 
+/* Allow compilation with outdated GL headers */
+#ifndef GL_MAP_PERSISTENT_BIT
+#	define GL_MAP_PERSISTENT_BIT 0x0040
+#endif
+#ifndef GL_MAP_COHERENT_BIT
+#	define GL_MAP_COHERENT_BIT 0x0080
+#endif
+
 void *
 glamor_get_vbo_space(ScreenPtr screen, int size, char **vbo_offset)
 {
 	glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 	glamor_gl_dispatch *dispatch;
+	int err = 0;
 
 	dispatch = glamor_get_dispatch(glamor_priv);
 
 	dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
 
-	if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+	if (glamor_priv->has_buffer_storage) {
+	    if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) {
+		if (glamor_priv->vbo_mapped)
+		    dispatch->glUnmapBuffer(GL_ARRAY_BUFFER);
+
+		if (size > glamor_priv->vbo_size) {
+		    glamor_priv->vbo_size = MAX(65536, size);
+
+		    /* We aren't allowed to resize glBufferStorage()
+		     * buffers, so we need to gen a new one.
+		     */
+		    dispatch->glDeleteBuffers(1, &glamor_priv->vbo);
+		    dispatch->glGenBuffers(1, &glamor_priv->vbo);
+		    dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+
+		    assert(dispatch->glGetError() == GL_NO_ERROR);
+		    dispatch->glBufferStorage(GL_ARRAY_BUFFER, glamor_priv->vbo_size, NULL,
+					      GL_MAP_WRITE_BIT |
+					      GL_MAP_PERSISTENT_BIT |
+					      GL_MAP_COHERENT_BIT);
+
+		    err = dispatch->glGetError();
+		    if (err != GL_NO_ERROR) {
+			    /* If the driver failed our coherent mapping, fall
+			     * back to the ARB_mbr path.
+			     */
+			    ErrorF("ARB_buffer_storage: falling back to MapBufferRange path!\n");
+			    glamor_priv->has_buffer_storage = FALSE;
+			    glamor_priv->vbo_size = 0;
+			    glamor_put_dispatch(glamor_priv);
+			    return glamor_get_vbo_space(screen, size, vbo_offset);
+		    }
+		}
+
+		glamor_priv->vbo_offset = 0;
+		glamor_priv->vb_base = dispatch->glMapBufferRange(GL_ARRAY_BUFFER,
+								  0, glamor_priv->vbo_size,
+								  GL_MAP_WRITE_BIT |
+								  GL_MAP_INVALIDATE_BUFFER_BIT |
+								  GL_MAP_PERSISTENT_BIT |
+								  GL_MAP_COHERENT_BIT);
+	    }
+	    glamor_priv->vb = glamor_priv->vb_base + glamor_priv->vbo_offset;
+	    *vbo_offset = (void *)(uintptr_t)glamor_priv->vbo_offset;
+	    glamor_priv->vbo_offset += size;
+	    glamor_priv->vbo_mapped = TRUE;
+	} else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
 	    if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) {
 		glamor_priv->vbo_size = MAX(65536, size);
 		glamor_priv->vbo_offset = 0;
@@ -81,6 +136,12 @@ glamor_put_vbo_space(ScreenPtr screen)
 	glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 	glamor_gl_dispatch *dispatch;
 
+	/* If we're in the ARB_buffer_storage path, we have a persistent
+	 * mapping, so we can leave it around until we reach the end.
+	 */
+	if (glamor_priv->has_buffer_storage)
+		return;
+
 	dispatch = glamor_get_dispatch(glamor_priv);
 
 	if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-- 
1.8.3.2



More information about the Glamor mailing list