Add MESA_FORMAT_XRGB8888_REV.
[mesa.git] / src / mesa / main / bufferobj.c
index d640f5358e54b6cc48c33f6c4ce0a4e3b7a31100..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;
 }
 
 
@@ -156,7 +160,7 @@ buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
       _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);
       return NULL;
    }
-   if (bufObj->Name == 0) {
+   if (!_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
       return NULL;
    }
@@ -165,7 +169,7 @@ buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
                  "%s(size + offset > buffer size)", caller);
       return NULL;
    }
-   if (bufObj->Pointer) {
+   if (_mesa_bufferobj_mapped(bufObj)) {
       /* Buffer is currently mapped */
       _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
       return NULL;
@@ -314,9 +318,10 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
  * \param usage   Hints about how the data will be used.
  * \param bufObj  Object to be used.
  *
+ * \return GL_TRUE for success, GL_FALSE for failure
  * \sa glBufferDataARB, dd_function_table::BufferData.
  */
-static void
+static GLboolean
 _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
                   const GLvoid * data, GLenum usage,
                   struct gl_buffer_object * bufObj )
@@ -334,6 +339,11 @@ _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
       if (data) {
         _mesa_memcpy( bufObj->Data, data, size );
       }
+
+      return GL_TRUE;
+   }
+   else {
+      return GL_FALSE;
    }
 }
 
@@ -423,11 +433,13 @@ _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
    (void) target;
    (void) access;
    /* Just return a direct pointer to the data */
-   if (bufObj->Pointer) {
+   if (_mesa_bufferobj_mapped(bufObj)) {
       /* already mapped! */
       return NULL;
    }
    bufObj->Pointer = bufObj->Data;
+   bufObj->Length = bufObj->Size;
+   bufObj->Offset = 0;
    return bufObj->Pointer;
 }
 
@@ -443,11 +455,13 @@ _mesa_buffer_map_range( GLcontext *ctx, GLenum target, GLintptr offset,
 {
    (void) ctx;
    (void) target;
-   (void) access;
-   (void) length;
-   assert(!bufObj->Pointer);
+   assert(!_mesa_bufferobj_mapped(bufObj));
    /* Just return a direct pointer to the data */
-   return bufObj->Data + offset;
+   bufObj->Pointer = bufObj->Data + offset;
+   bufObj->Length = length;
+   bufObj->Offset = offset;
+   bufObj->AccessFlags = access;
+   return bufObj->Pointer;
 }
 
 
@@ -484,6 +498,9 @@ _mesa_buffer_unmap( GLcontext *ctx, GLenum target,
    (void) target;
    /* XXX we might assert here that bufObj->Pointer is non-null */
    bufObj->Pointer = NULL;
+   bufObj->Length = 0;
+   bufObj->Offset = 0;
+   bufObj->AccessFlags = 0x0;
    return GL_TRUE;
 }
 
@@ -502,8 +519,8 @@ _mesa_copy_buffer_subdata(GLcontext *ctx,
    GLubyte *srcPtr, *dstPtr;
 
    /* buffer should not already be mapped */
-   assert(!src->Pointer);
-   assert(!dst->Pointer);
+   assert(!_mesa_bufferobj_mapped(src));
+   assert(!_mesa_bufferobj_mapped(dst));
 
    srcPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_READ_BUFFER,
                                               GL_READ_ONLY, src);
@@ -539,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)
@@ -547,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 */
 
@@ -645,6 +637,8 @@ _mesa_update_default_objects_buffer_objects(GLcontext *ctx)
  * currently mapped.  Whoever calls this function should check for that.
  * Remember, we can't use a PBO when it's mapped!
  *
+ * If we're not using a PBO, this is a no-op.
+ *
  * \param width  width of image to read/write
  * \param height  height of image to read/write
  * \param depth  depth of image to read/write
@@ -663,7 +657,8 @@ _mesa_validate_pbo_access(GLuint dimensions,
    GLvoid *start, *end;
    const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
 
-   ASSERT(pack->BufferObj->Name != 0);
+   if (!_mesa_is_bufferobj(pack->BufferObj))
+      return GL_TRUE;  /* no PBO, OK */
 
    if (pack->BufferObj->Size == 0)
       /* no buffer! */
@@ -695,21 +690,22 @@ _mesa_validate_pbo_access(GLuint dimensions,
 
 
 /**
- * If the source of glBitmap data is a PBO, check that we won't read out
- * of buffer bounds, then map the buffer.
- * If not sourcing from a PBO, just return the bitmap pointer.
- * This is a helper function for (some) drivers.
- * Return NULL if error.
- * If non-null return, must call _mesa_unmap_bitmap_pbo() when done.
+ * For commands that read from a PBO (glDrawPixels, glTexImage,
+ * glPolygonStipple, etc), if we're reading from a PBO, map it read-only
+ * and return the pointer into the PBO.  If we're not reading from a
+ * PBO, return \p src as-is.
+ * If non-null return, must call _mesa_unmap_pbo_source() when done.
+ *
+ * \return NULL if error, else pointer to start of data
  */
-const GLubyte *
-_mesa_map_bitmap_pbo(GLcontext *ctx,
+const GLvoid *
+_mesa_map_pbo_source(GLcontext *ctx,
                      const struct gl_pixelstore_attrib *unpack,
-                     const GLubyte *bitmap)
+                     const GLvoid *src)
 {
    const GLubyte *buf;
 
-   if (unpack->BufferObj->Name) {
+   if (_mesa_is_bufferobj(unpack->BufferObj)) {
       /* unpack from PBO */
       buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                                               GL_READ_ONLY_ARB,
@@ -717,11 +713,11 @@ _mesa_map_bitmap_pbo(GLcontext *ctx,
       if (!buf)
          return NULL;
 
-      buf = ADD_POINTERS(buf, bitmap);
+      buf = ADD_POINTERS(buf, src);
    }
    else {
       /* unpack from normal memory */
-      buf = bitmap;
+      buf = src;
    }
 
    return buf;
@@ -729,57 +725,55 @@ _mesa_map_bitmap_pbo(GLcontext *ctx,
 
 
 /**
- * Counterpart to _mesa_map_bitmap_pbo()
- * This is a helper function for (some) drivers.
- */
-void
-_mesa_unmap_bitmap_pbo(GLcontext *ctx,
-                       const struct gl_pixelstore_attrib *unpack)
-{
-   if (unpack->BufferObj->Name) {
-      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                              unpack->BufferObj);
-   }
-}
-
-
-/**
- * \sa _mesa_map_bitmap_pbo
+ * 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_drawpix_pbo(GLcontext *ctx,
-                      const struct gl_pixelstore_attrib *unpack,
-                      const GLvoid *pixels)
+_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)
 {
-   const GLvoid *buf;
+   ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3);
 
-   if (unpack->BufferObj->Name) {
-      /* unpack from PBO */
-      buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
-                                              GL_READ_ONLY_ARB,
-                                              unpack->BufferObj);
-      if (!buf)
-         return NULL;
+   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+      /* non-PBO access: no validation to be done */
+      return ptr;
+   }
 
-      buf = ADD_POINTERS(buf, pixels);
+   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;
    }
-   else {
-      /* unpack from normal memory */
-      buf = pixels;
+
+   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;
    }
 
-   return buf;
+   ptr = _mesa_map_pbo_source(ctx, unpack, ptr);
+   return ptr;
 }
 
 
 /**
- * \sa _mesa_unmap_bitmap_pbo
+ * Counterpart to _mesa_map_pbo_source()
  */
 void
-_mesa_unmap_drawpix_pbo(GLcontext *ctx,
-                        const struct gl_pixelstore_attrib *unpack)
+_mesa_unmap_pbo_source(GLcontext *ctx,
+                       const struct gl_pixelstore_attrib *unpack)
 {
-   if (unpack->BufferObj->Name) {
+   ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */
+   if (_mesa_is_bufferobj(unpack->BufferObj)) {
       ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
                               unpack->BufferObj);
    }
@@ -787,18 +781,21 @@ _mesa_unmap_drawpix_pbo(GLcontext *ctx,
 
 
 /**
- * If PBO is bound, map the buffer, return dest pointer in mapped buffer.
- * Call _mesa_unmap_readpix_pbo() when finished
- * \return NULL if error
+ * For commands that write to a PBO (glReadPixels, glGetColorTable, etc),
+ * if we're writing to a PBO, map it write-only and return the pointer
+ * into the PBO.  If we're not writing to a PBO, return \p dst as-is.
+ * If non-null return, must call _mesa_unmap_pbo_dest() when done.
+ *
+ * \return NULL if error, else pointer to start of data
  */
 void *
-_mesa_map_readpix_pbo(GLcontext *ctx,
-                      const struct gl_pixelstore_attrib *pack,
-                      GLvoid *dest)
+_mesa_map_pbo_dest(GLcontext *ctx,
+                   const struct gl_pixelstore_attrib *pack,
+                   GLvoid *dest)
 {
    void *buf;
 
-   if (pack->BufferObj->Name) {
+   if (_mesa_is_bufferobj(pack->BufferObj)) {
       /* pack into PBO */
       buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                                               GL_WRITE_ONLY_ARB,
@@ -818,13 +815,55 @@ _mesa_map_readpix_pbo(GLcontext *ctx,
 
 
 /**
- * Counterpart to _mesa_map_readpix_pbo()
+ * 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()
  */
 void
-_mesa_unmap_readpix_pbo(GLcontext *ctx,
-                        const struct gl_pixelstore_attrib *pack)
+_mesa_unmap_pbo_dest(GLcontext *ctx,
+                     const struct gl_pixelstore_attrib *pack)
 {
-   if (pack->BufferObj->Name) {
+   ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */
+   if (_mesa_is_bufferobj(pack->BufferObj)) {
       ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
    }
 }
@@ -932,7 +971,7 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
 
          ASSERT(bufObj->Name == ids[i]);
 
-         if (bufObj->Pointer) {
+         if (_mesa_bufferobj_mapped(bufObj)) {
             /* if mapped, unmap it now */
             ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
             bufObj->AccessFlags = DEFAULT_ACCESS;
@@ -1086,22 +1125,20 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
       _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" );
       return;
    }
-   if (bufObj->Name == 0) {
+   if (!_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer 0)" );
       return;
    }
    
-   if (bufObj->Pointer) {
+   if (_mesa_bufferobj_mapped(bufObj)) {
       /* Unmap the existing buffer.  We'll replace it now.  Not an error. */
       ctx->Driver.UnmapBuffer(ctx, target, bufObj);
       bufObj->AccessFlags = DEFAULT_ACCESS;
-      bufObj->Pointer = NULL;
+      ASSERT(bufObj->Pointer == NULL);
    }  
 
    FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
 
-   ASSERT(ctx->Driver.BufferData);
-
    bufObj->Written = GL_TRUE;
 
 #ifdef VBO_DEBUG
@@ -1112,8 +1149,11 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
 #ifdef BOUNDS_CHECK
    size += 100;
 #endif
-   /* Give the buffer object to the driver!  <data> may be null! */
-   ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj );
+
+   ASSERT(ctx->Driver.BufferData);
+   if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()");
+   }
 }
 
 
@@ -1165,6 +1205,8 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
    GET_CURRENT_CONTEXT(ctx);
    struct gl_buffer_object * bufObj;
    GLbitfield accessFlags;
+   void *map;
+
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
 
    switch (access) {
@@ -1187,24 +1229,31 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
       _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" );
       return NULL;
    }
-   if (bufObj->Name == 0) {
+   if (!_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(buffer 0)" );
       return NULL;
    }
-   if (bufObj->Pointer) {
+   if (_mesa_bufferobj_mapped(bufObj)) {
       _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) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
+   map = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
+   if (!map) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
+      return NULL;
+   }
+   else {
+      /* The driver callback should have set these fields.
+       * This is important because other modules (like VBO) might call
+       * the driver function directly.
+       */
+      ASSERT(bufObj->Pointer == map);
+      ASSERT(bufObj->Length == bufObj->Size);
+      ASSERT(bufObj->Offset == 0);
+      bufObj->AccessFlags = accessFlags;
    }
-
-   bufObj->AccessFlags = accessFlags;
-   bufObj->Offset = 0;
-   bufObj->Length = bufObj->Size;
 
    if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
       bufObj->Written = GL_TRUE;
@@ -1248,11 +1297,11 @@ _mesa_UnmapBufferARB(GLenum target)
       _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" );
       return GL_FALSE;
    }
-   if (bufObj->Name == 0) {
+   if (!_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" );
       return GL_FALSE;
    }
-   if (!bufObj->Pointer) {
+   if (!_mesa_bufferobj_mapped(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
       return GL_FALSE;
    }
@@ -1295,9 +1344,9 @@ _mesa_UnmapBufferARB(GLenum target)
 
    status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
    bufObj->AccessFlags = DEFAULT_ACCESS;
-   bufObj->Pointer = NULL;
-   bufObj->Offset = 0;
-   bufObj->Length = 0;
+   ASSERT(bufObj->Pointer == NULL);
+   ASSERT(bufObj->Offset == 0);
+   ASSERT(bufObj->Length == 0);
 
    return status;
 }
@@ -1315,7 +1364,7 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
       _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" );
       return;
    }
-   if (bufObj->Name == 0) {
+   if (!_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" );
       return;
    }
@@ -1331,7 +1380,7 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
          *params = simplified_access_mode(bufObj->AccessFlags);
          break;
       case GL_BUFFER_MAPPED_ARB:
-         *params = (bufObj->Pointer != NULL);
+         *params = _mesa_bufferobj_mapped(bufObj);
          break;
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)");
@@ -1357,7 +1406,7 @@ _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" );
       return;
    }
-   if (bufObj->Name == 0) {
+   if (!_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" );
       return;
    }
@@ -1376,26 +1425,26 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
    src = get_buffer(ctx, readTarget);
-   if (!src || src->Name == 0) {
+   if (!src || !_mesa_is_bufferobj(src)) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glCopyBuffserSubData(readTarget = 0x%x)", readTarget);
       return;
    }
 
    dst = get_buffer(ctx, writeTarget);
-   if (!dst || dst->Name == 0) {
+   if (!dst || !_mesa_is_bufferobj(dst)) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glCopyBuffserSubData(writeTarget = 0x%x)", writeTarget);
       return;
    }
 
-   if (src->Pointer) {
+   if (_mesa_bufferobj_mapped(src)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glCopyBuffserSubData(readBuffer is mapped)");
       return;
    }
 
-   if (dst->Pointer) {
+   if (_mesa_bufferobj_mapped(dst)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glCopyBuffserSubData(writeBuffer is mapped)");
       return;
@@ -1455,6 +1504,8 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
 {
    GET_CURRENT_CONTEXT(ctx);
    struct gl_buffer_object *bufObj;
+   void *map;
+
    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
 
    if (!ctx->Extensions.ARB_map_buffer_range) {
@@ -1499,7 +1550,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
    }
 
    bufObj = get_buffer(ctx, target);
-   if (!bufObj || bufObj->Name == 0) {
+   if (!bufObj || !_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_ENUM,
                   "glMapBufferRange(target = 0x%x)", target);
       return NULL;
@@ -1511,21 +1562,30 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
       return NULL;
    }
 
-   if (bufObj->Pointer) {
+   if (_mesa_bufferobj_mapped(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glMapBufferRange(buffer already mapped)");
       return NULL;
    }
       
    ASSERT(ctx->Driver.MapBufferRange);
-   bufObj->Pointer = ctx->Driver.MapBufferRange(ctx, target, offset, length,
-                                                access, bufObj);
-
-   bufObj->Offset = offset;
-   bufObj->Length = length;
-   bufObj->AccessFlags = access;
+   map = ctx->Driver.MapBufferRange(ctx, target, offset, length,
+                                    access, bufObj);
+   if (!map) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
+   }
+   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->Pointer == map);
+      ASSERT(bufObj->Length == length);
+      ASSERT(bufObj->Offset == offset);
+      ASSERT(bufObj->AccessFlags == access);
+   }
 
-   return bufObj->Pointer;
+   return map;
 }
 
 
@@ -1564,13 +1624,13 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
       return;
    }
 
-   if (bufObj->Name == 0) {
+   if (!_mesa_is_bufferobj(bufObj)) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glMapBufferRange(current buffer is 0)");
       return;
    }
 
-   if (!bufObj->Pointer) {
+   if (!_mesa_bufferobj_mapped(bufObj)) {
       /* buffer is not mapped */
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glMapBufferRange(buffer is not mapped)");