summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/main/bufferobj.c93
-rw-r--r--src/mesa/main/bufferobj.h4
-rw-r--r--src/mesa/main/extensions.c1
-rw-r--r--src/mesa/main/mtypes.h2
4 files changed, 100 insertions, 0 deletions
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index f4dea26c347..22d14baa560 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 71988b0d9b5..174fd608ced 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 2611db88a68..c46d70b2055 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 536ed314195..5c39ac91238 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;