/**
- * 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;
}
/**
* 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)
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 */
}
+/**
+ * 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()
*/
}
+/**
+ * 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()
*/
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()");
}
}
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 {
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.