--- v2: Document the difference between _mesa_lookup_bufferobj() and _mesa_multi_bind_lookup_bufferobj().
src/mesa/main/bufferobj.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ src/mesa/main/bufferobj.h | 14 ++++++++ 2 files changed, 97 insertions(+) diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 4d53e5c..9a59a5a 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -975,6 +975,89 @@ _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer) } +struct gl_buffer_object * +_mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer) +{ + return (struct gl_buffer_object *) + _mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer); +} + + +void +_mesa_begin_bufferobj_lookups(struct gl_context *ctx) +{ + _mesa_HashLockMutex(ctx->Shared->BufferObjects); +} + + +void +_mesa_end_bufferobj_lookups(struct gl_context *ctx) +{ + _mesa_HashUnlockMutex(ctx->Shared->BufferObjects); +} + + +/** + * Look up a buffer object for a multi-bind function. + * + * Unlike _mesa_lookup_bufferobj(), this function also takes care + * of allocating the buffer object if the buffer ID has not been + * used before. It will also generate a GL error if the ID + * is not zero or the name of an existing buffer object. + * + * If the buffer ID refers to an existing buffer object, a pointer + * to the buffer object is returned. If the ID is zero, a pointer + * to the shared NullBufferObj is returned. If the ID is not zero + * and does not refer to a valid buffer object, this function + * returns NULL. + * + * This function assumes that the caller has already locked the + * hash table mutex by calling _mesa_begin_bufferobj_lookups(). + */ +struct gl_buffer_object * +_mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx, GLenum target, + const GLuint *buffers, + GLuint index, const char *caller) +{ + struct gl_buffer_object *bufObj; + + if (buffers[index] != 0) + bufObj = _mesa_lookup_bufferobj_locked(ctx, buffers[index]); + else + bufObj = ctx->Shared->NullBufferObj; + + if (!bufObj) { + /* The ARB_multi_bind spec says: + * + * "An INVALID_OPERATION error is generated if any value + * in <buffers> is not zero or the name of an existing + * buffer object (per binding)." + */ + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(buffers[%u]=%u is not zero or the name " + "of an existing buffer object)", + caller, index, buffers[index]); + } + + if (unlikely(bufObj == &DummyBufferObject)) { + /* If the buffer ID has been generated but never used before, + * allocate a buffer object now. + */ + ASSERT(ctx->Driver.NewBufferObject); + bufObj = ctx->Driver.NewBufferObject(ctx, buffers[index], target); + if (unlikely(!bufObj)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); + return NULL; + } + + _mesa_HashInsertLocked(ctx->Shared->BufferObjects, + buffers[index], bufObj); + } + + return bufObj; +} + + /** * If *ptr points to obj, set ptr = the Null/default buffer object. * This is a helper for buffer object deletion. diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h index e1b2a56..1fb5cd4 100644 --- a/src/mesa/main/bufferobj.h +++ b/src/mesa/main/bufferobj.h @@ -86,6 +86,20 @@ _mesa_update_default_objects_buffer_objects(struct gl_context *ctx); extern struct gl_buffer_object * _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer); +extern struct gl_buffer_object * +_mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer); + +extern void +_mesa_begin_bufferobj_lookups(struct gl_context *ctx); + +extern void +_mesa_end_bufferobj_lookups(struct gl_context *ctx); + +extern struct gl_buffer_object * +_mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx, GLenum target, + const GLuint *buffers, + GLuint index, const char *caller); + extern void _mesa_initialize_buffer_object(struct gl_context *ctx, struct gl_buffer_object *obj, -- 1.8.5.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev