Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Mesa 3-D graphics library |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 3 | * Version: 7.5 |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 4 | * |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 5 | * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 6 | * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved. |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 7 | * |
| 8 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 9 | * copy of this software and associated documentation files (the "Software"), |
| 10 | * to deal in the Software without restriction, including without limitation |
| 11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 12 | * and/or sell copies of the Software, and to permit persons to whom the |
| 13 | * Software is furnished to do so, subject to the following conditions: |
| 14 | * |
| 15 | * The above copyright notice and this permission notice shall be included |
| 16 | * in all copies or substantial portions of the Software. |
| 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 21 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| 22 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 24 | */ |
| 25 | |
| 26 | |
| 27 | /** |
| 28 | * \file bufferobj.c |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 29 | * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions. |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 30 | * \author Brian Paul, Ian Romanick |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 31 | */ |
| 32 | |
| 33 | |
| 34 | #include "glheader.h" |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 35 | #include "hash.h" |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 36 | #include "imports.h" |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 37 | #include "image.h" |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 38 | #include "context.h" |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 39 | #include "bufferobj.h" |
| 40 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 41 | |
Brian Paul | 6c72bc8 | 2008-09-25 11:46:27 -0600 | [diff] [blame] | 42 | #ifdef FEATURE_OES_mapbuffer |
| 43 | #define DEFAULT_ACCESS GL_WRITE_ONLY; |
| 44 | #else |
| 45 | #define DEFAULT_ACCESS GL_READ_WRITE; |
| 46 | #endif |
| 47 | |
| 48 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 49 | /** |
| 50 | * Get the buffer object bound to the specified target in a GL context. |
| 51 | * |
| 52 | * \param ctx GL context |
| 53 | * \param target Buffer object target to be retrieved. Currently this must |
| 54 | * be either \c GL_ARRAY_BUFFER or \c GL_ELEMENT_ARRAY_BUFFER. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 55 | * \return A pointer to the buffer object bound to \c target in the |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 56 | * specified context or \c NULL if \c target is invalid. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 57 | */ |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 58 | static INLINE struct gl_buffer_object * |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 59 | get_buffer(GLcontext *ctx, GLenum target) |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 60 | { |
| 61 | struct gl_buffer_object * bufObj = NULL; |
| 62 | |
| 63 | switch (target) { |
| 64 | case GL_ARRAY_BUFFER_ARB: |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 65 | bufObj = ctx->Array.ArrayBufferObj; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 66 | break; |
| 67 | case GL_ELEMENT_ARRAY_BUFFER_ARB: |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 68 | bufObj = ctx->Array.ElementArrayBufferObj; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 69 | break; |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 70 | case GL_PIXEL_PACK_BUFFER_EXT: |
| 71 | bufObj = ctx->Pack.BufferObj; |
| 72 | break; |
| 73 | case GL_PIXEL_UNPACK_BUFFER_EXT: |
| 74 | bufObj = ctx->Unpack.BufferObj; |
| 75 | break; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 76 | default: |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 77 | /* error must be recorded by caller */ |
Brian Paul | 4b6f6e1 | 2003-10-14 14:49:39 +0000 | [diff] [blame] | 78 | return NULL; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 79 | } |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 80 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 81 | /* bufObj should point to NullBufferObj or a user-created buffer object */ |
| 82 | ASSERT(bufObj); |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 83 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 84 | return bufObj; |
| 85 | } |
| 86 | |
| 87 | |
| 88 | /** |
| 89 | * Tests the subdata range parameters and sets the GL error code for |
| 90 | * \c glBufferSubDataARB and \c glGetBufferSubDataARB. |
| 91 | * |
| 92 | * \param ctx GL context. |
| 93 | * \param target Buffer object target on which to operate. |
| 94 | * \param offset Offset of the first byte of the subdata range. |
| 95 | * \param size Size, in bytes, of the subdata range. |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 96 | * \param caller Name of calling function for recording errors. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 97 | * \return A pointer to the buffer object bound to \c target in the |
| 98 | * specified context or \c NULL if any of the parameter or state |
| 99 | * conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB |
| 100 | * are invalid. |
| 101 | * |
| 102 | * \sa glBufferSubDataARB, glGetBufferSubDataARB |
| 103 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 104 | static struct gl_buffer_object * |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 105 | buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, |
| 106 | GLintptrARB offset, GLsizeiptrARB size, |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 107 | const char *caller ) |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 108 | { |
| 109 | struct gl_buffer_object *bufObj; |
| 110 | |
| 111 | if (size < 0) { |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 112 | _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 113 | return NULL; |
| 114 | } |
| 115 | |
| 116 | if (offset < 0) { |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 117 | _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 118 | return NULL; |
| 119 | } |
| 120 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 121 | bufObj = get_buffer(ctx, target); |
| 122 | if (!bufObj) { |
| 123 | _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 124 | return NULL; |
| 125 | } |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 126 | if (bufObj->Name == 0) { |
| 127 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); |
| 128 | return NULL; |
| 129 | } |
Brian | 7e85b0a | 2007-01-23 12:50:08 -0700 | [diff] [blame] | 130 | if (offset + size > bufObj->Size) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 131 | _mesa_error(ctx, GL_INVALID_VALUE, |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 132 | "%s(size + offset > buffer size)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 133 | return NULL; |
| 134 | } |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 135 | if (bufObj->Pointer) { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 136 | /* Buffer is currently mapped */ |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 137 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 138 | return NULL; |
| 139 | } |
| 140 | |
| 141 | return bufObj; |
| 142 | } |
| 143 | |
| 144 | |
| 145 | /** |
| 146 | * Allocate and initialize a new buffer object. |
| 147 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 148 | * Default callback for the \c dd_function_table::NewBufferObject() hook. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 149 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 150 | struct gl_buffer_object * |
| 151 | _mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target ) |
| 152 | { |
| 153 | struct gl_buffer_object *obj; |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 154 | |
| 155 | (void) ctx; |
| 156 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 157 | obj = MALLOC_STRUCT(gl_buffer_object); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 158 | _mesa_initialize_buffer_object(obj, name, target); |
| 159 | return obj; |
| 160 | } |
| 161 | |
| 162 | |
| 163 | /** |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 164 | * Delete a buffer object. |
| 165 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 166 | * Default callback for the \c dd_function_table::DeleteBuffer() hook. |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 167 | */ |
| 168 | void |
| 169 | _mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) |
| 170 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 171 | (void) ctx; |
| 172 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 173 | if (bufObj->Data) |
| 174 | _mesa_free(bufObj->Data); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 175 | |
| 176 | /* assign strange values here to help w/ debugging */ |
| 177 | bufObj->RefCount = -1000; |
| 178 | bufObj->Name = ~0; |
| 179 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 180 | _mesa_free(bufObj); |
| 181 | } |
| 182 | |
| 183 | |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 184 | |
| 185 | /** |
| 186 | * Set ptr to bufObj w/ reference counting. |
| 187 | */ |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 188 | void |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 189 | _mesa_reference_buffer_object(GLcontext *ctx, |
| 190 | struct gl_buffer_object **ptr, |
| 191 | struct gl_buffer_object *bufObj) |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 192 | { |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 193 | if (*ptr == bufObj) |
| 194 | return; |
| 195 | |
| 196 | if (*ptr) { |
Brian Paul | 105c852 | 2009-05-07 13:10:48 -0600 | [diff] [blame^] | 197 | /* Unreference the old buffer */ |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 198 | GLboolean deleteFlag = GL_FALSE; |
| 199 | struct gl_buffer_object *oldObj = *ptr; |
| 200 | |
| 201 | /*_glthread_LOCK_MUTEX(oldObj->Mutex);*/ |
| 202 | ASSERT(oldObj->RefCount > 0); |
| 203 | oldObj->RefCount--; |
| 204 | #if 0 |
| 205 | printf("BufferObj %p %d DECR to %d\n", |
| 206 | (void *) oldObj, oldObj->Name, oldObj->RefCount); |
| 207 | #endif |
| 208 | deleteFlag = (oldObj->RefCount == 0); |
| 209 | /*_glthread_UNLOCK_MUTEX(oldObj->Mutex);*/ |
| 210 | |
| 211 | if (deleteFlag) { |
| 212 | |
| 213 | /* some sanity checking: don't delete a buffer still in use */ |
Brian Paul | d36f4ef | 2008-09-15 09:07:32 -0600 | [diff] [blame] | 214 | #if 0 |
| 215 | /* unfortunately, these tests are invalid during context tear-down */ |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 216 | ASSERT(ctx->Array.ArrayBufferObj != bufObj); |
| 217 | ASSERT(ctx->Array.ElementArrayBufferObj != bufObj); |
| 218 | ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj); |
Brian Paul | d36f4ef | 2008-09-15 09:07:32 -0600 | [diff] [blame] | 219 | #endif |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 220 | |
Brian Paul | d36f4ef | 2008-09-15 09:07:32 -0600 | [diff] [blame] | 221 | ASSERT(ctx->Driver.DeleteBuffer); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 222 | ctx->Driver.DeleteBuffer(ctx, oldObj); |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 223 | } |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 224 | |
| 225 | *ptr = NULL; |
| 226 | } |
| 227 | ASSERT(!*ptr); |
| 228 | |
| 229 | if (bufObj) { |
Brian Paul | 105c852 | 2009-05-07 13:10:48 -0600 | [diff] [blame^] | 230 | /* reference new buffer */ |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 231 | /*_glthread_LOCK_MUTEX(tex->Mutex);*/ |
| 232 | if (bufObj->RefCount == 0) { |
| 233 | /* this buffer's being deleted (look just above) */ |
| 234 | /* Not sure this can every really happen. Warn if it does. */ |
| 235 | _mesa_problem(NULL, "referencing deleted buffer object"); |
| 236 | *ptr = NULL; |
| 237 | } |
| 238 | else { |
| 239 | bufObj->RefCount++; |
| 240 | #if 0 |
| 241 | printf("BufferObj %p %d INCR to %d\n", |
| 242 | (void *) bufObj, bufObj->Name, bufObj->RefCount); |
| 243 | #endif |
| 244 | *ptr = bufObj; |
| 245 | } |
| 246 | /*_glthread_UNLOCK_MUTEX(tex->Mutex);*/ |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 247 | } |
| 248 | } |
| 249 | |
| 250 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 251 | /** |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 252 | * Initialize a buffer object to default values. |
| 253 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 254 | void |
| 255 | _mesa_initialize_buffer_object( struct gl_buffer_object *obj, |
| 256 | GLuint name, GLenum target ) |
| 257 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 258 | (void) target; |
| 259 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 260 | _mesa_bzero(obj, sizeof(struct gl_buffer_object)); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 261 | obj->RefCount = 1; |
| 262 | obj->Name = name; |
Brian Paul | 85ad44b | 2004-02-13 14:04:26 +0000 | [diff] [blame] | 263 | obj->Usage = GL_STATIC_DRAW_ARB; |
Brian Paul | 6c72bc8 | 2008-09-25 11:46:27 -0600 | [diff] [blame] | 264 | obj->Access = DEFAULT_ACCESS; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 265 | } |
| 266 | |
| 267 | |
| 268 | /** |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 269 | * Allocate space for and store data in a buffer object. Any data that was |
| 270 | * previously stored in the buffer object is lost. If \c data is \c NULL, |
| 271 | * memory will be allocated, but no copy will occur. |
| 272 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 273 | * This is the default callback for \c dd_function_table::BufferData() |
| 274 | * Note that all GL error checking will have been done already. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 275 | * |
| 276 | * \param ctx GL context. |
| 277 | * \param target Buffer object target on which to operate. |
| 278 | * \param size Size, in bytes, of the new data store. |
| 279 | * \param data Pointer to the data to store in the buffer object. This |
| 280 | * pointer may be \c NULL. |
| 281 | * \param usage Hints about how the data will be used. |
| 282 | * \param bufObj Object to be used. |
| 283 | * |
| 284 | * \sa glBufferDataARB, dd_function_table::BufferData. |
| 285 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 286 | void |
| 287 | _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, |
| 288 | const GLvoid * data, GLenum usage, |
| 289 | struct gl_buffer_object * bufObj ) |
| 290 | { |
| 291 | void * new_data; |
| 292 | |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 293 | (void) ctx; (void) target; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 294 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 295 | new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size ); |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 296 | if (new_data) { |
Brian Paul | e4fcea2 | 2003-09-19 15:38:15 +0000 | [diff] [blame] | 297 | bufObj->Data = (GLubyte *) new_data; |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 298 | bufObj->Size = size; |
| 299 | bufObj->Usage = usage; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 300 | |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 301 | if (data) { |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 302 | _mesa_memcpy( bufObj->Data, data, size ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 303 | } |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | |
| 308 | /** |
| 309 | * Replace data in a subrange of buffer object. If the data range |
| 310 | * specified by \c size + \c offset extends beyond the end of the buffer or |
| 311 | * if \c data is \c NULL, no copy is performed. |
| 312 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 313 | * This is the default callback for \c dd_function_table::BufferSubData() |
| 314 | * Note that all GL error checking will have been done already. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 315 | * |
| 316 | * \param ctx GL context. |
| 317 | * \param target Buffer object target on which to operate. |
| 318 | * \param offset Offset of the first byte to be modified. |
| 319 | * \param size Size, in bytes, of the data range. |
| 320 | * \param data Pointer to the data to store in the buffer object. |
| 321 | * \param bufObj Object to be used. |
| 322 | * |
| 323 | * \sa glBufferSubDataARB, dd_function_table::BufferSubData. |
| 324 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 325 | void |
| 326 | _mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, |
| 327 | GLsizeiptrARB size, const GLvoid * data, |
| 328 | struct gl_buffer_object * bufObj ) |
| 329 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 330 | (void) ctx; (void) target; |
| 331 | |
Brian Paul | 76785cb | 2006-09-21 22:59:50 +0000 | [diff] [blame] | 332 | /* this should have been caught in _mesa_BufferSubData() */ |
Brian | 7e85b0a | 2007-01-23 12:50:08 -0700 | [diff] [blame] | 333 | ASSERT(size + offset <= bufObj->Size); |
Brian Paul | 76785cb | 2006-09-21 22:59:50 +0000 | [diff] [blame] | 334 | |
| 335 | if (bufObj->Data) { |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 336 | _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 337 | } |
| 338 | } |
| 339 | |
| 340 | |
| 341 | /** |
| 342 | * Retrieve data from a subrange of buffer object. If the data range |
| 343 | * specified by \c size + \c offset extends beyond the end of the buffer or |
| 344 | * if \c data is \c NULL, no copy is performed. |
| 345 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 346 | * This is the default callback for \c dd_function_table::GetBufferSubData() |
| 347 | * Note that all GL error checking will have been done already. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 348 | * |
| 349 | * \param ctx GL context. |
| 350 | * \param target Buffer object target on which to operate. |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 351 | * \param offset Offset of the first byte to be fetched. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 352 | * \param size Size, in bytes, of the data range. |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 353 | * \param data Destination for data |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 354 | * \param bufObj Object to be used. |
| 355 | * |
| 356 | * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData. |
| 357 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 358 | void |
| 359 | _mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, |
| 360 | GLsizeiptrARB size, GLvoid * data, |
| 361 | struct gl_buffer_object * bufObj ) |
| 362 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 363 | (void) ctx; (void) target; |
| 364 | |
Brian Paul | c1f2f90 | 2005-03-03 02:05:33 +0000 | [diff] [blame] | 365 | if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) { |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 366 | _mesa_memcpy( data, (GLubyte *) bufObj->Data + offset, size ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 367 | } |
| 368 | } |
| 369 | |
| 370 | |
| 371 | /** |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 372 | * Default callback for \c dd_function_tabel::MapBuffer(). |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 373 | * |
Brian Paul | 76785cb | 2006-09-21 22:59:50 +0000 | [diff] [blame] | 374 | * The function parameters will have been already tested for errors. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 375 | * |
| 376 | * \param ctx GL context. |
| 377 | * \param target Buffer object target on which to operate. |
| 378 | * \param access Information about how the buffer will be accessed. |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 379 | * \param bufObj Object to be mapped. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 380 | * \return A pointer to the object's internal data store that can be accessed |
| 381 | * by the processor |
| 382 | * |
| 383 | * \sa glMapBufferARB, dd_function_table::MapBuffer |
| 384 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 385 | void * |
| 386 | _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access, |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 387 | struct gl_buffer_object *bufObj ) |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 388 | { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 389 | (void) ctx; |
| 390 | (void) target; |
| 391 | (void) access; |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 392 | /* Just return a direct pointer to the data */ |
| 393 | if (bufObj->Pointer) { |
| 394 | /* already mapped! */ |
| 395 | return NULL; |
| 396 | } |
| 397 | bufObj->Pointer = bufObj->Data; |
| 398 | return bufObj->Pointer; |
| 399 | } |
| 400 | |
| 401 | |
| 402 | /** |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 403 | * Default callback for \c dd_function_table::MapBuffer(). |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 404 | * |
| 405 | * The input parameters will have been already tested for errors. |
| 406 | * |
| 407 | * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer |
| 408 | */ |
| 409 | GLboolean |
| 410 | _mesa_buffer_unmap( GLcontext *ctx, GLenum target, |
| 411 | struct gl_buffer_object *bufObj ) |
| 412 | { |
| 413 | (void) ctx; |
| 414 | (void) target; |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 415 | /* XXX we might assert here that bufObj->Pointer is non-null */ |
| 416 | bufObj->Pointer = NULL; |
| 417 | return GL_TRUE; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 418 | } |
| 419 | |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 420 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 421 | /** |
| 422 | * Initialize the state associated with buffer objects |
| 423 | */ |
| 424 | void |
| 425 | _mesa_init_buffer_objects( GLcontext *ctx ) |
| 426 | { |
Brian Paul | 2020278 | 2004-02-11 22:06:05 +0000 | [diff] [blame] | 427 | /* Allocate the default buffer object and set refcount so high that |
| 428 | * it never gets deleted. |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 429 | * XXX with recent/improved refcounting this may not longer be needed. |
Brian Paul | 2020278 | 2004-02-11 22:06:05 +0000 | [diff] [blame] | 430 | */ |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 431 | ctx->Array.NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0); |
Brian Paul | 2020278 | 2004-02-11 22:06:05 +0000 | [diff] [blame] | 432 | if (ctx->Array.NullBufferObj) |
| 433 | ctx->Array.NullBufferObj->RefCount = 1000; |
| 434 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 435 | ctx->Array.ArrayBufferObj = ctx->Array.NullBufferObj; |
| 436 | ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj; |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 437 | } |
| 438 | |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 439 | |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 440 | /** |
| 441 | * Bind the specified target to buffer for the specified context. |
| 442 | */ |
| 443 | static void |
| 444 | bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer) |
| 445 | { |
| 446 | struct gl_buffer_object *oldBufObj; |
| 447 | struct gl_buffer_object *newBufObj = NULL; |
| 448 | struct gl_buffer_object **bindTarget = NULL; |
| 449 | |
| 450 | switch (target) { |
| 451 | case GL_ARRAY_BUFFER_ARB: |
| 452 | bindTarget = &ctx->Array.ArrayBufferObj; |
| 453 | break; |
| 454 | case GL_ELEMENT_ARRAY_BUFFER_ARB: |
| 455 | bindTarget = &ctx->Array.ElementArrayBufferObj; |
| 456 | break; |
| 457 | case GL_PIXEL_PACK_BUFFER_EXT: |
| 458 | bindTarget = &ctx->Pack.BufferObj; |
| 459 | break; |
| 460 | case GL_PIXEL_UNPACK_BUFFER_EXT: |
| 461 | bindTarget = &ctx->Unpack.BufferObj; |
| 462 | break; |
| 463 | default: |
| 464 | _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)"); |
| 465 | return; |
| 466 | } |
| 467 | |
| 468 | /* Get pointer to old buffer object (to be unbound) */ |
| 469 | oldBufObj = get_buffer(ctx, target); |
| 470 | if (oldBufObj && oldBufObj->Name == buffer) |
| 471 | return; /* rebinding the same buffer object- no change */ |
| 472 | |
| 473 | /* |
| 474 | * Get pointer to new buffer object (newBufObj) |
| 475 | */ |
| 476 | if (buffer == 0) { |
| 477 | /* The spec says there's not a buffer object named 0, but we use |
| 478 | * one internally because it simplifies things. |
| 479 | */ |
| 480 | newBufObj = ctx->Array.NullBufferObj; |
| 481 | } |
| 482 | else { |
| 483 | /* non-default buffer object */ |
| 484 | newBufObj = _mesa_lookup_bufferobj(ctx, buffer); |
| 485 | if (!newBufObj) { |
| 486 | /* if this is a new buffer object id, allocate a buffer object now */ |
| 487 | ASSERT(ctx->Driver.NewBufferObject); |
| 488 | newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target); |
| 489 | if (!newBufObj) { |
| 490 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); |
| 491 | return; |
| 492 | } |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 493 | _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj); |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 494 | } |
| 495 | } |
| 496 | |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 497 | /* bind new buffer */ |
| 498 | _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 499 | |
| 500 | /* Pass BindBuffer call to device driver */ |
| 501 | if (ctx->Driver.BindBuffer && newBufObj) |
| 502 | ctx->Driver.BindBuffer( ctx, target, newBufObj ); |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 503 | } |
| 504 | |
| 505 | |
| 506 | /** |
| 507 | * Update the default buffer objects in the given context to reference those |
| 508 | * specified in the shared state and release those referencing the old |
| 509 | * shared state. |
| 510 | */ |
| 511 | void |
| 512 | _mesa_update_default_objects_buffer_objects(GLcontext *ctx) |
| 513 | { |
| 514 | /* Bind the NullBufferObj to remove references to those |
| 515 | * in the shared context hash table. |
| 516 | */ |
| 517 | bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0); |
| 518 | bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0); |
| 519 | bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0); |
| 520 | bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0); |
| 521 | } |
| 522 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 523 | |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 524 | /** |
| 525 | * When we're about to read pixel data out of a PBO (via glDrawPixels, |
| 526 | * glTexImage, etc) or write data into a PBO (via glReadPixels, |
| 527 | * glGetTexImage, etc) we call this function to check that we're not |
| 528 | * going to read out of bounds. |
| 529 | * |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 530 | * XXX This would also be a convenient time to check that the PBO isn't |
| 531 | * currently mapped. Whoever calls this function should check for that. |
| 532 | * Remember, we can't use a PBO when it's mapped! |
| 533 | * |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 534 | * \param width width of image to read/write |
| 535 | * \param height height of image to read/write |
| 536 | * \param depth depth of image to read/write |
| 537 | * \param format format of image to read/write |
| 538 | * \param type datatype of image to read/write |
| 539 | * \param ptr the user-provided pointer/offset |
| 540 | * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would |
| 541 | * go out of bounds. |
| 542 | */ |
| 543 | GLboolean |
Brian Paul | 6090938 | 2004-11-10 15:46:52 +0000 | [diff] [blame] | 544 | _mesa_validate_pbo_access(GLuint dimensions, |
| 545 | const struct gl_pixelstore_attrib *pack, |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 546 | GLsizei width, GLsizei height, GLsizei depth, |
| 547 | GLenum format, GLenum type, const GLvoid *ptr) |
| 548 | { |
| 549 | GLvoid *start, *end; |
Brian Paul | 6b25193 | 2005-12-01 00:59:51 +0000 | [diff] [blame] | 550 | const GLubyte *sizeAddr; /* buffer size, cast to a pointer */ |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 551 | |
| 552 | ASSERT(pack->BufferObj->Name != 0); |
| 553 | |
| 554 | if (pack->BufferObj->Size == 0) |
| 555 | /* no buffer! */ |
| 556 | return GL_FALSE; |
| 557 | |
| 558 | /* get address of first pixel we'll read */ |
Brian Paul | 6090938 | 2004-11-10 15:46:52 +0000 | [diff] [blame] | 559 | start = _mesa_image_address(dimensions, pack, ptr, width, height, |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 560 | format, type, 0, 0, 0); |
| 561 | |
| 562 | /* get address just past the last pixel we'll read */ |
Brian Paul | 6090938 | 2004-11-10 15:46:52 +0000 | [diff] [blame] | 563 | end = _mesa_image_address(dimensions, pack, ptr, width, height, |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 564 | format, type, depth-1, height-1, width); |
| 565 | |
| 566 | |
Brian Paul | 6b25193 | 2005-12-01 00:59:51 +0000 | [diff] [blame] | 567 | sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size; |
| 568 | |
| 569 | if ((const GLubyte *) start > sizeAddr) { |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 570 | /* This will catch negative values / wrap-around */ |
| 571 | return GL_FALSE; |
| 572 | } |
Brian Paul | 6b25193 | 2005-12-01 00:59:51 +0000 | [diff] [blame] | 573 | if ((const GLubyte *) end > sizeAddr) { |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 574 | /* Image read goes beyond end of buffer */ |
| 575 | return GL_FALSE; |
| 576 | } |
| 577 | |
| 578 | /* OK! */ |
| 579 | return GL_TRUE; |
| 580 | } |
| 581 | |
| 582 | |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 583 | /** |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 584 | * If the source of glBitmap data is a PBO, check that we won't read out |
| 585 | * of buffer bounds, then map the buffer. |
| 586 | * If not sourcing from a PBO, just return the bitmap pointer. |
| 587 | * This is a helper function for (some) drivers. |
| 588 | * Return NULL if error. |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 589 | * If non-null return, must call _mesa_unmap_bitmap_pbo() when done. |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 590 | */ |
| 591 | const GLubyte * |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 592 | _mesa_map_bitmap_pbo(GLcontext *ctx, |
| 593 | const struct gl_pixelstore_attrib *unpack, |
| 594 | const GLubyte *bitmap) |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 595 | { |
| 596 | const GLubyte *buf; |
| 597 | |
| 598 | if (unpack->BufferObj->Name) { |
| 599 | /* unpack from PBO */ |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 600 | buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, |
| 601 | GL_READ_ONLY_ARB, |
| 602 | unpack->BufferObj); |
| 603 | if (!buf) |
| 604 | return NULL; |
| 605 | |
| 606 | buf = ADD_POINTERS(buf, bitmap); |
| 607 | } |
| 608 | else { |
| 609 | /* unpack from normal memory */ |
| 610 | buf = bitmap; |
| 611 | } |
| 612 | |
| 613 | return buf; |
| 614 | } |
| 615 | |
| 616 | |
| 617 | /** |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 618 | * Counterpart to _mesa_map_bitmap_pbo() |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 619 | * This is a helper function for (some) drivers. |
| 620 | */ |
| 621 | void |
| 622 | _mesa_unmap_bitmap_pbo(GLcontext *ctx, |
| 623 | const struct gl_pixelstore_attrib *unpack) |
| 624 | { |
| 625 | if (unpack->BufferObj->Name) { |
| 626 | ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, |
| 627 | unpack->BufferObj); |
| 628 | } |
| 629 | } |
| 630 | |
| 631 | |
| 632 | /** |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 633 | * \sa _mesa_map_bitmap_pbo |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 634 | */ |
| 635 | const GLvoid * |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 636 | _mesa_map_drawpix_pbo(GLcontext *ctx, |
| 637 | const struct gl_pixelstore_attrib *unpack, |
| 638 | const GLvoid *pixels) |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 639 | { |
| 640 | const GLvoid *buf; |
| 641 | |
| 642 | if (unpack->BufferObj->Name) { |
| 643 | /* unpack from PBO */ |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 644 | buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, |
| 645 | GL_READ_ONLY_ARB, |
| 646 | unpack->BufferObj); |
| 647 | if (!buf) |
| 648 | return NULL; |
| 649 | |
| 650 | buf = ADD_POINTERS(buf, pixels); |
| 651 | } |
| 652 | else { |
| 653 | /* unpack from normal memory */ |
| 654 | buf = pixels; |
| 655 | } |
| 656 | |
| 657 | return buf; |
| 658 | } |
| 659 | |
| 660 | |
| 661 | /** |
| 662 | * \sa _mesa_unmap_bitmap_pbo |
| 663 | */ |
| 664 | void |
Brian Paul | 1437b41 | 2008-04-25 14:15:42 -0600 | [diff] [blame] | 665 | _mesa_unmap_drawpix_pbo(GLcontext *ctx, |
| 666 | const struct gl_pixelstore_attrib *unpack) |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 667 | { |
| 668 | if (unpack->BufferObj->Name) { |
| 669 | ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, |
| 670 | unpack->BufferObj); |
| 671 | } |
| 672 | } |
| 673 | |
| 674 | |
| 675 | /** |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 676 | * If PBO is bound, map the buffer, return dest pointer in mapped buffer. |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 677 | * Call _mesa_unmap_readpix_pbo() when finished |
| 678 | * \return NULL if error |
| 679 | */ |
| 680 | void * |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 681 | _mesa_map_readpix_pbo(GLcontext *ctx, |
| 682 | const struct gl_pixelstore_attrib *pack, |
| 683 | GLvoid *dest) |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 684 | { |
| 685 | void *buf; |
| 686 | |
| 687 | if (pack->BufferObj->Name) { |
| 688 | /* pack into PBO */ |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 689 | buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, |
| 690 | GL_WRITE_ONLY_ARB, |
| 691 | pack->BufferObj); |
| 692 | if (!buf) |
| 693 | return NULL; |
| 694 | |
| 695 | buf = ADD_POINTERS(buf, dest); |
| 696 | } |
| 697 | else { |
| 698 | /* pack to normal memory */ |
| 699 | buf = dest; |
| 700 | } |
| 701 | |
| 702 | return buf; |
| 703 | } |
| 704 | |
| 705 | |
| 706 | /** |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 707 | * Counterpart to _mesa_map_readpix_pbo() |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 708 | */ |
| 709 | void |
| 710 | _mesa_unmap_readpix_pbo(GLcontext *ctx, |
| 711 | const struct gl_pixelstore_attrib *pack) |
| 712 | { |
| 713 | if (pack->BufferObj->Name) { |
| 714 | ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj); |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 719 | |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 720 | /** |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 721 | * Return the gl_buffer_object for the given ID. |
| 722 | * Always return NULL for ID 0. |
| 723 | */ |
Brian Paul | 4d12a05 | 2006-08-23 23:10:14 +0000 | [diff] [blame] | 724 | struct gl_buffer_object * |
| 725 | _mesa_lookup_bufferobj(GLcontext *ctx, GLuint buffer) |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 726 | { |
| 727 | if (buffer == 0) |
| 728 | return NULL; |
| 729 | else |
| 730 | return (struct gl_buffer_object *) |
| 731 | _mesa_HashLookup(ctx->Shared->BufferObjects, buffer); |
| 732 | } |
| 733 | |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 734 | |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 735 | /** |
| 736 | * If *ptr points to obj, set ptr = the Null/default buffer object. |
| 737 | * This is a helper for buffer object deletion. |
| 738 | * The GL spec says that deleting a buffer object causes it to get |
| 739 | * unbound from all arrays in the current context. |
| 740 | */ |
| 741 | static void |
| 742 | unbind(GLcontext *ctx, |
| 743 | struct gl_buffer_object **ptr, |
| 744 | struct gl_buffer_object *obj) |
| 745 | { |
| 746 | if (*ptr == obj) { |
| 747 | _mesa_reference_buffer_object(ctx, ptr, ctx->Array.NullBufferObj); |
| 748 | } |
| 749 | } |
| 750 | |
| 751 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 752 | |
| 753 | /**********************************************************************/ |
| 754 | /* API Functions */ |
| 755 | /**********************************************************************/ |
| 756 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 757 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 758 | _mesa_BindBufferARB(GLenum target, GLuint buffer) |
| 759 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 760 | GET_CURRENT_CONTEXT(ctx); |
| 761 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 762 | |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 763 | bind_buffer_object(ctx, target, buffer); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 764 | } |
| 765 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 766 | |
| 767 | /** |
| 768 | * Delete a set of buffer objects. |
| 769 | * |
| 770 | * \param n Number of buffer objects to delete. |
Jose Fonseca | 375457b | 2004-09-09 22:23:24 +0000 | [diff] [blame] | 771 | * \param ids Array of \c n buffer object IDs. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 772 | */ |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 773 | void GLAPIENTRY |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 774 | _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 775 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 776 | GET_CURRENT_CONTEXT(ctx); |
Karl Schultz | df8d337 | 2003-09-18 15:14:10 +0000 | [diff] [blame] | 777 | GLsizei i; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 778 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 779 | |
| 780 | if (n < 0) { |
| 781 | _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)"); |
| 782 | return; |
| 783 | } |
| 784 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 785 | _glthread_LOCK_MUTEX(ctx->Shared->Mutex); |
| 786 | |
| 787 | for (i = 0; i < n; i++) { |
Brian Paul | 4d12a05 | 2006-08-23 23:10:14 +0000 | [diff] [blame] | 788 | struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 789 | if (bufObj) { |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 790 | GLuint j; |
Brian Paul | 94ec525 | 2004-03-04 14:46:00 +0000 | [diff] [blame] | 791 | |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 792 | ASSERT(bufObj->Name == ids[i]); |
Brian Paul | 94ec525 | 2004-03-04 14:46:00 +0000 | [diff] [blame] | 793 | |
Brian Paul | a7f434b | 2009-02-27 13:04:38 -0700 | [diff] [blame] | 794 | if (bufObj->Pointer) { |
| 795 | /* if mapped, unmap it now */ |
| 796 | ctx->Driver.UnmapBuffer(ctx, 0, bufObj); |
Brian Paul | 67025f7 | 2009-02-27 13:10:45 -0700 | [diff] [blame] | 797 | bufObj->Access = DEFAULT_ACCESS; |
| 798 | bufObj->Pointer = NULL; |
Brian Paul | a7f434b | 2009-02-27 13:04:38 -0700 | [diff] [blame] | 799 | } |
| 800 | |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 801 | /* unbind any vertex pointers bound to this buffer */ |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 802 | unbind(ctx, &ctx->Array.ArrayObj->Vertex.BufferObj, bufObj); |
| 803 | unbind(ctx, &ctx->Array.ArrayObj->Normal.BufferObj, bufObj); |
| 804 | unbind(ctx, &ctx->Array.ArrayObj->Color.BufferObj, bufObj); |
| 805 | unbind(ctx, &ctx->Array.ArrayObj->SecondaryColor.BufferObj, bufObj); |
| 806 | unbind(ctx, &ctx->Array.ArrayObj->FogCoord.BufferObj, bufObj); |
| 807 | unbind(ctx, &ctx->Array.ArrayObj->Index.BufferObj, bufObj); |
| 808 | unbind(ctx, &ctx->Array.ArrayObj->EdgeFlag.BufferObj, bufObj); |
Brian Paul | e9b3488 | 2008-12-31 11:54:02 -0700 | [diff] [blame] | 809 | for (j = 0; j < MAX_TEXTURE_COORD_UNITS; j++) { |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 810 | unbind(ctx, &ctx->Array.ArrayObj->TexCoord[j].BufferObj, bufObj); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 811 | } |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 812 | for (j = 0; j < VERT_ATTRIB_MAX; j++) { |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 813 | unbind(ctx, &ctx->Array.ArrayObj->VertexAttrib[j].BufferObj, bufObj); |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 814 | } |
| 815 | |
| 816 | if (ctx->Array.ArrayBufferObj == bufObj) { |
| 817 | _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); |
| 818 | } |
| 819 | if (ctx->Array.ElementArrayBufferObj == bufObj) { |
| 820 | _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); |
| 821 | } |
| 822 | |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 823 | /* unbind any pixel pack/unpack pointers bound to this buffer */ |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 824 | if (ctx->Pack.BufferObj == bufObj) { |
| 825 | _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 ); |
| 826 | } |
| 827 | if (ctx->Unpack.BufferObj == bufObj) { |
| 828 | _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); |
| 829 | } |
| 830 | |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 831 | /* The ID is immediately freed for re-use */ |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 832 | _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name); |
| 833 | _mesa_reference_buffer_object(ctx, &bufObj, NULL); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 834 | } |
| 835 | } |
| 836 | |
| 837 | _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 838 | } |
| 839 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 840 | |
| 841 | /** |
| 842 | * Generate a set of unique buffer object IDs and store them in \c buffer. |
| 843 | * |
| 844 | * \param n Number of IDs to generate. |
| 845 | * \param buffer Array of \c n locations to store the IDs. |
| 846 | */ |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 847 | void GLAPIENTRY |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 848 | _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 849 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 850 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 851 | GLuint first; |
| 852 | GLint i; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 853 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 854 | |
| 855 | if (n < 0) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 856 | _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 857 | return; |
| 858 | } |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 859 | |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 860 | if (!buffer) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 861 | return; |
| 862 | } |
| 863 | |
| 864 | /* |
| 865 | * This must be atomic (generation and allocation of buffer object IDs) |
| 866 | */ |
| 867 | _glthread_LOCK_MUTEX(ctx->Shared->Mutex); |
| 868 | |
| 869 | first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); |
| 870 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 871 | /* Allocate new, empty buffer objects and return identifiers */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 872 | for (i = 0; i < n; i++) { |
| 873 | struct gl_buffer_object *bufObj; |
| 874 | GLuint name = first + i; |
| 875 | GLenum target = 0; |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 876 | bufObj = ctx->Driver.NewBufferObject( ctx, name, target ); |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 877 | if (!bufObj) { |
Brian Paul | 2752177 | 2005-02-12 18:43:38 +0000 | [diff] [blame] | 878 | _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 879 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB"); |
| 880 | return; |
| 881 | } |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 882 | _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, bufObj); |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 883 | buffer[i] = first + i; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 884 | } |
| 885 | |
| 886 | _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 887 | } |
| 888 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 889 | |
| 890 | /** |
| 891 | * Determine if ID is the name of a buffer object. |
| 892 | * |
| 893 | * \param id ID of the potential buffer object. |
| 894 | * \return \c GL_TRUE if \c id is the name of a buffer object, |
| 895 | * \c GL_FALSE otherwise. |
| 896 | */ |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 897 | GLboolean GLAPIENTRY |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 898 | _mesa_IsBufferARB(GLuint id) |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 899 | { |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 900 | struct gl_buffer_object *bufObj; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 901 | GET_CURRENT_CONTEXT(ctx); |
| 902 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); |
| 903 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 904 | _glthread_LOCK_MUTEX(ctx->Shared->Mutex); |
Brian Paul | 4d12a05 | 2006-08-23 23:10:14 +0000 | [diff] [blame] | 905 | bufObj = _mesa_lookup_bufferobj(ctx, id); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 906 | _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); |
| 907 | |
Brian Paul | ea2943e | 2005-01-20 04:02:02 +0000 | [diff] [blame] | 908 | return bufObj ? GL_TRUE : GL_FALSE; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 909 | } |
| 910 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 911 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 912 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 913 | _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, |
| 914 | const GLvoid * data, GLenum usage) |
| 915 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 916 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 917 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 918 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 919 | |
| 920 | if (size < 0) { |
| 921 | _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); |
| 922 | return; |
| 923 | } |
| 924 | |
| 925 | switch (usage) { |
| 926 | case GL_STREAM_DRAW_ARB: |
| 927 | case GL_STREAM_READ_ARB: |
| 928 | case GL_STREAM_COPY_ARB: |
| 929 | case GL_STATIC_DRAW_ARB: |
| 930 | case GL_STATIC_READ_ARB: |
| 931 | case GL_STATIC_COPY_ARB: |
| 932 | case GL_DYNAMIC_DRAW_ARB: |
| 933 | case GL_DYNAMIC_READ_ARB: |
| 934 | case GL_DYNAMIC_COPY_ARB: |
| 935 | /* OK */ |
| 936 | break; |
| 937 | default: |
| 938 | _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)"); |
| 939 | return; |
| 940 | } |
| 941 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 942 | bufObj = get_buffer(ctx, target); |
| 943 | if (!bufObj) { |
| 944 | _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" ); |
| 945 | return; |
| 946 | } |
| 947 | if (bufObj->Name == 0) { |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 948 | _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB" ); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 949 | return; |
| 950 | } |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 951 | |
Brian Paul | 66e6e3e | 2003-09-17 21:18:22 +0000 | [diff] [blame] | 952 | if (bufObj->Pointer) { |
Brian Paul | 75e3ccf | 2009-02-27 12:30:21 -0700 | [diff] [blame] | 953 | /* Unmap the existing buffer. We'll replace it now. Not an error. */ |
| 954 | ctx->Driver.UnmapBuffer(ctx, target, bufObj); |
| 955 | bufObj->Access = DEFAULT_ACCESS; |
| 956 | bufObj->Pointer = NULL; |
Brian Paul | 66e6e3e | 2003-09-17 21:18:22 +0000 | [diff] [blame] | 957 | } |
| 958 | |
Brian Paul | b9d0f94 | 2009-05-06 15:17:25 -0600 | [diff] [blame] | 959 | FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); |
| 960 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 961 | ASSERT(ctx->Driver.BufferData); |
| 962 | |
Brian Paul | dcca97a | 2009-05-06 15:23:09 -0600 | [diff] [blame] | 963 | bufObj->Written = GL_TRUE; |
| 964 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 965 | /* Give the buffer object to the driver! <data> may be null! */ |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 966 | ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj ); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 967 | } |
| 968 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 969 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 970 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 971 | _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, |
| 972 | GLsizeiptrARB size, const GLvoid * data) |
| 973 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 974 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 975 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 976 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 977 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 978 | bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 979 | "glBufferSubDataARB" ); |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 980 | if (!bufObj) { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 981 | /* error already recorded */ |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 982 | return; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 983 | } |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 984 | |
Brian Paul | dcca97a | 2009-05-06 15:23:09 -0600 | [diff] [blame] | 985 | bufObj->Written = GL_TRUE; |
| 986 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 987 | ASSERT(ctx->Driver.BufferSubData); |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 988 | ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj ); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 989 | } |
| 990 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 991 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 992 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 993 | _mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, |
| 994 | GLsizeiptrARB size, void * data) |
| 995 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 996 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 997 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 998 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 999 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1000 | bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1001 | "glGetBufferSubDataARB" ); |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1002 | if (!bufObj) { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 1003 | /* error already recorded */ |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1004 | return; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1005 | } |
Brian Paul | 66e6e3e | 2003-09-17 21:18:22 +0000 | [diff] [blame] | 1006 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1007 | ASSERT(ctx->Driver.GetBufferSubData); |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 1008 | ctx->Driver.GetBufferSubData( ctx, target, offset, size, data, bufObj ); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1009 | } |
| 1010 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1011 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1012 | void * GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1013 | _mesa_MapBufferARB(GLenum target, GLenum access) |
| 1014 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1015 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1016 | struct gl_buffer_object * bufObj; |
Brian Paul | ea31ca4 | 2003-05-10 04:35:09 +0000 | [diff] [blame] | 1017 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1018 | |
| 1019 | switch (access) { |
| 1020 | case GL_READ_ONLY_ARB: |
| 1021 | case GL_WRITE_ONLY_ARB: |
| 1022 | case GL_READ_WRITE_ARB: |
| 1023 | /* OK */ |
| 1024 | break; |
| 1025 | default: |
| 1026 | _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)"); |
Brian Paul | ea31ca4 | 2003-05-10 04:35:09 +0000 | [diff] [blame] | 1027 | return NULL; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1028 | } |
| 1029 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1030 | bufObj = get_buffer(ctx, target); |
| 1031 | if (!bufObj) { |
| 1032 | _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" ); |
| 1033 | return NULL; |
| 1034 | } |
| 1035 | if (bufObj->Name == 0) { |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1036 | _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB" ); |
Brian Paul | ea31ca4 | 2003-05-10 04:35:09 +0000 | [diff] [blame] | 1037 | return NULL; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1038 | } |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 1039 | if (bufObj->Pointer) { |
Brian Paul | 66e6e3e | 2003-09-17 21:18:22 +0000 | [diff] [blame] | 1040 | _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1041 | return NULL; |
| 1042 | } |
| 1043 | |
| 1044 | ASSERT(ctx->Driver.MapBuffer); |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 1045 | bufObj->Pointer = ctx->Driver.MapBuffer( ctx, target, access, bufObj ); |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 1046 | if (!bufObj->Pointer) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1047 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)"); |
| 1048 | } |
| 1049 | |
Brian Paul | 0bb281b | 2003-10-14 15:48:39 +0000 | [diff] [blame] | 1050 | bufObj->Access = access; |
Brian Paul | dcca97a | 2009-05-06 15:23:09 -0600 | [diff] [blame] | 1051 | if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) |
| 1052 | bufObj->Written = GL_TRUE; |
Brian Paul | 0bb281b | 2003-10-14 15:48:39 +0000 | [diff] [blame] | 1053 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1054 | return bufObj->Pointer; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1055 | } |
| 1056 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1057 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1058 | GLboolean GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1059 | _mesa_UnmapBufferARB(GLenum target) |
| 1060 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1061 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1062 | struct gl_buffer_object *bufObj; |
| 1063 | GLboolean status = GL_TRUE; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1064 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); |
| 1065 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1066 | bufObj = get_buffer(ctx, target); |
| 1067 | if (!bufObj) { |
| 1068 | _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" ); |
| 1069 | return GL_FALSE; |
| 1070 | } |
| 1071 | if (bufObj->Name == 0) { |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1072 | _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" ); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1073 | return GL_FALSE; |
| 1074 | } |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 1075 | if (!bufObj->Pointer) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1076 | _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); |
| 1077 | return GL_FALSE; |
| 1078 | } |
| 1079 | |
Brian Paul | 67025f7 | 2009-02-27 13:10:45 -0700 | [diff] [blame] | 1080 | status = ctx->Driver.UnmapBuffer( ctx, target, bufObj ); |
Brian Paul | 6c72bc8 | 2008-09-25 11:46:27 -0600 | [diff] [blame] | 1081 | bufObj->Access = DEFAULT_ACCESS; |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1082 | bufObj->Pointer = NULL; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1083 | |
| 1084 | return status; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1085 | } |
| 1086 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1087 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1088 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1089 | _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) |
| 1090 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1091 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1092 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1093 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1094 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1095 | bufObj = get_buffer(ctx, target); |
| 1096 | if (!bufObj) { |
| 1097 | _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" ); |
| 1098 | return; |
| 1099 | } |
| 1100 | if (bufObj->Name == 0) { |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1101 | _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1102 | return; |
| 1103 | } |
| 1104 | |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1105 | switch (pname) { |
| 1106 | case GL_BUFFER_SIZE_ARB: |
Brian Paul | e4b2356 | 2005-05-04 20:11:35 +0000 | [diff] [blame] | 1107 | *params = (GLint) bufObj->Size; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1108 | break; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1109 | case GL_BUFFER_USAGE_ARB: |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1110 | *params = bufObj->Usage; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1111 | break; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1112 | case GL_BUFFER_ACCESS_ARB: |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1113 | *params = bufObj->Access; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1114 | break; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1115 | case GL_BUFFER_MAPPED_ARB: |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1116 | *params = (bufObj->Pointer != NULL); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1117 | break; |
| 1118 | default: |
| 1119 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)"); |
| 1120 | return; |
| 1121 | } |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1122 | } |
| 1123 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1124 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1125 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1126 | _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) |
| 1127 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1128 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1129 | struct gl_buffer_object * bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1130 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1131 | |
| 1132 | if (pname != GL_BUFFER_MAP_POINTER_ARB) { |
| 1133 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)"); |
| 1134 | return; |
| 1135 | } |
| 1136 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1137 | bufObj = get_buffer(ctx, target); |
| 1138 | if (!bufObj) { |
| 1139 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" ); |
| 1140 | return; |
| 1141 | } |
| 1142 | if (bufObj->Name == 0) { |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1143 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" ); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1144 | return; |
| 1145 | } |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1146 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1147 | *params = bufObj->Pointer; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1148 | } |