From e592f1122782c64edbbf93bb30125f822d65b767 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 27 Jan 2014 21:22:43 +0100 Subject: [PATCH] mesa: implement glBufferStorage, immutable buffers; add extension enable flag MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reviewed-by: Fredrik Höglund v2: dropped the error that DYNAMIC_STORAGE is required for MAP_WRITE_BIT, the error is removed in the latest revision of GL 4.4 --- src/mesa/main/bufferobj.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ src/mesa/main/bufferobj.h | 4 ++ src/mesa/main/extensions.c | 1 + src/mesa/main/mtypes.h | 2 + 4 files changed, 100 insertions(+) diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index f4dea26..22d14ba 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -1234,6 +1234,68 @@ _mesa_IsBuffer(GLuint id) void GLAPIENTRY +_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_buffer_object *bufObj; + + if (size <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(size <= 0)"); + return; + } + + if (flags & ~(GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_PERSISTENT_BIT | + GL_MAP_COHERENT_BIT | + GL_DYNAMIC_STORAGE_BIT | + GL_CLIENT_STORAGE_BIT)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags)"); + return; + } + + if (flags & GL_MAP_PERSISTENT_BIT && + !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=READ/WRITE)"); + return; + } + + if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBufferStorage(flags!=PERSISTENT)"); + return; + } + + bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION); + if (!bufObj) + return; + + if (bufObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage(immutable)"); + return; + } + + if (_mesa_bufferobj_mapped(bufObj)) { + /* Unmap the existing buffer. We'll replace it now. Not an error. */ + ctx->Driver.UnmapBuffer(ctx, bufObj); + bufObj->AccessFlags = 0; + ASSERT(bufObj->Pointer == NULL); + } + + FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); + + bufObj->Written = GL_TRUE; + bufObj->Immutable = GL_TRUE; + + ASSERT(ctx->Driver.BufferData); + if (!ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW, + flags, bufObj)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()"); + } +} + + +void GLAPIENTRY _mesa_BufferData(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage) { @@ -1285,6 +1347,11 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, if (!bufObj) return; + if (bufObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData(immutable)"); + return; + } + if (_mesa_bufferobj_mapped(bufObj)) { /* Unmap the existing buffer. We'll replace it now. Not an error. */ ctx->Driver.UnmapBuffer(ctx, bufObj); @@ -1331,6 +1398,12 @@ _mesa_BufferSubData(GLenum target, GLintptrARB offset, return; } + if (bufObj->Immutable && + !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubData"); + return; + } + if (size == 0) return; @@ -1663,6 +1736,16 @@ _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) goto invalid_pname; *params = (GLint) bufObj->Length; return; + case GL_BUFFER_IMMUTABLE_STORAGE: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->Immutable; + return; + case GL_BUFFER_STORAGE_FLAGS: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->StorageFlags; + return; default: ; /* fall-through */ } @@ -1717,6 +1800,16 @@ _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) goto invalid_pname; *params = bufObj->Length; return; + case GL_BUFFER_IMMUTABLE_STORAGE: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->Immutable; + return; + case GL_BUFFER_STORAGE_FLAGS: + if (!ctx->Extensions.ARB_buffer_storage) + goto invalid_pname; + *params = bufObj->StorageFlags; + return; default: ; /* fall-through */ } diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h index 71988b0..174fd60 100644 --- a/src/mesa/main/bufferobj.h +++ b/src/mesa/main/bufferobj.h @@ -118,6 +118,10 @@ GLboolean GLAPIENTRY _mesa_IsBuffer(GLuint buffer); void GLAPIENTRY +_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, + GLbitfield flags); + +void GLAPIENTRY _mesa_BufferData(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage); diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 2611db8..c46d70b 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -83,6 +83,7 @@ static const struct extension extension_table[] = { { "GL_ARB_arrays_of_arrays", o(ARB_arrays_of_arrays), GL, 2012 }, { "GL_ARB_base_instance", o(ARB_base_instance), GL, 2011 }, { "GL_ARB_blend_func_extended", o(ARB_blend_func_extended), GL, 2009 }, + { "GL_ARB_buffer_storage", o(ARB_buffer_storage), GL, 2013 }, { "GL_ARB_clear_buffer_object", o(dummy_true), GL, 2012 }, { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, { "GL_ARB_compute_shader", o(ARB_compute_shader), GL, 2012 }, diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 536ed31..5c39ac9 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1462,6 +1462,7 @@ struct gl_buffer_object GLboolean DeletePending; /**< true if buffer object is removed from the hash */ GLboolean Written; /**< Ever written to? (for debugging) */ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */ + GLboolean Immutable; /**< GL_ARB_buffer_storage */ }; @@ -3474,6 +3475,7 @@ struct gl_extensions GLboolean ARB_arrays_of_arrays; GLboolean ARB_base_instance; GLboolean ARB_blend_func_extended; + GLboolean ARB_buffer_storage; GLboolean ARB_color_buffer_float; GLboolean ARB_compute_shader; GLboolean ARB_conservative_depth; -- 2.7.4