Add MESA_FORMAT_XRGB8888_REV.
[mesa.git] / src / mesa / main / bufferobj.c
index 1ae63a0ef6fffeba1b6a4295e684c01f0dd85725..52c4995b0ad95a69e8848f92dd19ae5ef83c4b29 100644 (file)
 
 
 /**
- * Get the buffer object bound to the specified target in a GL context.
- *
- * \param ctx     GL context
- * \param target  Buffer object target to be retrieved.  Currently this must
- *                be either \c GL_ARRAY_BUFFER or \c GL_ELEMENT_ARRAY_BUFFER.
- * \return   A pointer to the buffer object bound to \c target in the
+ * Return pointer to address of a buffer object target.
+ * \param ctx  the GL context
+ * \param target  the buffer object target to be retrieved.
+ * \return   pointer to pointer to the buffer object bound to \c target in the
  *           specified context or \c NULL if \c target is invalid.
  */
-static INLINE struct gl_buffer_object *
-get_buffer(GLcontext *ctx, GLenum target)
+static INLINE struct gl_buffer_object **
+get_buffer_target(GLcontext *ctx, GLenum target)
 {
-   struct gl_buffer_object * bufObj = NULL;
-
    switch (target) {
-      case GL_ARRAY_BUFFER_ARB:
-         bufObj = ctx->Array.ArrayBufferObj;
-         break;
-      case GL_ELEMENT_ARRAY_BUFFER_ARB:
-         bufObj = ctx->Array.ElementArrayBufferObj;
-         break;
-      case GL_PIXEL_PACK_BUFFER_EXT:
-         bufObj = ctx->Pack.BufferObj;
-         break;
-      case GL_PIXEL_UNPACK_BUFFER_EXT:
-         bufObj = ctx->Unpack.BufferObj;
-         break;
-      case GL_COPY_READ_BUFFER:
-         if (ctx->Extensions.ARB_copy_buffer) {
-            bufObj = ctx->CopyReadBuffer;
-         }
-         break;
-      case GL_COPY_WRITE_BUFFER:
-         if (ctx->Extensions.ARB_copy_buffer) {
-            bufObj = ctx->CopyWriteBuffer;
-         }
-         break;
-      default:
-         /* error must be recorded by caller */
-         return NULL;
+   case GL_ARRAY_BUFFER_ARB:
+      return &ctx->Array.ArrayBufferObj;
+   case GL_ELEMENT_ARRAY_BUFFER_ARB:
+      return &ctx->Array.ElementArrayBufferObj;
+   case GL_PIXEL_PACK_BUFFER_EXT:
+      return &ctx->Pack.BufferObj;
+   case GL_PIXEL_UNPACK_BUFFER_EXT:
+      return &ctx->Unpack.BufferObj;
+   case GL_COPY_READ_BUFFER:
+      if (ctx->Extensions.ARB_copy_buffer) {
+         return &ctx->CopyReadBuffer;
+      }
+      break;
+   case GL_COPY_WRITE_BUFFER:
+      if (ctx->Extensions.ARB_copy_buffer) {
+         return &ctx->CopyWriteBuffer;
+      }
+      break;
+   default:
+      return NULL;
    }
+   return NULL;
+}
 
-   /* bufObj should point to NullBufferObj or a user-created buffer object */
-   ASSERT(bufObj);
 
-   return bufObj;
+/**
+ * Get the buffer object bound to the specified target in a GL context.
+ * \param ctx  the GL context
+ * \param target  the buffer object target to be retrieved.
+ * \return   pointer to the buffer object bound to \c target in the
+ *           specified context or \c NULL if \c target is invalid.
+ */
+static INLINE struct gl_buffer_object *
+get_buffer(GLcontext *ctx, GLenum target)
+{
+   struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
+   if (bufObj)
+      return *bufObj;
+   return NULL;
 }
 
 
@@ -552,6 +556,7 @@ _mesa_init_buffer_objects( GLcontext *ctx )
 
 /**
  * Bind the specified target to buffer for the specified context.
+ * Called by glBindBuffer() and other functions.
  */
 static void
 bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
@@ -560,40 +565,14 @@ bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
    struct gl_buffer_object *newBufObj = NULL;
    struct gl_buffer_object **bindTarget = NULL;
 
-   switch (target) {
-   case GL_ARRAY_BUFFER_ARB:
-      bindTarget = &ctx->Array.ArrayBufferObj;
-      break;
-   case GL_ELEMENT_ARRAY_BUFFER_ARB:
-      bindTarget = &ctx->Array.ElementArrayBufferObj;
-      break;
-   case GL_PIXEL_PACK_BUFFER_EXT:
-      bindTarget = &ctx->Pack.BufferObj;
-      break;
-   case GL_PIXEL_UNPACK_BUFFER_EXT:
-      bindTarget = &ctx->Unpack.BufferObj;
-      break;
-   case GL_COPY_READ_BUFFER:
-      if (ctx->Extensions.ARB_copy_buffer) {
-         bindTarget = &ctx->CopyReadBuffer;
-      }
-      break;
-   case GL_COPY_WRITE_BUFFER:
-      if (ctx->Extensions.ARB_copy_buffer) {
-         bindTarget = &ctx->CopyWriteBuffer;
-      }
-      break;
-   default:
-      ; /* no-op / we'll hit the follow error test next */
-   }
-
+   bindTarget = get_buffer_target(ctx, target);
    if (!bindTarget) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)");
       return;
    }
 
    /* Get pointer to old buffer object (to be unbound) */
-   oldBufObj = get_buffer(ctx, target);
+   oldBufObj = *bindTarget;
    if (oldBufObj && oldBufObj->Name == buffer)
       return;   /* rebinding the same buffer object- no change */
 
@@ -745,6 +724,47 @@ _mesa_map_pbo_source(GLcontext *ctx,
 }
 
 
+/**
+ * Combine PBO-read validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_source
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_source().
+ */
+const GLvoid *
+_mesa_map_validate_pbo_source(GLcontext *ctx,
+                              GLuint dimensions,
+                              const struct gl_pixelstore_attrib *unpack,
+                              GLsizei width, GLsizei height, GLsizei depth,
+                              GLenum format, GLenum type, const GLvoid *ptr,
+                              const char *where)
+{
+   ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+      /* non-PBO access: no validation to be done */
+      return ptr;
+   }
+
+   if (!_mesa_validate_pbo_access(dimensions, unpack,
+                                  width, height, depth, format, type, ptr)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(out of bounds PBO access)", where);
+      return NULL;
+   }
+
+   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+      /* buffer is already mapped - that's an error */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+      return NULL;
+   }
+
+   ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
+   return ptr;
+}
+
+
 /**
  * Counterpart to _mesa_map_pbo_source()
  */
@@ -794,6 +814,47 @@ _mesa_map_pbo_dest(GLcontext *ctx,
 }
 
 
+/**
+ * Combine PBO-write validation and mapping.
+ * If any GL errors are detected, they'll be recorded and NULL returned.
+ * \sa _mesa_validate_pbo_access
+ * \sa _mesa_map_pbo_dest
+ * A call to this function should have a matching call to
+ * _mesa_unmap_pbo_dest().
+ */
+GLvoid *
+_mesa_map_validate_pbo_dest(GLcontext *ctx,
+                            GLuint dimensions,
+                            const struct gl_pixelstore_attrib *unpack,
+                            GLsizei width, GLsizei height, GLsizei depth,
+                            GLenum format, GLenum type, GLvoid *ptr,
+                            const char *where)
+{
+   ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
+
+   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+      /* non-PBO access: no validation to be done */
+      return ptr;
+   }
+
+   if (!_mesa_validate_pbo_access(dimensions, unpack,
+                                  width, height, depth, format, type, ptr)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "%s(out of bounds PBO access)", where);
+      return NULL;
+   }
+
+   if (_mesa_bufferobj_mapped(unpack->BufferObj)) {
+      /* buffer is already mapped - that's an error */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where);
+      return NULL;
+   }
+
+   ptr = _mesa_map_pbo_dest(ctx, unpack, ptr);
+   return ptr;
+}
+
+
 /**
  * Counterpart to _mesa_map_pbo_dest()
  */
@@ -1091,7 +1152,7 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
 
    ASSERT(ctx->Driver.BufferData);
    if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB(access)");
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()");
    }
 }
 
@@ -1180,7 +1241,7 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
    ASSERT(ctx->Driver.MapBuffer);
    map = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
    if (!map) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
       return NULL;
    }
    else {
@@ -1511,7 +1572,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
    map = ctx->Driver.MapBufferRange(ctx, target, offset, length,
                                     access, bufObj);
    if (!map) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
    }
    else {
       /* The driver callback should have set all these fields.