v2: - Make the default buffer size a #define. (by Markus Wick) - Fix the return offset for mapping with buffer_storage. (oops!) v3: - Avoid GL error at first rendering from unmapping no buffer. - Rebase on the glBindBuffer(GL_ARRAY_BUFFER, 0) change. v4: Rebase on Markus's vbo init changes.
Signed-off-by: Eric Anholt <e...@anholt.net> --- glamor/glamor.c | 2 ++ glamor/glamor_priv.h | 1 + glamor/glamor_vbo.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index dc69c72..e856179 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -353,6 +353,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"); glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); #ifdef MAX_FBO_SIZE glamor_priv->max_fbo_size = MAX_FBO_SIZE; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 986e729..d15eabd 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -208,6 +208,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 diff --git a/glamor/glamor_vbo.c b/glamor/glamor_vbo.c index be2c2af..f736cbe 100644 --- a/glamor/glamor_vbo.c +++ b/glamor/glamor_vbo.c @@ -52,7 +52,49 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset) 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_size) + glUnmapBuffer(GL_ARRAY_BUFFER); + + if (size > glamor_priv->vbo_size) { + glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size); + + /* We aren't allowed to resize glBufferStorage() + * buffers, so we need to gen a new one. + */ + glDeleteBuffers(1, &glamor_priv->vbo); + glGenBuffers(1, &glamor_priv->vbo); + glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo); + + assert(glGetError() == GL_NO_ERROR); + glBufferStorage(GL_ARRAY_BUFFER, glamor_priv->vbo_size, NULL, + GL_MAP_WRITE_BIT | + GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT); + + if (glGetError() != GL_NO_ERROR) { + /* If the driver failed our coherent mapping, fall + * back to the ARB_mbr path. + */ + glamor_priv->has_buffer_storage = false; + glamor_priv->vbo_size = 0; + return glamor_get_vbo_space(screen, size, vbo_offset); + } + } + + glamor_priv->vbo_offset = 0; + glamor_priv->vb = 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); + } + *vbo_offset = (void *)(uintptr_t)glamor_priv->vbo_offset; + data = glamor_priv->vb + glamor_priv->vbo_offset; + glamor_priv->vbo_offset += size; + } else 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; @@ -99,7 +141,12 @@ glamor_put_vbo_space(ScreenPtr screen) glamor_get_context(glamor_priv); - if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { + if (glamor_priv->has_buffer_storage) { + /* 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 of the buffer. + */ + } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) { glUnmapBuffer(GL_ARRAY_BUFFER); } else { glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset, -- 1.9.0 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel