[Mesa-dev] [PATCH 02/18] mesa: split out validation from map_buffer_range()

Timothy Arceri tarceri at itsqueeze.com
Thu May 4 07:41:27 UTC 2017


This will allow us to add KHR_no_error support for *BufferRange
functions.
---
 src/mesa/main/bufferobj.c | 77 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 50 insertions(+), 27 deletions(-)

diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index 76e035f..797b6fb 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -2371,163 +2371,170 @@ _mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
 
    dst = _mesa_lookup_bufferobj_err(ctx, writeBuffer,
                                     "glCopyNamedBufferSubData");
    if (!dst)
       return;
 
    _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
                               "glCopyNamedBufferSubData");
 }
 
-
-static void *
-map_buffer_range(struct gl_context *ctx, struct gl_buffer_object *bufObj,
-                 GLintptr offset, GLsizeiptr length, GLbitfield access,
-                 const char *func)
+static bool
+validate_map_buffer_range(struct gl_context *ctx,
+                          struct gl_buffer_object *bufObj, GLintptr offset,
+                          GLsizeiptr length, GLbitfield access,
+                          const char *func)
 {
-   void *map;
    GLbitfield allowed_access;
 
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, false);
 
    if (offset < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "%s(offset %ld < 0)", func, (long) offset);
-      return NULL;
+      return false;
    }
 
    if (length < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "%s(length %ld < 0)", func, (long) length);
-      return NULL;
+      return false;
    }
 
    /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
     *
     *     "An INVALID_OPERATION error is generated for any of the following
     *     conditions:
     *
     *     * <length> is zero."
     *
     * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec
     * (30.10.2014) also says this, so it's no longer allowed for desktop GL,
     * either.
     */
    if (length == 0) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func);
-      return NULL;
+      return false;
    }
 
    allowed_access = GL_MAP_READ_BIT |
                     GL_MAP_WRITE_BIT |
                     GL_MAP_INVALIDATE_RANGE_BIT |
                     GL_MAP_INVALIDATE_BUFFER_BIT |
                     GL_MAP_FLUSH_EXPLICIT_BIT |
                     GL_MAP_UNSYNCHRONIZED_BIT;
 
    if (ctx->Extensions.ARB_buffer_storage) {
          allowed_access |= GL_MAP_PERSISTENT_BIT |
                            GL_MAP_COHERENT_BIT;
    }
 
    if (access & ~allowed_access) {
       /* generate an error if any bits other than those allowed are set */
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "%s(access has undefined bits set)", func);
-      return NULL;
+      return false;
    }
 
    if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(access indicates neither read or write)", func);
-      return NULL;
+      return false;
    }
 
    if ((access & GL_MAP_READ_BIT) &&
        (access & (GL_MAP_INVALIDATE_RANGE_BIT |
                   GL_MAP_INVALIDATE_BUFFER_BIT |
                   GL_MAP_UNSYNCHRONIZED_BIT))) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(read access with disallowed bits)", func);
-      return NULL;
+      return false;
    }
 
    if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
        ((access & GL_MAP_WRITE_BIT) == 0)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(access has flush explicit without write)", func);
-      return NULL;
+      return false;
    }
 
    if (access & GL_MAP_READ_BIT &&
        !(bufObj->StorageFlags & GL_MAP_READ_BIT)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(buffer does not allow read access)", func);
-      return NULL;
+      return false;
    }
 
    if (access & GL_MAP_WRITE_BIT &&
        !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(buffer does not allow write access)", func);
-      return NULL;
+      return false;
    }
 
    if (access & GL_MAP_COHERENT_BIT &&
        !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(buffer does not allow coherent access)", func);
-      return NULL;
+      return false;
    }
 
    if (access & GL_MAP_PERSISTENT_BIT &&
        !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(buffer does not allow persistent access)", func);
-      return NULL;
+      return false;
    }
 
    if (offset + length > bufObj->Size) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "%s(offset %lu + length %lu > buffer_size %lu)", func,
                   (unsigned long) offset, (unsigned long) length,
                   (unsigned long) bufObj->Size);
-      return NULL;
+      return false;
    }
 
    if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "%s(buffer already mapped)", func);
-      return NULL;
-   }
-
-   if (!bufObj->Size) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
-      return NULL;
+      return false;
    }
 
    if (access & GL_MAP_WRITE_BIT) {
       bufObj->NumMapBufferWriteCalls++;
       if ((bufObj->Usage == GL_STATIC_DRAW ||
            bufObj->Usage == GL_STATIC_COPY) &&
           bufObj->NumMapBufferWriteCalls >= BUFFER_WARNING_CALL_COUNT) {
          BUFFER_USAGE_WARNING(ctx,
                               "using %s(buffer %u, offset %u, length %u) to "
                               "update a %s buffer",
                               func, bufObj->Name, offset, length,
                               _mesa_enum_to_string(bufObj->Usage));
       }
    }
 
+   return true;
+}
+
+static void *
+map_buffer_range(struct gl_context *ctx, struct gl_buffer_object *bufObj,
+                 GLintptr offset, GLsizeiptr length, GLbitfield access,
+                 const char *func)
+{
+   if (!bufObj->Size) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
+      return NULL;
+   }
+
    assert(ctx->Driver.MapBufferRange);
-   map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
-                                    MAP_USER);
+   void *map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
+                                          MAP_USER);
    if (!map) {
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func);
    }
    else {
       /* The driver callback should have set all these fields.
        * This is important because other modules (like VBO) might call
        * the driver function directly.
        */
       assert(bufObj->Mappings[MAP_USER].Pointer == map);
       assert(bufObj->Mappings[MAP_USER].Length == length);
@@ -2578,20 +2585,24 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
    if (!ctx->Extensions.ARB_map_buffer_range) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glMapBufferRange(ARB_map_buffer_range not supported)");
       return NULL;
    }
 
    bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION);
    if (!bufObj)
       return NULL;
 
+   if (!validate_map_buffer_range(ctx, bufObj, offset, length, access,
+                                  "glMapBufferRange"))
+      return NULL;
+
    return map_buffer_range(ctx, bufObj, offset, length, access,
                            "glMapBufferRange");
 }
 
 void * GLAPIENTRY
 _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
                           GLbitfield access)
 {
    GET_CURRENT_CONTEXT(ctx);
    struct gl_buffer_object *bufObj;
@@ -2600,20 +2611,24 @@ _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glMapNamedBufferRange("
                   "ARB_map_buffer_range not supported)");
       return NULL;
    }
 
    bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBufferRange");
    if (!bufObj)
       return NULL;
 
+   if (!validate_map_buffer_range(ctx, bufObj, offset, length, access,
+                                  "glMapNamedBufferRange"))
+      return NULL;
+
    return map_buffer_range(ctx, bufObj, offset, length, access,
                            "glMapNamedBufferRange");
 }
 
 /**
  * Converts GLenum access from MapBuffer and MapNamedBuffer into
  * flags for input to map_buffer_range.
  *
  * \return true if the type of requested access is permissible.
  */
@@ -2645,40 +2660,48 @@ _mesa_MapBuffer(GLenum target, GLenum access)
 
    if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glMapBuffer(invalid access)");
       return NULL;
    }
 
    bufObj = get_buffer(ctx, "glMapBuffer", target, GL_INVALID_OPERATION);
    if (!bufObj)
       return NULL;
 
+   if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+                                  "glMapBuffer"))
+      return NULL;
+
    return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
                            "glMapBuffer");
 }
 
 void * GLAPIENTRY
 _mesa_MapNamedBuffer(GLuint buffer, GLenum access)
 {
    GET_CURRENT_CONTEXT(ctx);
    struct gl_buffer_object *bufObj;
    GLbitfield accessFlags;
 
    if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)");
       return NULL;
    }
 
    bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBuffer");
    if (!bufObj)
       return NULL;
 
+   if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
+                                  "glMapNamedBuffer"))
+      return NULL;
+
    return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
                            "glMapNamedBuffer");
 }
 
 
 void
 _mesa_flush_mapped_buffer_range(struct gl_context *ctx,
                                 struct gl_buffer_object *bufObj,
                                 GLintptr offset, GLsizeiptr length,
                                 const char *func)
-- 
2.9.3



More information about the mesa-dev mailing list