X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmesa%2Fmain%2Fbufferobj.c;h=185d841f81219d2a7731ee6ea0df83c0de7a5006;hb=c1f2f9090bcca309b9aeef7ae57acc280704db81;hp=4e67bc225c40683593ed540bae908e5fffef62b5;hpb=0207b47aafebc06cf83fbdb8c9b01f63374fac66;p=mesa.git diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 4e67bc225c4..185d841f812 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 5.1 + * Version: 6.3 * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,32 +26,17 @@ /** * \file bufferobj.c * \brief Functions for the GL_ARB_vertex_buffer_object extension. - * \author Brian Paul + * \author Brian Paul, Ian Romanick */ #include "glheader.h" #include "hash.h" #include "imports.h" +#include "image.h" #include "context.h" #include "bufferobj.h" -struct gl_buffer_object { - GLint RefCount; - GLuint Name; - GLenum Target; - - GLenum usage; - GLenum access; - GLvoid * pointer; - GLuint size; - - void * data; -}; - -void _mesa_initialize_buffer_object( struct gl_buffer_object *obj, - GLuint name, GLenum target ); - /** * Get the buffer object bound to the specified target in a GL context. @@ -64,25 +49,32 @@ void _mesa_initialize_buffer_object( struct gl_buffer_object *obj, * specified context or \c NULL if \c target is invalid or no * buffer object is bound. */ - -static __inline struct gl_buffer_object * -_mesa_buffer_object_get_target( GLcontext *ctx, GLenum target, - const char * str ) +static INLINE struct gl_buffer_object * +buffer_object_get_target( GLcontext *ctx, GLenum target, const char * str ) { struct gl_buffer_object * bufObj = NULL; switch (target) { case GL_ARRAY_BUFFER_ARB: - bufObj = ctx->ArrayBuffer; + bufObj = ctx->Array.ArrayBufferObj; break; case GL_ELEMENT_ARRAY_BUFFER_ARB: - bufObj = ctx->ElementArrayBuffer; + 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; default: _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(target)", str); - break; + return NULL; } - + + if (bufObj->Name == 0) + return NULL; + return bufObj; } @@ -103,37 +95,37 @@ _mesa_buffer_object_get_target( GLcontext *ctx, GLenum target, * * \sa glBufferSubDataARB, glGetBufferSubDataARB */ - static struct gl_buffer_object * -_mesa_buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, - GLintptrARB offset, GLsizeiptrARB size, - const char * str ) +buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, + GLintptrARB offset, GLsizeiptrARB size, + const char * str ) { struct gl_buffer_object *bufObj; if (size < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "gl%s(size < 0)", str); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", str); return NULL; } if (offset < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "gl%s(offset < 0)", str); + _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", str); return NULL; } - bufObj = _mesa_buffer_object_get_target( ctx, target, str ); - if ( bufObj == NULL ) { + bufObj = buffer_object_get_target( ctx, target, str ); + if (!bufObj || bufObj->Name == 0) { return NULL; } - if ( (offset + size) > bufObj->size ) { + if ((GLuint) (offset + size) > bufObj->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "gl%s(size + offset > buffer size)", str); + "%s(size + offset > buffer size)", str); return NULL; } - if ( bufObj->pointer != NULL ) { - _mesa_error(ctx, GL_INVALID_OPERATION, "gl%s", str); + if (bufObj->Pointer) { + /* Buffer is currently mapped */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s", str); return NULL; } @@ -147,34 +139,56 @@ _mesa_buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, * This function is intended to be called via * \c dd_function_table::NewBufferObject. */ - struct gl_buffer_object * _mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target ) { struct gl_buffer_object *obj; - obj = CALLOC_STRUCT(gl_buffer_object); + + (void) ctx; + + obj = MALLOC_STRUCT(gl_buffer_object); _mesa_initialize_buffer_object(obj, name, target); return obj; } /** - * Initialize a buffer object to default values. + * Delete a buffer object. + * + * This function is intended to be called via + * \c dd_function_table::DeleteBuffer. */ +void +_mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) +{ + (void) ctx; + if (bufObj->Data) + _mesa_free(bufObj->Data); + _mesa_free(bufObj); +} + + +/** + * Initialize a buffer object to default values. + */ void _mesa_initialize_buffer_object( struct gl_buffer_object *obj, GLuint name, GLenum target ) { + (void) target; + + _mesa_bzero(obj, sizeof(struct gl_buffer_object)); obj->RefCount = 1; obj->Name = name; + obj->Usage = GL_STATIC_DRAW_ARB; + obj->Access = GL_READ_WRITE_ARB; } /** * Add the given buffer object to the buffer object pool. */ - void _mesa_save_buffer_object( GLcontext *ctx, struct gl_buffer_object *obj ) { @@ -189,7 +203,6 @@ _mesa_save_buffer_object( GLcontext *ctx, struct gl_buffer_object *obj ) * Remove the given buffer object from the buffer object pool. * Do not deallocate the buffer object though. */ - void _mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) { @@ -219,7 +232,6 @@ _mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) * * \sa glBufferDataARB, dd_function_table::BufferData. */ - void _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage, @@ -227,16 +239,16 @@ _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, { void * new_data; - (void) target; + (void) ctx; (void) target; - new_data = _mesa_realloc( bufObj->data, bufObj->size, size ); - if ( new_data != NULL ) { - bufObj->data = new_data; - bufObj->size = size; - bufObj->usage = usage; + new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size ); + if (new_data) { + bufObj->Data = (GLubyte *) new_data; + bufObj->Size = size; + bufObj->Usage = usage; - if ( data != NULL ) { - memcpy( bufObj->data, data, size ); + if (data) { + _mesa_memcpy( bufObj->Data, data, size ); } } } @@ -260,15 +272,15 @@ _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, * * \sa glBufferSubDataARB, dd_function_table::BufferSubData. */ - void _mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data, struct gl_buffer_object * bufObj ) { - if ( (bufObj->data != NULL) - && ((size + offset) <= bufObj->size) ) { - memcpy( (GLubyte *) bufObj->data + offset, data, size ); + (void) ctx; (void) target; + + if (bufObj->Data && ((GLuint) (size + offset) <= bufObj->Size)) { + _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size ); } } @@ -291,76 +303,198 @@ _mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, * * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData. */ - void _mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid * data, struct gl_buffer_object * bufObj ) { - if ( (bufObj->data != NULL) - && ((size + offset) <= bufObj->size) ) { - memcpy( data, (GLubyte *) bufObj->data + offset, size ); + (void) ctx; (void) target; + + if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) { + _mesa_memcpy( data, (GLubyte *) bufObj->Data + offset, size ); } } /** - * Maps the private data buffer into the processor's address space. + * Fallback function called via ctx->Driver.MapBuffer(). + * Hardware drivers that really implement buffer objects should never use + * function. * - * This function is intended to be called by \c dd_function_table::MapBuffer. - * This function need not set GL error codes. The input parameters will have - * been tested before calling. + * The input parameters will have been already tested for errors. * * \param ctx GL context. * \param target Buffer object target on which to operate. * \param access Information about how the buffer will be accessed. - * \param bufObj Object to be used. + * \param bufObj Object to be mapped. * \return A pointer to the object's internal data store that can be accessed * by the processor * * \sa glMapBufferARB, dd_function_table::MapBuffer */ - void * _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access, - struct gl_buffer_object * bufObj ) + struct gl_buffer_object *bufObj ) +{ + (void) ctx; + (void) target; + (void) access; + ASSERT(!bufObj->OnCard); + /* Just return a direct pointer to the data */ + if (bufObj->Pointer) { + /* already mapped! */ + return NULL; + } + bufObj->Pointer = bufObj->Data; + return bufObj->Pointer; +} + + +/** + * Fallback function called via ctx->Driver.MapBuffer(). + * Hardware drivers that really implement buffer objects should never use + * function. + * + * The input parameters will have been already tested for errors. + * + * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer + */ +GLboolean +_mesa_buffer_unmap( GLcontext *ctx, GLenum target, + struct gl_buffer_object *bufObj ) { - return bufObj->data; + (void) ctx; + (void) target; + ASSERT(!bufObj->OnCard); + /* XXX we might assert here that bufObj->Pointer is non-null */ + bufObj->Pointer = NULL; + return GL_TRUE; } +/** + * Initialize the state associated with buffer objects + */ void +_mesa_init_buffer_objects( GLcontext *ctx ) +{ + GLuint i; + + /* Allocate the default buffer object and set refcount so high that + * it never gets deleted. + */ + ctx->Array.NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0); + if (ctx->Array.NullBufferObj) + ctx->Array.NullBufferObj->RefCount = 1000; + + ctx->Array.ArrayBufferObj = ctx->Array.NullBufferObj; + ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj; + + /* Vertex array buffers */ + ctx->Array.Vertex.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.Normal.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.Color.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.SecondaryColor.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.FogCoord.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.Index.BufferObj = ctx->Array.NullBufferObj; + for (i = 0; i < MAX_TEXTURE_UNITS; i++) { + ctx->Array.TexCoord[i].BufferObj = ctx->Array.NullBufferObj; + } + ctx->Array.EdgeFlag.BufferObj = ctx->Array.NullBufferObj; + for (i = 0; i < VERT_ATTRIB_MAX; i++) { + ctx->Array.VertexAttrib[i].BufferObj = ctx->Array.NullBufferObj; + } +} + + +/** + * When we're about to read pixel data out of a PBO (via glDrawPixels, + * glTexImage, etc) or write data into a PBO (via glReadPixels, + * glGetTexImage, etc) we call this function to check that we're not + * going to read out of bounds. + * + * XXX This would also be a convenient time to check that the PBO isn't + * currently mapped. Whoever calls this function should check for that. + * Remember, we can't use a PBO when it's mapped! + * + * \param width width of image to read/write + * \param height height of image to read/write + * \param depth depth of image to read/write + * \param format format of image to read/write + * \param type datatype of image to read/write + * \param ptr the user-provided pointer/offset + * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would + * go out of bounds. + */ +GLboolean +_mesa_validate_pbo_access(GLuint dimensions, + const struct gl_pixelstore_attrib *pack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *ptr) +{ + GLvoid *start, *end; + + ASSERT(pack->BufferObj->Name != 0); + + if (pack->BufferObj->Size == 0) + /* no buffer! */ + return GL_FALSE; + + /* get address of first pixel we'll read */ + start = _mesa_image_address(dimensions, pack, ptr, width, height, + format, type, 0, 0, 0); + + /* get address just past the last pixel we'll read */ + end = _mesa_image_address(dimensions, pack, ptr, width, height, + format, type, depth-1, height-1, width); + + + if ((const GLubyte *) start > (const GLubyte *) pack->BufferObj->Size) { + /* This will catch negative values / wrap-around */ + return GL_FALSE; + } + if ((const GLubyte *) end > (const GLubyte *) pack->BufferObj->Size) { + /* Image read goes beyond end of buffer */ + return GL_FALSE; + } + + /* OK! */ + return GL_TRUE; +} + + + + +/**********************************************************************/ +/* API Functions */ +/**********************************************************************/ + +void GLAPIENTRY _mesa_BindBufferARB(GLenum target, GLuint buffer) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *oldBufObj; - struct gl_buffer_object *newBufObj = 0; + struct gl_buffer_object *newBufObj = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); - oldBufObj = _mesa_buffer_object_get_target( ctx, target, "BindBufferARB" ); - if ( (oldBufObj != NULL) && (oldBufObj->Name == buffer) ) + oldBufObj = buffer_object_get_target( ctx, target, "BindBufferARB" ); + if (oldBufObj && oldBufObj->Name == buffer) return; /* rebinding the same buffer object- no change */ /* * Get pointer to new buffer object (newBufObj) */ - if ( buffer == 0 ) { - newBufObj = NULL; + if (buffer == 0) { + /* The spec says there's not a buffer object named 0, but we use + * one internally because it simplifies things. + */ + newBufObj = ctx->Array.NullBufferObj; } else { /* non-default buffer object */ const struct _mesa_HashTable *hash = ctx->Shared->BufferObjects; newBufObj = (struct gl_buffer_object *) _mesa_HashLookup(hash, buffer); - if ( newBufObj != NULL ) { - /* error checking */ - if (newBufObj->Target != 0 && newBufObj->Target != target) { - /* the named buffer object's target doesn't match the target */ - _mesa_error( ctx, GL_INVALID_OPERATION, - "glBindBufferARB(wrong target)" ); - return; - } - } - else { + if (!newBufObj) { /* if this is a new buffer object id, allocate a buffer object now */ newBufObj = (*ctx->Driver.NewBufferObject)(ctx, buffer, target); if (!newBufObj) { @@ -369,31 +503,38 @@ _mesa_BindBufferARB(GLenum target, GLuint buffer) } _mesa_save_buffer_object(ctx, newBufObj); } - newBufObj->Target = target; newBufObj->RefCount++; } switch (target) { case GL_ARRAY_BUFFER_ARB: - ctx->ArrayBuffer = newBufObj; + ctx->Array.ArrayBufferObj = newBufObj; break; case GL_ELEMENT_ARRAY_BUFFER_ARB: - ctx->ElementArrayBuffer = newBufObj; + ctx->Array.ElementArrayBufferObj = newBufObj; + break; + case GL_PIXEL_PACK_BUFFER_EXT: + ctx->Pack.BufferObj = newBufObj; + break; + case GL_PIXEL_UNPACK_BUFFER_EXT: + ctx->Unpack.BufferObj = newBufObj; break; + default: + _mesa_problem(ctx, "Bad target in _mesa_BindBufferARB"); + return; } /* Pass BindBuffer call to device driver */ - if ( (ctx->Driver.BindBuffer != NULL) && (newBufObj != NULL) ) + if (ctx->Driver.BindBuffer && newBufObj) (*ctx->Driver.BindBuffer)( ctx, target, newBufObj ); - if ( oldBufObj != NULL ) { + if (oldBufObj) { oldBufObj->RefCount--; assert(oldBufObj->RefCount >= 0); if (oldBufObj->RefCount == 0) { assert(oldBufObj->Name != 0); - _mesa_remove_buffer_object(ctx, oldBufObj); ASSERT(ctx->Driver.DeleteBuffer); - (*ctx->Driver.DeleteBuffer)( ctx, oldBufObj ); + ctx->Driver.DeleteBuffer( ctx, oldBufObj ); } } } @@ -403,14 +544,13 @@ _mesa_BindBufferARB(GLenum target, GLuint buffer) * Delete a set of buffer objects. * * \param n Number of buffer objects to delete. - * \param buffer Array of \c n buffer object IDs. + * \param ids Array of \c n buffer object IDs. */ - -void +void GLAPIENTRY _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) { GET_CURRENT_CONTEXT(ctx); - unsigned i; + GLsizei i; ASSERT_OUTSIDE_BEGIN_END(ctx); if (n < 0) { @@ -425,24 +565,84 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) struct gl_buffer_object *bufObj = (struct gl_buffer_object *) _mesa_HashLookup(ctx->Shared->BufferObjects, ids[i]); if (bufObj) { - if ( (bufObj->Target == GL_ARRAY_BUFFER_ARB) - || (bufObj->Target == GL_ELEMENT_ARRAY_BUFFER_ARB) ) { - _mesa_BindBufferARB( bufObj->Target, 0 ); + /* unbind any vertex pointers bound to this buffer */ + GLuint j; + + ASSERT(bufObj->Name == ids[i]); + + if (ctx->Array.Vertex.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Vertex.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.Normal.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Normal.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.Color.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Color.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.SecondaryColor.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.SecondaryColor.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.FogCoord.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.FogCoord.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.Index.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.Index.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + if (ctx->Array.EdgeFlag.BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.EdgeFlag.BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + for (j = 0; j < MAX_TEXTURE_UNITS; j++) { + if (ctx->Array.TexCoord[j].BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.TexCoord[j].BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } + } + for (j = 0; j < VERT_ATTRIB_MAX; j++) { + if (ctx->Array.VertexAttrib[j].BufferObj == bufObj) { + bufObj->RefCount--; + ctx->Array.VertexAttrib[j].BufferObj = ctx->Array.NullBufferObj; + ctx->Array.NullBufferObj->RefCount++; + } } - else if (bufObj->Target == 0) { - /* The buffer object is not bound. - */ - } - else { - _mesa_problem(ctx, "bad target in glDeleteBufferARB"); - return; + + if (ctx->Array.ArrayBufferObj == bufObj) { + _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); + } + if (ctx->Array.ElementArrayBufferObj == bufObj) { + _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); + } + + if (ctx->Pack.BufferObj == bufObj) { + _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 ); + } + if (ctx->Unpack.BufferObj == bufObj) { + _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); } + + /* The ID is immediately freed for re-use */ + _mesa_remove_buffer_object(ctx, bufObj); bufObj->RefCount--; if (bufObj->RefCount <= 0) { - ASSERT(bufObj->Name != 0); - _mesa_remove_buffer_object(ctx, bufObj); + ASSERT(ctx->Array.ArrayBufferObj != bufObj); + ASSERT(ctx->Array.ElementArrayBufferObj != bufObj); + ASSERT(ctx->Array.Vertex.BufferObj != bufObj); ASSERT(ctx->Driver.DeleteBuffer); - (*ctx->Driver.DeleteBuffer)(ctx, bufObj); + ctx->Driver.DeleteBuffer(ctx, bufObj); } } } @@ -458,8 +658,7 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) * \param n Number of IDs to generate. * \param buffer Array of \c n locations to store the IDs. */ - -void +void GLAPIENTRY _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) { GET_CURRENT_CONTEXT(ctx); @@ -472,7 +671,7 @@ _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) return; } - if ( buffer == NULL ) { + if (!buffer) { return; } @@ -483,22 +682,19 @@ _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); - /* Return the buffer names */ - for (i=0;iDriver.NewBufferObject)( ctx, name, target ); - if ( bufObj != NULL ) { + if (!bufObj) { + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB"); return; } _mesa_save_buffer_object(ctx, bufObj); + buffer[i] = first + i; } _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); @@ -512,8 +708,7 @@ _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) * \return \c GL_TRUE if \c id is the name of a buffer object, * \c GL_FALSE otherwise. */ - -GLboolean +GLboolean GLAPIENTRY _mesa_IsBufferARB(GLuint id) { struct gl_buffer_object * bufObj; @@ -527,11 +722,11 @@ _mesa_IsBufferARB(GLuint id) bufObj = (struct gl_buffer_object *) _mesa_HashLookup(ctx->Shared->BufferObjects, id); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); - return (bufObj != NULL); + return bufObj ? GL_TRUE : GL_FALSE; } -void +void GLAPIENTRY _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, const GLvoid * data, GLenum usage) { @@ -561,18 +756,25 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, return; } - bufObj = _mesa_buffer_object_get_target( ctx, target, "BufferDataARB" ); - if ( bufObj == NULL ) { + bufObj = buffer_object_get_target( ctx, target, "BufferDataARB" ); + if (!bufObj || bufObj->Name ==0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB" ); return; } + if (bufObj->Pointer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer is mapped)" ); + return; + } + ASSERT(ctx->Driver.BufferData); /* Give the buffer object to the driver! may be null! */ (*ctx->Driver.BufferData)( ctx, target, size, data, usage, bufObj ); } -void + +void GLAPIENTRY _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid * data) { @@ -580,15 +782,19 @@ _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, struct gl_buffer_object *bufObj; ASSERT_OUTSIDE_BEGIN_END(ctx); - bufObj = _mesa_buffer_object_subdata_range_good( ctx, target, offset, size, - "BufferSubDataARB" ); - if ( bufObj != NULL ) { - ASSERT(ctx->Driver.BufferSubData); - (*ctx->Driver.BufferSubData)( ctx, target, offset, size, data, bufObj ); + bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, + "BufferSubDataARB" ); + if (!bufObj) { + /* error already recorded */ + return; } + + ASSERT(ctx->Driver.BufferSubData); + (*ctx->Driver.BufferSubData)( ctx, target, offset, size, data, bufObj ); } -void + +void GLAPIENTRY _mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data) { @@ -596,15 +802,19 @@ _mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, struct gl_buffer_object *bufObj; ASSERT_OUTSIDE_BEGIN_END(ctx); - bufObj = _mesa_buffer_object_subdata_range_good( ctx, target, offset, size, - "GetBufferSubDataARB" ); - if ( bufObj != NULL ) { - ASSERT(ctx->Driver.GetBufferSubData); - (*ctx->Driver.GetBufferSubData)( ctx, target, offset, size, data, bufObj ); + bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, + "GetBufferSubDataARB" ); + if (!bufObj) { + /* error already recorded */ + return; } + + ASSERT(ctx->Driver.GetBufferSubData); + (*ctx->Driver.GetBufferSubData)( ctx, target, offset, size, data, bufObj ); } -void * + +void * GLAPIENTRY _mesa_MapBufferARB(GLenum target, GLenum access) { GET_CURRENT_CONTEXT(ctx); @@ -622,27 +832,30 @@ _mesa_MapBufferARB(GLenum target, GLenum access) return NULL; } - bufObj = _mesa_buffer_object_get_target( ctx, target, - "MapBufferARB" ); - if ( bufObj == NULL ) { + bufObj = buffer_object_get_target( ctx, target, "MapBufferARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB" ); return NULL; } - if ( bufObj->pointer != NULL ) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB"); + if (bufObj->Pointer) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); return NULL; } ASSERT(ctx->Driver.MapBuffer); - bufObj->pointer = (*ctx->Driver.MapBuffer)( ctx, target, access, bufObj ); - if ( bufObj->pointer == NULL ) { + bufObj->Pointer = (*ctx->Driver.MapBuffer)( ctx, target, access, bufObj ); + if (!bufObj->Pointer) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)"); } - return bufObj->pointer; + bufObj->Access = access; + + return bufObj->Pointer; } -GLboolean + +GLboolean GLAPIENTRY _mesa_UnmapBufferARB(GLenum target) { GET_CURRENT_CONTEXT(ctx); @@ -650,52 +863,53 @@ _mesa_UnmapBufferARB(GLenum target) GLboolean status = GL_TRUE; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - - bufObj = _mesa_buffer_object_get_target( ctx, target, - "UnmapBufferARB" ); - if ( bufObj == NULL ) { + bufObj = buffer_object_get_target( ctx, target, "UnmapBufferARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" ); return GL_FALSE; } - if ( bufObj->pointer == NULL ) { + if (!bufObj->Pointer) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); return GL_FALSE; } - if ( ctx->Driver.UnmapBuffer != NULL ) { + if (ctx->Driver.UnmapBuffer) { status = (*ctx->Driver.UnmapBuffer)( ctx, target, bufObj ); } - bufObj->pointer = NULL; + bufObj->Access = GL_READ_WRITE_ARB; /* initial value, OK? */ + bufObj->Pointer = NULL; return status; } -void + +void GLAPIENTRY _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) { GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; ASSERT_OUTSIDE_BEGIN_END(ctx); - bufObj = _mesa_buffer_object_get_target( ctx, target, - "GetBufferParameterivARB" ); - if ( bufObj == NULL ) { + bufObj = buffer_object_get_target( ctx, target, "GetBufferParameterivARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" ); return; } switch (pname) { case GL_BUFFER_SIZE_ARB: - *params = bufObj->size; + *params = bufObj->Size; break; case GL_BUFFER_USAGE_ARB: - *params = bufObj->usage; + *params = bufObj->Usage; break; case GL_BUFFER_ACCESS_ARB: - *params = bufObj->access; + *params = bufObj->Access; break; case GL_BUFFER_MAPPED_ARB: - *params = (bufObj->pointer != NULL); + *params = (bufObj->Pointer != NULL); break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)"); @@ -703,7 +917,8 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) } } -void + +void GLAPIENTRY _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) { GET_CURRENT_CONTEXT(ctx); @@ -715,11 +930,11 @@ _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) return; } - bufObj = _mesa_buffer_object_get_target( ctx, target, - "GetBufferPointervARB" ); - if ( bufObj == NULL ) { + bufObj = buffer_object_get_target( ctx, target, "GetBufferPointervARB" ); + if (!bufObj || bufObj->Name == 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" ); return; } - *params = bufObj->pointer; + *params = bufObj->Pointer; }