mesa: implement glBufferStorage, immutable buffers; add extension enable flag
authorMarek Olšák <marek.olsak@amd.com>
Mon, 27 Jan 2014 20:22:43 +0000 (21:22 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 25 Feb 2014 15:04:22 +0000 (16:04 +0100)
Reviewed-by: Fredrik Höglund <fredrik@kde.org>
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
src/mesa/main/bufferobj.h
src/mesa/main/extensions.c
src/mesa/main/mtypes.h

index f4dea26c3477f6e1e84f24492e8f46b2d537b931..22d14baa56026f7bc9aae4f890b5f312962c20a7 100644 (file)
@@ -1233,6 +1233,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 */
    }
index 71988b0d9b51c2d6f25be31a418cdc2bcc3e4f68..174fd608ced1a4d64da35405cc505c2e6d38ea3c 100644 (file)
@@ -117,6 +117,10 @@ _mesa_GenBuffers(GLsizei n, GLuint * buffer);
 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);
index 2611db88a68d7fb918b4d74f7d1a714c023fcc19..c46d70b205506d40e3a5b482b064becd5f18bfe2 100644 (file)
@@ -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 },
index 536ed31419566a8e225bf9c1620df5c56e5a8b10..5c39ac9123849c8c01b2d0567206d59b7056e84b 100644 (file)
@@ -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;