Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Mesa 3-D graphics library |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 3 | * Version: 7.6 |
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 | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 6 | * Copyright (C) 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" |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 35 | #include "enums.h" |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 36 | #include "hash.h" |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 37 | #include "imports.h" |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 38 | #include "image.h" |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 39 | #include "context.h" |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 40 | #include "bufferobj.h" |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 41 | #include "fbobject.h" |
| 42 | #include "texobj.h" |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 43 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 44 | |
Brian Paul | 4a7fd63 | 2009-06-09 11:53:19 -0600 | [diff] [blame] | 45 | /* Debug flags */ |
| 46 | /*#define VBO_DEBUG*/ |
| 47 | /*#define BOUNDS_CHECK*/ |
| 48 | |
| 49 | |
Chia-I Wu | 066477a | 2010-03-30 13:13:20 +0800 | [diff] [blame] | 50 | #if FEATURE_OES_mapbuffer |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 51 | #define DEFAULT_ACCESS GL_MAP_WRITE_BIT |
Brian Paul | 6c72bc8 | 2008-09-25 11:46:27 -0600 | [diff] [blame] | 52 | #else |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 53 | #define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT) |
Brian Paul | 6c72bc8 | 2008-09-25 11:46:27 -0600 | [diff] [blame] | 54 | #endif |
| 55 | |
| 56 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 57 | /** |
Brian Paul | c552f27 | 2010-11-11 14:47:30 -0700 | [diff] [blame] | 58 | * Used as a placeholder for buffer objects between glGenBuffers() and |
| 59 | * glBindBuffer() so that glIsBuffer() can work correctly. |
| 60 | */ |
| 61 | static struct gl_buffer_object DummyBufferObject; |
| 62 | |
| 63 | |
| 64 | /** |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 65 | * Return pointer to address of a buffer object target. |
| 66 | * \param ctx the GL context |
| 67 | * \param target the buffer object target to be retrieved. |
| 68 | * \return pointer to pointer to the buffer object bound to \c target in the |
| 69 | * specified context or \c NULL if \c target is invalid. |
| 70 | */ |
| 71 | static INLINE struct gl_buffer_object ** |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 72 | get_buffer_target(struct gl_context *ctx, GLenum target) |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 73 | { |
| 74 | switch (target) { |
| 75 | case GL_ARRAY_BUFFER_ARB: |
| 76 | return &ctx->Array.ArrayBufferObj; |
| 77 | case GL_ELEMENT_ARRAY_BUFFER_ARB: |
| 78 | return &ctx->Array.ElementArrayBufferObj; |
| 79 | case GL_PIXEL_PACK_BUFFER_EXT: |
| 80 | return &ctx->Pack.BufferObj; |
| 81 | case GL_PIXEL_UNPACK_BUFFER_EXT: |
| 82 | return &ctx->Unpack.BufferObj; |
| 83 | case GL_COPY_READ_BUFFER: |
Ian Romanick | 4da5f1b | 2010-09-27 14:29:12 -0700 | [diff] [blame] | 84 | return &ctx->CopyReadBuffer; |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 85 | case GL_COPY_WRITE_BUFFER: |
Ian Romanick | 4da5f1b | 2010-09-27 14:29:12 -0700 | [diff] [blame] | 86 | return &ctx->CopyWriteBuffer; |
Brian Paul | 423860a | 2010-03-30 19:53:01 -0600 | [diff] [blame] | 87 | #if FEATURE_EXT_transform_feedback |
| 88 | case GL_TRANSFORM_FEEDBACK_BUFFER: |
| 89 | if (ctx->Extensions.EXT_transform_feedback) { |
| 90 | return &ctx->TransformFeedback.CurrentBuffer; |
| 91 | } |
| 92 | break; |
| 93 | #endif |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 94 | default: |
| 95 | return NULL; |
| 96 | } |
| 97 | return NULL; |
| 98 | } |
| 99 | |
| 100 | |
| 101 | /** |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 102 | * Get the buffer object bound to the specified target in a GL context. |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 103 | * \param ctx the GL context |
| 104 | * \param target the buffer object target to be retrieved. |
| 105 | * \return pointer to the buffer object bound to \c target in the |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 106 | * specified context or \c NULL if \c target is invalid. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 107 | */ |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 108 | static INLINE struct gl_buffer_object * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 109 | get_buffer(struct gl_context *ctx, GLenum target) |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 110 | { |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 111 | struct gl_buffer_object **bufObj = get_buffer_target(ctx, target); |
| 112 | if (bufObj) |
| 113 | return *bufObj; |
| 114 | return NULL; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | |
| 118 | /** |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 119 | * Convert a GLbitfield describing the mapped buffer access flags |
| 120 | * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY. |
| 121 | */ |
| 122 | static GLenum |
| 123 | simplified_access_mode(GLbitfield access) |
| 124 | { |
| 125 | const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; |
| 126 | if ((access & rwFlags) == rwFlags) |
| 127 | return GL_READ_WRITE; |
| 128 | if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT) |
| 129 | return GL_READ_ONLY; |
| 130 | if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT) |
| 131 | return GL_WRITE_ONLY; |
| 132 | return GL_READ_WRITE; /* this should never happen, but no big deal */ |
| 133 | } |
| 134 | |
| 135 | |
| 136 | /** |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 137 | * Tests the subdata range parameters and sets the GL error code for |
| 138 | * \c glBufferSubDataARB and \c glGetBufferSubDataARB. |
| 139 | * |
| 140 | * \param ctx GL context. |
| 141 | * \param target Buffer object target on which to operate. |
| 142 | * \param offset Offset of the first byte of the subdata range. |
| 143 | * \param size Size, in bytes, of the subdata range. |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 144 | * \param caller Name of calling function for recording errors. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 145 | * \return A pointer to the buffer object bound to \c target in the |
| 146 | * specified context or \c NULL if any of the parameter or state |
| 147 | * conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB |
| 148 | * are invalid. |
| 149 | * |
| 150 | * \sa glBufferSubDataARB, glGetBufferSubDataARB |
| 151 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 152 | static struct gl_buffer_object * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 153 | buffer_object_subdata_range_good( struct gl_context * ctx, GLenum target, |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 154 | GLintptrARB offset, GLsizeiptrARB size, |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 155 | const char *caller ) |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 156 | { |
| 157 | struct gl_buffer_object *bufObj; |
| 158 | |
| 159 | if (size < 0) { |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 160 | _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 161 | return NULL; |
| 162 | } |
| 163 | |
| 164 | if (offset < 0) { |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 165 | _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 166 | return NULL; |
| 167 | } |
| 168 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 169 | bufObj = get_buffer(ctx, target); |
| 170 | if (!bufObj) { |
| 171 | _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 172 | return NULL; |
| 173 | } |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 174 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 175 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); |
| 176 | return NULL; |
| 177 | } |
Brian | 7e85b0a | 2007-01-23 12:50:08 -0700 | [diff] [blame] | 178 | if (offset + size > bufObj->Size) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 179 | _mesa_error(ctx, GL_INVALID_VALUE, |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 180 | "%s(size + offset > buffer size)", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 181 | return NULL; |
| 182 | } |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 183 | if (_mesa_bufferobj_mapped(bufObj)) { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 184 | /* Buffer is currently mapped */ |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 185 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 186 | return NULL; |
| 187 | } |
| 188 | |
| 189 | return bufObj; |
| 190 | } |
| 191 | |
| 192 | |
| 193 | /** |
| 194 | * Allocate and initialize a new buffer object. |
| 195 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 196 | * Default callback for the \c dd_function_table::NewBufferObject() hook. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 197 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 198 | static struct gl_buffer_object * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 199 | _mesa_new_buffer_object( struct gl_context *ctx, GLuint name, GLenum target ) |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 200 | { |
| 201 | struct gl_buffer_object *obj; |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 202 | |
| 203 | (void) ctx; |
| 204 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 205 | obj = MALLOC_STRUCT(gl_buffer_object); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 206 | _mesa_initialize_buffer_object(obj, name, target); |
| 207 | return obj; |
| 208 | } |
| 209 | |
| 210 | |
| 211 | /** |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 212 | * Delete a buffer object. |
| 213 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 214 | * Default callback for the \c dd_function_table::DeleteBuffer() hook. |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 215 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 216 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 217 | _mesa_delete_buffer_object( struct gl_context *ctx, struct gl_buffer_object *bufObj ) |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 218 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 219 | (void) ctx; |
| 220 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 221 | if (bufObj->Data) |
Kristian Høgsberg | 32f2fd1 | 2010-02-19 11:58:49 -0500 | [diff] [blame] | 222 | free(bufObj->Data); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 223 | |
| 224 | /* assign strange values here to help w/ debugging */ |
| 225 | bufObj->RefCount = -1000; |
| 226 | bufObj->Name = ~0; |
| 227 | |
Michal Krol | eeec2c3 | 2010-02-08 19:43:42 +0100 | [diff] [blame] | 228 | _glthread_DESTROY_MUTEX(bufObj->Mutex); |
Kristian Høgsberg | 32f2fd1 | 2010-02-19 11:58:49 -0500 | [diff] [blame] | 229 | free(bufObj); |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 233 | |
| 234 | /** |
| 235 | * Set ptr to bufObj w/ reference counting. |
| 236 | */ |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 237 | void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 238 | _mesa_reference_buffer_object(struct gl_context *ctx, |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 239 | struct gl_buffer_object **ptr, |
| 240 | struct gl_buffer_object *bufObj) |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 241 | { |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 242 | if (*ptr == bufObj) |
| 243 | return; |
| 244 | |
| 245 | if (*ptr) { |
Brian Paul | 105c852 | 2009-05-07 13:10:48 -0600 | [diff] [blame] | 246 | /* Unreference the old buffer */ |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 247 | GLboolean deleteFlag = GL_FALSE; |
| 248 | struct gl_buffer_object *oldObj = *ptr; |
| 249 | |
Michal Krol | eeec2c3 | 2010-02-08 19:43:42 +0100 | [diff] [blame] | 250 | _glthread_LOCK_MUTEX(oldObj->Mutex); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 251 | ASSERT(oldObj->RefCount > 0); |
| 252 | oldObj->RefCount--; |
| 253 | #if 0 |
| 254 | printf("BufferObj %p %d DECR to %d\n", |
| 255 | (void *) oldObj, oldObj->Name, oldObj->RefCount); |
| 256 | #endif |
| 257 | deleteFlag = (oldObj->RefCount == 0); |
Michal Krol | eeec2c3 | 2010-02-08 19:43:42 +0100 | [diff] [blame] | 258 | _glthread_UNLOCK_MUTEX(oldObj->Mutex); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 259 | |
| 260 | if (deleteFlag) { |
| 261 | |
| 262 | /* some sanity checking: don't delete a buffer still in use */ |
Brian Paul | d36f4ef | 2008-09-15 09:07:32 -0600 | [diff] [blame] | 263 | #if 0 |
| 264 | /* unfortunately, these tests are invalid during context tear-down */ |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 265 | ASSERT(ctx->Array.ArrayBufferObj != bufObj); |
| 266 | ASSERT(ctx->Array.ElementArrayBufferObj != bufObj); |
| 267 | ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj); |
Brian Paul | d36f4ef | 2008-09-15 09:07:32 -0600 | [diff] [blame] | 268 | #endif |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 269 | |
Brian Paul | d36f4ef | 2008-09-15 09:07:32 -0600 | [diff] [blame] | 270 | ASSERT(ctx->Driver.DeleteBuffer); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 271 | ctx->Driver.DeleteBuffer(ctx, oldObj); |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 272 | } |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 273 | |
| 274 | *ptr = NULL; |
| 275 | } |
| 276 | ASSERT(!*ptr); |
| 277 | |
| 278 | if (bufObj) { |
Brian Paul | 105c852 | 2009-05-07 13:10:48 -0600 | [diff] [blame] | 279 | /* reference new buffer */ |
Michal Krol | eeec2c3 | 2010-02-08 19:43:42 +0100 | [diff] [blame] | 280 | _glthread_LOCK_MUTEX(bufObj->Mutex); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 281 | if (bufObj->RefCount == 0) { |
| 282 | /* this buffer's being deleted (look just above) */ |
| 283 | /* Not sure this can every really happen. Warn if it does. */ |
| 284 | _mesa_problem(NULL, "referencing deleted buffer object"); |
| 285 | *ptr = NULL; |
| 286 | } |
| 287 | else { |
| 288 | bufObj->RefCount++; |
| 289 | #if 0 |
| 290 | printf("BufferObj %p %d INCR to %d\n", |
| 291 | (void *) bufObj, bufObj->Name, bufObj->RefCount); |
| 292 | #endif |
| 293 | *ptr = bufObj; |
| 294 | } |
Michal Krol | eeec2c3 | 2010-02-08 19:43:42 +0100 | [diff] [blame] | 295 | _glthread_UNLOCK_MUTEX(bufObj->Mutex); |
Ian Romanick | ee34e6e | 2006-06-12 16:26:29 +0000 | [diff] [blame] | 296 | } |
| 297 | } |
| 298 | |
| 299 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 300 | /** |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 301 | * Initialize a buffer object to default values. |
| 302 | */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 303 | void |
| 304 | _mesa_initialize_buffer_object( struct gl_buffer_object *obj, |
| 305 | GLuint name, GLenum target ) |
| 306 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 307 | (void) target; |
| 308 | |
Brian Paul | 6bf1ea8 | 2010-02-19 08:32:36 -0700 | [diff] [blame] | 309 | memset(obj, 0, sizeof(struct gl_buffer_object)); |
Michal Krol | eeec2c3 | 2010-02-08 19:43:42 +0100 | [diff] [blame] | 310 | _glthread_INIT_MUTEX(obj->Mutex); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 311 | obj->RefCount = 1; |
| 312 | obj->Name = name; |
Brian Paul | 85ad44b | 2004-02-13 14:04:26 +0000 | [diff] [blame] | 313 | obj->Usage = GL_STATIC_DRAW_ARB; |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 314 | obj->AccessFlags = DEFAULT_ACCESS; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 315 | } |
| 316 | |
| 317 | |
| 318 | /** |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 319 | * Allocate space for and store data in a buffer object. Any data that was |
| 320 | * previously stored in the buffer object is lost. If \c data is \c NULL, |
| 321 | * memory will be allocated, but no copy will occur. |
| 322 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 323 | * This is the default callback for \c dd_function_table::BufferData() |
| 324 | * Note that all GL error checking will have been done already. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 325 | * |
| 326 | * \param ctx GL context. |
| 327 | * \param target Buffer object target on which to operate. |
| 328 | * \param size Size, in bytes, of the new data store. |
| 329 | * \param data Pointer to the data to store in the buffer object. This |
| 330 | * pointer may be \c NULL. |
| 331 | * \param usage Hints about how the data will be used. |
| 332 | * \param bufObj Object to be used. |
| 333 | * |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 334 | * \return GL_TRUE for success, GL_FALSE for failure |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 335 | * \sa glBufferDataARB, dd_function_table::BufferData. |
| 336 | */ |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 337 | static GLboolean |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 338 | _mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size, |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 339 | const GLvoid * data, GLenum usage, |
| 340 | struct gl_buffer_object * bufObj ) |
| 341 | { |
| 342 | void * new_data; |
| 343 | |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 344 | (void) ctx; (void) target; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 345 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 346 | new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size ); |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 347 | if (new_data) { |
Brian Paul | e4fcea2 | 2003-09-19 15:38:15 +0000 | [diff] [blame] | 348 | bufObj->Data = (GLubyte *) new_data; |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 349 | bufObj->Size = size; |
| 350 | bufObj->Usage = usage; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 351 | |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 352 | if (data) { |
Kenneth Graunke | c7ac4862 | 2010-02-18 23:50:59 -0800 | [diff] [blame] | 353 | memcpy( bufObj->Data, data, size ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 354 | } |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 355 | |
| 356 | return GL_TRUE; |
| 357 | } |
| 358 | else { |
| 359 | return GL_FALSE; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 360 | } |
| 361 | } |
| 362 | |
| 363 | |
| 364 | /** |
| 365 | * Replace data in a subrange of buffer object. If the data range |
| 366 | * specified by \c size + \c offset extends beyond the end of the buffer or |
| 367 | * if \c data is \c NULL, no copy is performed. |
| 368 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 369 | * This is the default callback for \c dd_function_table::BufferSubData() |
| 370 | * Note that all GL error checking will have been done already. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 371 | * |
| 372 | * \param ctx GL context. |
| 373 | * \param target Buffer object target on which to operate. |
| 374 | * \param offset Offset of the first byte to be modified. |
| 375 | * \param size Size, in bytes, of the data range. |
| 376 | * \param data Pointer to the data to store in the buffer object. |
| 377 | * \param bufObj Object to be used. |
| 378 | * |
| 379 | * \sa glBufferSubDataARB, dd_function_table::BufferSubData. |
| 380 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 381 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 382 | _mesa_buffer_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset, |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 383 | GLsizeiptrARB size, const GLvoid * data, |
| 384 | struct gl_buffer_object * bufObj ) |
| 385 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 386 | (void) ctx; (void) target; |
| 387 | |
Brian Paul | 76785cb | 2006-09-21 22:59:50 +0000 | [diff] [blame] | 388 | /* this should have been caught in _mesa_BufferSubData() */ |
Brian | 7e85b0a | 2007-01-23 12:50:08 -0700 | [diff] [blame] | 389 | ASSERT(size + offset <= bufObj->Size); |
Brian Paul | 76785cb | 2006-09-21 22:59:50 +0000 | [diff] [blame] | 390 | |
| 391 | if (bufObj->Data) { |
Kenneth Graunke | c7ac4862 | 2010-02-18 23:50:59 -0800 | [diff] [blame] | 392 | memcpy( (GLubyte *) bufObj->Data + offset, data, size ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 393 | } |
| 394 | } |
| 395 | |
| 396 | |
| 397 | /** |
| 398 | * Retrieve data from a subrange of buffer object. If the data range |
| 399 | * specified by \c size + \c offset extends beyond the end of the buffer or |
| 400 | * if \c data is \c NULL, no copy is performed. |
| 401 | * |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 402 | * This is the default callback for \c dd_function_table::GetBufferSubData() |
| 403 | * Note that all GL error checking will have been done already. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 404 | * |
| 405 | * \param ctx GL context. |
| 406 | * \param target Buffer object target on which to operate. |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 407 | * \param offset Offset of the first byte to be fetched. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 408 | * \param size Size, in bytes, of the data range. |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 409 | * \param data Destination for data |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 410 | * \param bufObj Object to be used. |
| 411 | * |
| 412 | * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData. |
| 413 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 414 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 415 | _mesa_buffer_get_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset, |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 416 | GLsizeiptrARB size, GLvoid * data, |
| 417 | struct gl_buffer_object * bufObj ) |
| 418 | { |
Brian Paul | a6c423d | 2004-08-25 15:59:48 +0000 | [diff] [blame] | 419 | (void) ctx; (void) target; |
| 420 | |
Brian Paul | c1f2f90 | 2005-03-03 02:05:33 +0000 | [diff] [blame] | 421 | if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) { |
Kenneth Graunke | c7ac4862 | 2010-02-18 23:50:59 -0800 | [diff] [blame] | 422 | memcpy( data, (GLubyte *) bufObj->Data + offset, size ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 423 | } |
| 424 | } |
| 425 | |
| 426 | |
| 427 | /** |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 428 | * Default callback for \c dd_function_tabel::MapBuffer(). |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 429 | * |
Brian Paul | 76785cb | 2006-09-21 22:59:50 +0000 | [diff] [blame] | 430 | * The function parameters will have been already tested for errors. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 431 | * |
| 432 | * \param ctx GL context. |
| 433 | * \param target Buffer object target on which to operate. |
| 434 | * \param access Information about how the buffer will be accessed. |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 435 | * \param bufObj Object to be mapped. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 436 | * \return A pointer to the object's internal data store that can be accessed |
| 437 | * by the processor |
| 438 | * |
| 439 | * \sa glMapBufferARB, dd_function_table::MapBuffer |
| 440 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 441 | static void * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 442 | _mesa_buffer_map( struct gl_context *ctx, GLenum target, GLenum access, |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 443 | struct gl_buffer_object *bufObj ) |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 444 | { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 445 | (void) ctx; |
| 446 | (void) target; |
| 447 | (void) access; |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 448 | /* Just return a direct pointer to the data */ |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 449 | if (_mesa_bufferobj_mapped(bufObj)) { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 450 | /* already mapped! */ |
| 451 | return NULL; |
| 452 | } |
| 453 | bufObj->Pointer = bufObj->Data; |
Brian Paul | d1da8ac | 2009-08-31 09:05:28 -0600 | [diff] [blame] | 454 | bufObj->Length = bufObj->Size; |
| 455 | bufObj->Offset = 0; |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 456 | return bufObj->Pointer; |
| 457 | } |
| 458 | |
| 459 | |
| 460 | /** |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 461 | * Default fallback for \c dd_function_table::MapBufferRange(). |
| 462 | * Called via glMapBufferRange(). |
| 463 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 464 | static void * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 465 | _mesa_buffer_map_range( struct gl_context *ctx, GLenum target, GLintptr offset, |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 466 | GLsizeiptr length, GLbitfield access, |
| 467 | struct gl_buffer_object *bufObj ) |
| 468 | { |
| 469 | (void) ctx; |
| 470 | (void) target; |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 471 | assert(!_mesa_bufferobj_mapped(bufObj)); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 472 | /* Just return a direct pointer to the data */ |
Brian Paul | 2b6ab61 | 2009-08-31 09:12:04 -0600 | [diff] [blame] | 473 | bufObj->Pointer = bufObj->Data + offset; |
| 474 | bufObj->Length = length; |
| 475 | bufObj->Offset = offset; |
| 476 | bufObj->AccessFlags = access; |
| 477 | return bufObj->Pointer; |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 478 | } |
| 479 | |
| 480 | |
| 481 | /** |
| 482 | * Default fallback for \c dd_function_table::FlushMappedBufferRange(). |
| 483 | * Called via glFlushMappedBufferRange(). |
| 484 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 485 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 486 | _mesa_buffer_flush_mapped_range( struct gl_context *ctx, GLenum target, |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 487 | GLintptr offset, GLsizeiptr length, |
| 488 | struct gl_buffer_object *obj ) |
| 489 | { |
| 490 | (void) ctx; |
| 491 | (void) target; |
| 492 | (void) offset; |
| 493 | (void) length; |
| 494 | (void) obj; |
| 495 | /* no-op */ |
| 496 | } |
| 497 | |
| 498 | |
| 499 | /** |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 500 | * Default callback for \c dd_function_table::MapBuffer(). |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 501 | * |
| 502 | * The input parameters will have been already tested for errors. |
| 503 | * |
| 504 | * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer |
| 505 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 506 | static GLboolean |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 507 | _mesa_buffer_unmap( struct gl_context *ctx, GLenum target, |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 508 | struct gl_buffer_object *bufObj ) |
| 509 | { |
| 510 | (void) ctx; |
| 511 | (void) target; |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 512 | /* XXX we might assert here that bufObj->Pointer is non-null */ |
| 513 | bufObj->Pointer = NULL; |
Brian Paul | 822c796 | 2009-08-31 08:59:38 -0600 | [diff] [blame] | 514 | bufObj->Length = 0; |
| 515 | bufObj->Offset = 0; |
| 516 | bufObj->AccessFlags = 0x0; |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 517 | return GL_TRUE; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 518 | } |
| 519 | |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 520 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 521 | /** |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 522 | * Default fallback for \c dd_function_table::CopyBufferSubData(). |
| 523 | * Called via glCopyBuffserSubData(). |
| 524 | */ |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 525 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 526 | _mesa_copy_buffer_subdata(struct gl_context *ctx, |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 527 | struct gl_buffer_object *src, |
| 528 | struct gl_buffer_object *dst, |
| 529 | GLintptr readOffset, GLintptr writeOffset, |
| 530 | GLsizeiptr size) |
| 531 | { |
| 532 | GLubyte *srcPtr, *dstPtr; |
| 533 | |
| 534 | /* buffer should not already be mapped */ |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 535 | assert(!_mesa_bufferobj_mapped(src)); |
| 536 | assert(!_mesa_bufferobj_mapped(dst)); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 537 | |
| 538 | srcPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_READ_BUFFER, |
| 539 | GL_READ_ONLY, src); |
| 540 | dstPtr = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_COPY_WRITE_BUFFER, |
| 541 | GL_WRITE_ONLY, dst); |
| 542 | |
| 543 | if (srcPtr && dstPtr) |
Kenneth Graunke | c7ac4862 | 2010-02-18 23:50:59 -0800 | [diff] [blame] | 544 | memcpy(dstPtr + writeOffset, srcPtr + readOffset, size); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 545 | |
| 546 | ctx->Driver.UnmapBuffer(ctx, GL_COPY_READ_BUFFER, src); |
| 547 | ctx->Driver.UnmapBuffer(ctx, GL_COPY_WRITE_BUFFER, dst); |
| 548 | } |
| 549 | |
| 550 | |
| 551 | |
| 552 | /** |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 553 | * Initialize the state associated with buffer objects |
| 554 | */ |
| 555 | void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 556 | _mesa_init_buffer_objects( struct gl_context *ctx ) |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 557 | { |
Brian Paul | c552f27 | 2010-11-11 14:47:30 -0700 | [diff] [blame] | 558 | memset(&DummyBufferObject, 0, sizeof(DummyBufferObject)); |
| 559 | DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */ |
| 560 | |
Brian Paul | 0854b7e | 2009-06-10 13:45:01 -0600 | [diff] [blame] | 561 | _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, |
| 562 | ctx->Shared->NullBufferObj); |
| 563 | _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, |
| 564 | ctx->Shared->NullBufferObj); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 565 | |
Brian Paul | 0854b7e | 2009-06-10 13:45:01 -0600 | [diff] [blame] | 566 | _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, |
| 567 | ctx->Shared->NullBufferObj); |
| 568 | _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, |
| 569 | ctx->Shared->NullBufferObj); |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 570 | } |
| 571 | |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 572 | |
Michal Krol | 01d7e3d | 2010-02-09 14:25:41 +0100 | [diff] [blame] | 573 | void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 574 | _mesa_free_buffer_objects( struct gl_context *ctx ) |
Michal Krol | 01d7e3d | 2010-02-09 14:25:41 +0100 | [diff] [blame] | 575 | { |
| 576 | _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL); |
| 577 | _mesa_reference_buffer_object(ctx, &ctx->Array.ElementArrayBufferObj, NULL); |
| 578 | |
| 579 | _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL); |
| 580 | _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL); |
| 581 | } |
| 582 | |
| 583 | |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 584 | /** |
| 585 | * Bind the specified target to buffer for the specified context. |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 586 | * Called by glBindBuffer() and other functions. |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 587 | */ |
| 588 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 589 | bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 590 | { |
| 591 | struct gl_buffer_object *oldBufObj; |
| 592 | struct gl_buffer_object *newBufObj = NULL; |
| 593 | struct gl_buffer_object **bindTarget = NULL; |
| 594 | |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 595 | bindTarget = get_buffer_target(ctx, target); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 596 | if (!bindTarget) { |
Eric Anholt | 86af037 | 2010-09-01 14:46:22 -0700 | [diff] [blame] | 597 | _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)", target); |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 598 | return; |
| 599 | } |
| 600 | |
| 601 | /* Get pointer to old buffer object (to be unbound) */ |
Brian Paul | dd5691e | 2009-10-27 20:10:30 -0600 | [diff] [blame] | 602 | oldBufObj = *bindTarget; |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 603 | if (oldBufObj && oldBufObj->Name == buffer) |
| 604 | return; /* rebinding the same buffer object- no change */ |
| 605 | |
| 606 | /* |
| 607 | * Get pointer to new buffer object (newBufObj) |
| 608 | */ |
| 609 | if (buffer == 0) { |
| 610 | /* The spec says there's not a buffer object named 0, but we use |
| 611 | * one internally because it simplifies things. |
| 612 | */ |
Brian Paul | 4f6b704 | 2009-05-07 13:30:39 -0600 | [diff] [blame] | 613 | newBufObj = ctx->Shared->NullBufferObj; |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 614 | } |
| 615 | else { |
| 616 | /* non-default buffer object */ |
| 617 | newBufObj = _mesa_lookup_bufferobj(ctx, buffer); |
Brian Paul | c552f27 | 2010-11-11 14:47:30 -0700 | [diff] [blame] | 618 | if (!newBufObj || newBufObj == &DummyBufferObject) { |
| 619 | /* If this is a new buffer object id, or one which was generated but |
| 620 | * never used before, allocate a buffer object now. |
| 621 | */ |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 622 | ASSERT(ctx->Driver.NewBufferObject); |
| 623 | newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target); |
| 624 | if (!newBufObj) { |
| 625 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); |
| 626 | return; |
| 627 | } |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 628 | _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj); |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 629 | } |
| 630 | } |
| 631 | |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 632 | /* bind new buffer */ |
| 633 | _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 634 | |
| 635 | /* Pass BindBuffer call to device driver */ |
Brian Paul | f7ca97f | 2009-05-14 16:51:10 -0600 | [diff] [blame] | 636 | if (ctx->Driver.BindBuffer) |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 637 | ctx->Driver.BindBuffer( ctx, target, newBufObj ); |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 638 | } |
| 639 | |
| 640 | |
| 641 | /** |
| 642 | * Update the default buffer objects in the given context to reference those |
| 643 | * specified in the shared state and release those referencing the old |
| 644 | * shared state. |
| 645 | */ |
| 646 | void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 647 | _mesa_update_default_objects_buffer_objects(struct gl_context *ctx) |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 648 | { |
| 649 | /* Bind the NullBufferObj to remove references to those |
| 650 | * in the shared context hash table. |
| 651 | */ |
| 652 | bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0); |
| 653 | bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0); |
| 654 | bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0); |
| 655 | bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0); |
| 656 | } |
| 657 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 658 | |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 659 | /** |
| 660 | * When we're about to read pixel data out of a PBO (via glDrawPixels, |
| 661 | * glTexImage, etc) or write data into a PBO (via glReadPixels, |
| 662 | * glGetTexImage, etc) we call this function to check that we're not |
| 663 | * going to read out of bounds. |
| 664 | * |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 665 | * XXX This would also be a convenient time to check that the PBO isn't |
| 666 | * currently mapped. Whoever calls this function should check for that. |
| 667 | * Remember, we can't use a PBO when it's mapped! |
| 668 | * |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 669 | * If we're not using a PBO, this is a no-op. |
| 670 | * |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 671 | * \param width width of image to read/write |
| 672 | * \param height height of image to read/write |
| 673 | * \param depth depth of image to read/write |
| 674 | * \param format format of image to read/write |
| 675 | * \param type datatype of image to read/write |
| 676 | * \param ptr the user-provided pointer/offset |
| 677 | * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would |
| 678 | * go out of bounds. |
| 679 | */ |
| 680 | GLboolean |
Brian Paul | 6090938 | 2004-11-10 15:46:52 +0000 | [diff] [blame] | 681 | _mesa_validate_pbo_access(GLuint dimensions, |
| 682 | const struct gl_pixelstore_attrib *pack, |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 683 | GLsizei width, GLsizei height, GLsizei depth, |
| 684 | GLenum format, GLenum type, const GLvoid *ptr) |
| 685 | { |
| 686 | GLvoid *start, *end; |
Brian Paul | 6b25193 | 2005-12-01 00:59:51 +0000 | [diff] [blame] | 687 | const GLubyte *sizeAddr; /* buffer size, cast to a pointer */ |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 688 | |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 689 | if (!_mesa_is_bufferobj(pack->BufferObj)) |
| 690 | return GL_TRUE; /* no PBO, OK */ |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 691 | |
| 692 | if (pack->BufferObj->Size == 0) |
| 693 | /* no buffer! */ |
| 694 | return GL_FALSE; |
| 695 | |
| 696 | /* get address of first pixel we'll read */ |
Brian Paul | 6090938 | 2004-11-10 15:46:52 +0000 | [diff] [blame] | 697 | start = _mesa_image_address(dimensions, pack, ptr, width, height, |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 698 | format, type, 0, 0, 0); |
| 699 | |
| 700 | /* get address just past the last pixel we'll read */ |
Brian Paul | 6090938 | 2004-11-10 15:46:52 +0000 | [diff] [blame] | 701 | end = _mesa_image_address(dimensions, pack, ptr, width, height, |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 702 | format, type, depth-1, height-1, width); |
| 703 | |
| 704 | |
Brian Paul | 6b25193 | 2005-12-01 00:59:51 +0000 | [diff] [blame] | 705 | sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size; |
| 706 | |
| 707 | if ((const GLubyte *) start > sizeAddr) { |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 708 | /* This will catch negative values / wrap-around */ |
| 709 | return GL_FALSE; |
| 710 | } |
Brian Paul | 6b25193 | 2005-12-01 00:59:51 +0000 | [diff] [blame] | 711 | if ((const GLubyte *) end > sizeAddr) { |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 712 | /* Image read goes beyond end of buffer */ |
| 713 | return GL_FALSE; |
| 714 | } |
| 715 | |
| 716 | /* OK! */ |
| 717 | return GL_TRUE; |
| 718 | } |
| 719 | |
| 720 | |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 721 | /** |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 722 | * For commands that read from a PBO (glDrawPixels, glTexImage, |
| 723 | * glPolygonStipple, etc), if we're reading from a PBO, map it read-only |
| 724 | * and return the pointer into the PBO. If we're not reading from a |
| 725 | * PBO, return \p src as-is. |
| 726 | * If non-null return, must call _mesa_unmap_pbo_source() when done. |
| 727 | * |
| 728 | * \return NULL if error, else pointer to start of data |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 729 | */ |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 730 | const GLvoid * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 731 | _mesa_map_pbo_source(struct gl_context *ctx, |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 732 | const struct gl_pixelstore_attrib *unpack, |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 733 | const GLvoid *src) |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 734 | { |
| 735 | const GLubyte *buf; |
| 736 | |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 737 | if (_mesa_is_bufferobj(unpack->BufferObj)) { |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 738 | /* unpack from PBO */ |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 739 | buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, |
| 740 | GL_READ_ONLY_ARB, |
| 741 | unpack->BufferObj); |
| 742 | if (!buf) |
| 743 | return NULL; |
| 744 | |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 745 | buf = ADD_POINTERS(buf, src); |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 746 | } |
| 747 | else { |
| 748 | /* unpack from normal memory */ |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 749 | buf = src; |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 750 | } |
| 751 | |
| 752 | return buf; |
| 753 | } |
| 754 | |
| 755 | |
| 756 | /** |
Brian Paul | dc947c8 | 2009-09-03 11:22:27 -0600 | [diff] [blame] | 757 | * Combine PBO-read validation and mapping. |
| 758 | * If any GL errors are detected, they'll be recorded and NULL returned. |
| 759 | * \sa _mesa_validate_pbo_access |
| 760 | * \sa _mesa_map_pbo_source |
| 761 | * A call to this function should have a matching call to |
| 762 | * _mesa_unmap_pbo_source(). |
| 763 | */ |
| 764 | const GLvoid * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 765 | _mesa_map_validate_pbo_source(struct gl_context *ctx, |
Brian Paul | dc947c8 | 2009-09-03 11:22:27 -0600 | [diff] [blame] | 766 | GLuint dimensions, |
| 767 | const struct gl_pixelstore_attrib *unpack, |
| 768 | GLsizei width, GLsizei height, GLsizei depth, |
| 769 | GLenum format, GLenum type, const GLvoid *ptr, |
| 770 | const char *where) |
| 771 | { |
| 772 | ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3); |
| 773 | |
| 774 | if (!_mesa_is_bufferobj(unpack->BufferObj)) { |
| 775 | /* non-PBO access: no validation to be done */ |
| 776 | return ptr; |
| 777 | } |
| 778 | |
| 779 | if (!_mesa_validate_pbo_access(dimensions, unpack, |
| 780 | width, height, depth, format, type, ptr)) { |
| 781 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 782 | "%s(out of bounds PBO access)", where); |
| 783 | return NULL; |
| 784 | } |
| 785 | |
| 786 | if (_mesa_bufferobj_mapped(unpack->BufferObj)) { |
| 787 | /* buffer is already mapped - that's an error */ |
| 788 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); |
| 789 | return NULL; |
| 790 | } |
| 791 | |
| 792 | ptr = _mesa_map_pbo_source(ctx, unpack, ptr); |
| 793 | return ptr; |
| 794 | } |
| 795 | |
| 796 | |
| 797 | /** |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 798 | * Counterpart to _mesa_map_pbo_source() |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 799 | */ |
| 800 | void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 801 | _mesa_unmap_pbo_source(struct gl_context *ctx, |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 802 | const struct gl_pixelstore_attrib *unpack) |
| 803 | { |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 804 | ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 805 | if (_mesa_is_bufferobj(unpack->BufferObj)) { |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 806 | ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, |
| 807 | unpack->BufferObj); |
| 808 | } |
| 809 | } |
| 810 | |
| 811 | |
| 812 | /** |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 813 | * For commands that write to a PBO (glReadPixels, glGetColorTable, etc), |
| 814 | * if we're writing to a PBO, map it write-only and return the pointer |
| 815 | * into the PBO. If we're not writing to a PBO, return \p dst as-is. |
| 816 | * If non-null return, must call _mesa_unmap_pbo_dest() when done. |
| 817 | * |
| 818 | * \return NULL if error, else pointer to start of data |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 819 | */ |
| 820 | void * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 821 | _mesa_map_pbo_dest(struct gl_context *ctx, |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 822 | const struct gl_pixelstore_attrib *pack, |
| 823 | GLvoid *dest) |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 824 | { |
| 825 | void *buf; |
| 826 | |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 827 | if (_mesa_is_bufferobj(pack->BufferObj)) { |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 828 | /* pack into PBO */ |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 829 | buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, |
| 830 | GL_WRITE_ONLY_ARB, |
| 831 | pack->BufferObj); |
| 832 | if (!buf) |
| 833 | return NULL; |
| 834 | |
| 835 | buf = ADD_POINTERS(buf, dest); |
| 836 | } |
| 837 | else { |
| 838 | /* pack to normal memory */ |
| 839 | buf = dest; |
| 840 | } |
| 841 | |
| 842 | return buf; |
| 843 | } |
| 844 | |
| 845 | |
| 846 | /** |
Brian Paul | dc947c8 | 2009-09-03 11:22:27 -0600 | [diff] [blame] | 847 | * Combine PBO-write validation and mapping. |
| 848 | * If any GL errors are detected, they'll be recorded and NULL returned. |
| 849 | * \sa _mesa_validate_pbo_access |
| 850 | * \sa _mesa_map_pbo_dest |
| 851 | * A call to this function should have a matching call to |
| 852 | * _mesa_unmap_pbo_dest(). |
| 853 | */ |
| 854 | GLvoid * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 855 | _mesa_map_validate_pbo_dest(struct gl_context *ctx, |
Brian Paul | dc947c8 | 2009-09-03 11:22:27 -0600 | [diff] [blame] | 856 | GLuint dimensions, |
| 857 | const struct gl_pixelstore_attrib *unpack, |
| 858 | GLsizei width, GLsizei height, GLsizei depth, |
| 859 | GLenum format, GLenum type, GLvoid *ptr, |
| 860 | const char *where) |
| 861 | { |
| 862 | ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3); |
| 863 | |
| 864 | if (!_mesa_is_bufferobj(unpack->BufferObj)) { |
| 865 | /* non-PBO access: no validation to be done */ |
| 866 | return ptr; |
| 867 | } |
| 868 | |
| 869 | if (!_mesa_validate_pbo_access(dimensions, unpack, |
| 870 | width, height, depth, format, type, ptr)) { |
| 871 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 872 | "%s(out of bounds PBO access)", where); |
| 873 | return NULL; |
| 874 | } |
| 875 | |
| 876 | if (_mesa_bufferobj_mapped(unpack->BufferObj)) { |
| 877 | /* buffer is already mapped - that's an error */ |
| 878 | _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); |
| 879 | return NULL; |
| 880 | } |
| 881 | |
| 882 | ptr = _mesa_map_pbo_dest(ctx, unpack, ptr); |
| 883 | return ptr; |
| 884 | } |
| 885 | |
| 886 | |
| 887 | /** |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 888 | * Counterpart to _mesa_map_pbo_dest() |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 889 | */ |
| 890 | void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 891 | _mesa_unmap_pbo_dest(struct gl_context *ctx, |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 892 | const struct gl_pixelstore_attrib *pack) |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 893 | { |
Brian Paul | 1b448c7 | 2009-09-03 11:29:18 -0600 | [diff] [blame] | 894 | ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 895 | if (_mesa_is_bufferobj(pack->BufferObj)) { |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 896 | ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj); |
| 897 | } |
| 898 | } |
| 899 | |
| 900 | |
Brian | d933be6 | 2008-03-21 14:19:28 -0600 | [diff] [blame] | 901 | |
Brian | a429a25 | 2008-03-21 13:41:00 -0600 | [diff] [blame] | 902 | /** |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 903 | * Return the gl_buffer_object for the given ID. |
| 904 | * Always return NULL for ID 0. |
| 905 | */ |
Brian Paul | 4d12a05 | 2006-08-23 23:10:14 +0000 | [diff] [blame] | 906 | struct gl_buffer_object * |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 907 | _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer) |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 908 | { |
| 909 | if (buffer == 0) |
| 910 | return NULL; |
| 911 | else |
| 912 | return (struct gl_buffer_object *) |
| 913 | _mesa_HashLookup(ctx->Shared->BufferObjects, buffer); |
| 914 | } |
| 915 | |
Brian Paul | 7a6b71e | 2004-03-13 18:21:40 +0000 | [diff] [blame] | 916 | |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 917 | /** |
| 918 | * If *ptr points to obj, set ptr = the Null/default buffer object. |
| 919 | * This is a helper for buffer object deletion. |
| 920 | * The GL spec says that deleting a buffer object causes it to get |
| 921 | * unbound from all arrays in the current context. |
| 922 | */ |
| 923 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 924 | unbind(struct gl_context *ctx, |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 925 | struct gl_buffer_object **ptr, |
| 926 | struct gl_buffer_object *obj) |
| 927 | { |
| 928 | if (*ptr == obj) { |
Brian Paul | 4f6b704 | 2009-05-07 13:30:39 -0600 | [diff] [blame] | 929 | _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 930 | } |
| 931 | } |
| 932 | |
| 933 | |
Brian Paul | 331eb58f | 2009-06-19 10:00:03 -0600 | [diff] [blame] | 934 | /** |
| 935 | * Plug default/fallback buffer object functions into the device |
| 936 | * driver hooks. |
| 937 | */ |
| 938 | void |
| 939 | _mesa_init_buffer_object_functions(struct dd_function_table *driver) |
| 940 | { |
| 941 | /* GL_ARB_vertex/pixel_buffer_object */ |
| 942 | driver->NewBufferObject = _mesa_new_buffer_object; |
| 943 | driver->DeleteBuffer = _mesa_delete_buffer_object; |
| 944 | driver->BindBuffer = NULL; |
| 945 | driver->BufferData = _mesa_buffer_data; |
| 946 | driver->BufferSubData = _mesa_buffer_subdata; |
| 947 | driver->GetBufferSubData = _mesa_buffer_get_subdata; |
| 948 | driver->MapBuffer = _mesa_buffer_map; |
| 949 | driver->UnmapBuffer = _mesa_buffer_unmap; |
| 950 | |
| 951 | /* GL_ARB_map_buffer_range */ |
| 952 | driver->MapBufferRange = _mesa_buffer_map_range; |
| 953 | driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range; |
| 954 | |
| 955 | /* GL_ARB_copy_buffer */ |
| 956 | driver->CopyBufferSubData = _mesa_copy_buffer_subdata; |
| 957 | } |
| 958 | |
| 959 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 960 | |
| 961 | /**********************************************************************/ |
| 962 | /* API Functions */ |
| 963 | /**********************************************************************/ |
| 964 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 965 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 966 | _mesa_BindBufferARB(GLenum target, GLuint buffer) |
| 967 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 968 | GET_CURRENT_CONTEXT(ctx); |
| 969 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 970 | |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 971 | bind_buffer_object(ctx, target, buffer); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 972 | } |
| 973 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 974 | |
| 975 | /** |
| 976 | * Delete a set of buffer objects. |
| 977 | * |
| 978 | * \param n Number of buffer objects to delete. |
Jose Fonseca | 375457b | 2004-09-09 22:23:24 +0000 | [diff] [blame] | 979 | * \param ids Array of \c n buffer object IDs. |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 980 | */ |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 981 | void GLAPIENTRY |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 982 | _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 983 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 984 | GET_CURRENT_CONTEXT(ctx); |
Karl Schultz | df8d337 | 2003-09-18 15:14:10 +0000 | [diff] [blame] | 985 | GLsizei i; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 986 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 987 | |
| 988 | if (n < 0) { |
| 989 | _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)"); |
| 990 | return; |
| 991 | } |
| 992 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 993 | _glthread_LOCK_MUTEX(ctx->Shared->Mutex); |
| 994 | |
| 995 | for (i = 0; i < n; i++) { |
Brian Paul | 4d12a05 | 2006-08-23 23:10:14 +0000 | [diff] [blame] | 996 | struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 997 | if (bufObj) { |
Brian Paul | a65f385 | 2009-05-22 14:14:53 -0600 | [diff] [blame] | 998 | struct gl_array_object *arrayObj = ctx->Array.ArrayObj; |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 999 | GLuint j; |
Brian Paul | 94ec525 | 2004-03-04 14:46:00 +0000 | [diff] [blame] | 1000 | |
Brian Paul | 78587ea | 2010-11-11 15:31:28 -0700 | [diff] [blame^] | 1001 | ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject); |
Brian Paul | 94ec525 | 2004-03-04 14:46:00 +0000 | [diff] [blame] | 1002 | |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1003 | if (_mesa_bufferobj_mapped(bufObj)) { |
Brian Paul | a7f434b | 2009-02-27 13:04:38 -0700 | [diff] [blame] | 1004 | /* if mapped, unmap it now */ |
| 1005 | ctx->Driver.UnmapBuffer(ctx, 0, bufObj); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1006 | bufObj->AccessFlags = DEFAULT_ACCESS; |
Brian Paul | 67025f7 | 2009-02-27 13:10:45 -0700 | [diff] [blame] | 1007 | bufObj->Pointer = NULL; |
Brian Paul | a7f434b | 2009-02-27 13:04:38 -0700 | [diff] [blame] | 1008 | } |
| 1009 | |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 1010 | /* unbind any vertex pointers bound to this buffer */ |
Brian Paul | a65f385 | 2009-05-22 14:14:53 -0600 | [diff] [blame] | 1011 | unbind(ctx, &arrayObj->Vertex.BufferObj, bufObj); |
| 1012 | unbind(ctx, &arrayObj->Weight.BufferObj, bufObj); |
| 1013 | unbind(ctx, &arrayObj->Normal.BufferObj, bufObj); |
| 1014 | unbind(ctx, &arrayObj->Color.BufferObj, bufObj); |
| 1015 | unbind(ctx, &arrayObj->SecondaryColor.BufferObj, bufObj); |
| 1016 | unbind(ctx, &arrayObj->FogCoord.BufferObj, bufObj); |
| 1017 | unbind(ctx, &arrayObj->Index.BufferObj, bufObj); |
| 1018 | unbind(ctx, &arrayObj->EdgeFlag.BufferObj, bufObj); |
Brian Paul | ebb991c | 2009-05-22 14:16:00 -0600 | [diff] [blame] | 1019 | for (j = 0; j < Elements(arrayObj->TexCoord); j++) { |
Brian Paul | a65f385 | 2009-05-22 14:14:53 -0600 | [diff] [blame] | 1020 | unbind(ctx, &arrayObj->TexCoord[j].BufferObj, bufObj); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1021 | } |
Brian Paul | ebb991c | 2009-05-22 14:16:00 -0600 | [diff] [blame] | 1022 | for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) { |
Brian Paul | a65f385 | 2009-05-22 14:14:53 -0600 | [diff] [blame] | 1023 | unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj); |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 1024 | } |
| 1025 | |
| 1026 | if (ctx->Array.ArrayBufferObj == bufObj) { |
| 1027 | _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); |
| 1028 | } |
| 1029 | if (ctx->Array.ElementArrayBufferObj == bufObj) { |
| 1030 | _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); |
| 1031 | } |
| 1032 | |
Brian Paul | 395bcad | 2009-02-27 12:41:11 -0700 | [diff] [blame] | 1033 | /* unbind any pixel pack/unpack pointers bound to this buffer */ |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 1034 | if (ctx->Pack.BufferObj == bufObj) { |
| 1035 | _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 ); |
| 1036 | } |
| 1037 | if (ctx->Unpack.BufferObj == bufObj) { |
| 1038 | _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); |
| 1039 | } |
| 1040 | |
Brian | 4b654d4 | 2007-08-23 08:53:43 +0100 | [diff] [blame] | 1041 | /* The ID is immediately freed for re-use */ |
Brian Paul | 78587ea | 2010-11-11 15:31:28 -0700 | [diff] [blame^] | 1042 | _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]); |
Brian Paul | 37c74af | 2008-09-04 14:58:02 -0600 | [diff] [blame] | 1043 | _mesa_reference_buffer_object(ctx, &bufObj, NULL); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1044 | } |
| 1045 | } |
| 1046 | |
| 1047 | _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1048 | } |
| 1049 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1050 | |
| 1051 | /** |
| 1052 | * Generate a set of unique buffer object IDs and store them in \c buffer. |
| 1053 | * |
| 1054 | * \param n Number of IDs to generate. |
| 1055 | * \param buffer Array of \c n locations to store the IDs. |
| 1056 | */ |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1057 | void GLAPIENTRY |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1058 | _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1059 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1060 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1061 | GLuint first; |
| 1062 | GLint i; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1063 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1064 | |
| 1065 | if (n < 0) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1066 | _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1067 | return; |
| 1068 | } |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1069 | |
Brian Paul | a789252 | 2004-11-22 20:01:25 +0000 | [diff] [blame] | 1070 | if (!buffer) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1071 | return; |
| 1072 | } |
| 1073 | |
| 1074 | /* |
| 1075 | * This must be atomic (generation and allocation of buffer object IDs) |
| 1076 | */ |
| 1077 | _glthread_LOCK_MUTEX(ctx->Shared->Mutex); |
| 1078 | |
| 1079 | first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); |
| 1080 | |
Brian Paul | c552f27 | 2010-11-11 14:47:30 -0700 | [diff] [blame] | 1081 | /* Insert the ID and pointer to dummy buffer object into hash table */ |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1082 | for (i = 0; i < n; i++) { |
Brian Paul | c552f27 | 2010-11-11 14:47:30 -0700 | [diff] [blame] | 1083 | _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, |
| 1084 | &DummyBufferObject); |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1085 | buffer[i] = first + i; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1086 | } |
| 1087 | |
| 1088 | _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1089 | } |
| 1090 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1091 | |
| 1092 | /** |
| 1093 | * Determine if ID is the name of a buffer object. |
| 1094 | * |
| 1095 | * \param id ID of the potential buffer object. |
| 1096 | * \return \c GL_TRUE if \c id is the name of a buffer object, |
| 1097 | * \c GL_FALSE otherwise. |
| 1098 | */ |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1099 | GLboolean GLAPIENTRY |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1100 | _mesa_IsBufferARB(GLuint id) |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1101 | { |
Brian Paul | 4cb9fff | 2006-06-03 15:32:27 +0000 | [diff] [blame] | 1102 | struct gl_buffer_object *bufObj; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1103 | GET_CURRENT_CONTEXT(ctx); |
| 1104 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); |
| 1105 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1106 | _glthread_LOCK_MUTEX(ctx->Shared->Mutex); |
Brian Paul | 4d12a05 | 2006-08-23 23:10:14 +0000 | [diff] [blame] | 1107 | bufObj = _mesa_lookup_bufferobj(ctx, id); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1108 | _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); |
| 1109 | |
Brian Paul | c552f27 | 2010-11-11 14:47:30 -0700 | [diff] [blame] | 1110 | return bufObj && bufObj != &DummyBufferObject; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1111 | } |
| 1112 | |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1113 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1114 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1115 | _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, |
| 1116 | const GLvoid * data, GLenum usage) |
| 1117 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1118 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1119 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1120 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1121 | |
| 1122 | if (size < 0) { |
| 1123 | _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); |
| 1124 | return; |
| 1125 | } |
| 1126 | |
| 1127 | switch (usage) { |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1128 | case GL_STREAM_DRAW_ARB: |
| 1129 | case GL_STREAM_READ_ARB: |
| 1130 | case GL_STREAM_COPY_ARB: |
| 1131 | case GL_STATIC_DRAW_ARB: |
| 1132 | case GL_STATIC_READ_ARB: |
| 1133 | case GL_STATIC_COPY_ARB: |
| 1134 | case GL_DYNAMIC_DRAW_ARB: |
| 1135 | case GL_DYNAMIC_READ_ARB: |
| 1136 | case GL_DYNAMIC_COPY_ARB: |
| 1137 | /* OK */ |
| 1138 | break; |
| 1139 | default: |
| 1140 | _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)"); |
| 1141 | return; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1142 | } |
| 1143 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1144 | bufObj = get_buffer(ctx, target); |
| 1145 | if (!bufObj) { |
| 1146 | _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" ); |
| 1147 | return; |
| 1148 | } |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1149 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | f7ca97f | 2009-05-14 16:51:10 -0600 | [diff] [blame] | 1150 | _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB(buffer 0)" ); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1151 | return; |
| 1152 | } |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1153 | |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1154 | if (_mesa_bufferobj_mapped(bufObj)) { |
Brian Paul | 75e3ccf | 2009-02-27 12:30:21 -0700 | [diff] [blame] | 1155 | /* Unmap the existing buffer. We'll replace it now. Not an error. */ |
| 1156 | ctx->Driver.UnmapBuffer(ctx, target, bufObj); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1157 | bufObj->AccessFlags = DEFAULT_ACCESS; |
Brian Paul | 822c796 | 2009-08-31 08:59:38 -0600 | [diff] [blame] | 1158 | ASSERT(bufObj->Pointer == NULL); |
Brian Paul | 66e6e3e | 2003-09-17 21:18:22 +0000 | [diff] [blame] | 1159 | } |
| 1160 | |
Brian Paul | b9d0f94 | 2009-05-06 15:17:25 -0600 | [diff] [blame] | 1161 | FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); |
| 1162 | |
Brian Paul | dcca97a | 2009-05-06 15:23:09 -0600 | [diff] [blame] | 1163 | bufObj->Written = GL_TRUE; |
| 1164 | |
Brian Paul | e792762 | 2009-06-03 15:38:57 -0600 | [diff] [blame] | 1165 | #ifdef VBO_DEBUG |
Kristian Høgsberg | 298be2b | 2010-02-19 12:32:24 -0500 | [diff] [blame] | 1166 | printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n", |
Brian Paul | e792762 | 2009-06-03 15:38:57 -0600 | [diff] [blame] | 1167 | bufObj->Name, size, data, usage); |
| 1168 | #endif |
| 1169 | |
Brian Paul | 4a7fd63 | 2009-06-09 11:53:19 -0600 | [diff] [blame] | 1170 | #ifdef BOUNDS_CHECK |
| 1171 | size += 100; |
| 1172 | #endif |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 1173 | |
| 1174 | ASSERT(ctx->Driver.BufferData); |
| 1175 | if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) { |
Brian Paul | f338de4 | 2009-09-22 13:47:49 -0600 | [diff] [blame] | 1176 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()"); |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 1177 | } |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1178 | } |
| 1179 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1180 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1181 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1182 | _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, |
| 1183 | GLsizeiptrARB size, const GLvoid * data) |
| 1184 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1185 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1186 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1187 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1188 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1189 | bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1190 | "glBufferSubDataARB" ); |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1191 | if (!bufObj) { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 1192 | /* error already recorded */ |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1193 | return; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1194 | } |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1195 | |
Brian Paul | 6e2e136 | 2010-11-09 12:24:49 -0700 | [diff] [blame] | 1196 | if (size == 0) |
| 1197 | return; |
| 1198 | |
Brian Paul | dcca97a | 2009-05-06 15:23:09 -0600 | [diff] [blame] | 1199 | bufObj->Written = GL_TRUE; |
| 1200 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1201 | ASSERT(ctx->Driver.BufferSubData); |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 1202 | ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj ); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1203 | } |
| 1204 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1205 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1206 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1207 | _mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, |
| 1208 | GLsizeiptrARB size, void * data) |
| 1209 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1210 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1211 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1212 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1213 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1214 | bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1215 | "glGetBufferSubDataARB" ); |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1216 | if (!bufObj) { |
Brian Paul | 2daa413 | 2004-10-31 00:17:42 +0000 | [diff] [blame] | 1217 | /* error already recorded */ |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1218 | return; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1219 | } |
Brian Paul | 66e6e3e | 2003-09-17 21:18:22 +0000 | [diff] [blame] | 1220 | |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1221 | ASSERT(ctx->Driver.GetBufferSubData); |
Brian Paul | 6f172f7 | 2006-06-02 22:51:45 +0000 | [diff] [blame] | 1222 | ctx->Driver.GetBufferSubData( ctx, target, offset, size, data, bufObj ); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1223 | } |
| 1224 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1225 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1226 | void * GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1227 | _mesa_MapBufferARB(GLenum target, GLenum access) |
| 1228 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1229 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1230 | struct gl_buffer_object * bufObj; |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1231 | GLbitfield accessFlags; |
Brian Paul | 92033a9 | 2009-08-31 08:50:15 -0600 | [diff] [blame] | 1232 | void *map; |
| 1233 | |
Brian Paul | ea31ca4 | 2003-05-10 04:35:09 +0000 | [diff] [blame] | 1234 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1235 | |
| 1236 | switch (access) { |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1237 | case GL_READ_ONLY_ARB: |
| 1238 | accessFlags = GL_MAP_READ_BIT; |
| 1239 | break; |
| 1240 | case GL_WRITE_ONLY_ARB: |
| 1241 | accessFlags = GL_MAP_WRITE_BIT; |
| 1242 | break; |
| 1243 | case GL_READ_WRITE_ARB: |
| 1244 | accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; |
| 1245 | break; |
| 1246 | default: |
| 1247 | _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)"); |
| 1248 | return NULL; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1249 | } |
| 1250 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1251 | bufObj = get_buffer(ctx, target); |
| 1252 | if (!bufObj) { |
| 1253 | _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" ); |
| 1254 | return NULL; |
| 1255 | } |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1256 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | f7ca97f | 2009-05-14 16:51:10 -0600 | [diff] [blame] | 1257 | _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(buffer 0)" ); |
Brian Paul | ea31ca4 | 2003-05-10 04:35:09 +0000 | [diff] [blame] | 1258 | return NULL; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1259 | } |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1260 | if (_mesa_bufferobj_mapped(bufObj)) { |
Brian Paul | 66e6e3e | 2003-09-17 21:18:22 +0000 | [diff] [blame] | 1261 | _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1262 | return NULL; |
| 1263 | } |
| 1264 | |
| 1265 | ASSERT(ctx->Driver.MapBuffer); |
Brian Paul | 92033a9 | 2009-08-31 08:50:15 -0600 | [diff] [blame] | 1266 | map = ctx->Driver.MapBuffer( ctx, target, access, bufObj ); |
| 1267 | if (!map) { |
Brian Paul | f338de4 | 2009-09-22 13:47:49 -0600 | [diff] [blame] | 1268 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 1269 | return NULL; |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1270 | } |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 1271 | else { |
Brian Paul | 92033a9 | 2009-08-31 08:50:15 -0600 | [diff] [blame] | 1272 | /* The driver callback should have set these fields. |
| 1273 | * This is important because other modules (like VBO) might call |
| 1274 | * the driver function directly. |
| 1275 | */ |
| 1276 | ASSERT(bufObj->Pointer == map); |
| 1277 | ASSERT(bufObj->Length == bufObj->Size); |
| 1278 | ASSERT(bufObj->Offset == 0); |
| 1279 | bufObj->AccessFlags = accessFlags; |
| 1280 | } |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1281 | |
Brian Paul | dcca97a | 2009-05-06 15:23:09 -0600 | [diff] [blame] | 1282 | if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) |
| 1283 | bufObj->Written = GL_TRUE; |
Brian Paul | 0bb281b | 2003-10-14 15:48:39 +0000 | [diff] [blame] | 1284 | |
Brian Paul | e792762 | 2009-06-03 15:38:57 -0600 | [diff] [blame] | 1285 | #ifdef VBO_DEBUG |
Kristian Høgsberg | 298be2b | 2010-02-19 12:32:24 -0500 | [diff] [blame] | 1286 | printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n", |
| 1287 | bufObj->Name, bufObj->Size, access); |
Brian Paul | e792762 | 2009-06-03 15:38:57 -0600 | [diff] [blame] | 1288 | if (access == GL_WRITE_ONLY_ARB) { |
| 1289 | GLuint i; |
| 1290 | GLubyte *b = (GLubyte *) bufObj->Pointer; |
| 1291 | for (i = 0; i < bufObj->Size; i++) |
| 1292 | b[i] = i & 0xff; |
| 1293 | } |
| 1294 | #endif |
| 1295 | |
Brian Paul | 4a7fd63 | 2009-06-09 11:53:19 -0600 | [diff] [blame] | 1296 | #ifdef BOUNDS_CHECK |
| 1297 | { |
| 1298 | GLubyte *buf = (GLubyte *) bufObj->Pointer; |
| 1299 | GLuint i; |
| 1300 | /* buffer is 100 bytes larger than requested, fill with magic value */ |
| 1301 | for (i = 0; i < 100; i++) { |
| 1302 | buf[bufObj->Size - i - 1] = 123; |
| 1303 | } |
| 1304 | } |
| 1305 | #endif |
| 1306 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1307 | return bufObj->Pointer; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1308 | } |
| 1309 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1310 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1311 | GLboolean GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1312 | _mesa_UnmapBufferARB(GLenum target) |
| 1313 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1314 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1315 | struct gl_buffer_object *bufObj; |
| 1316 | GLboolean status = GL_TRUE; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1317 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); |
| 1318 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1319 | bufObj = get_buffer(ctx, target); |
| 1320 | if (!bufObj) { |
| 1321 | _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" ); |
| 1322 | return GL_FALSE; |
| 1323 | } |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1324 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1325 | _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" ); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1326 | return GL_FALSE; |
| 1327 | } |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1328 | if (!_mesa_bufferobj_mapped(bufObj)) { |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1329 | _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); |
| 1330 | return GL_FALSE; |
| 1331 | } |
| 1332 | |
Brian Paul | 4a7fd63 | 2009-06-09 11:53:19 -0600 | [diff] [blame] | 1333 | #ifdef BOUNDS_CHECK |
| 1334 | if (bufObj->Access != GL_READ_ONLY_ARB) { |
| 1335 | GLubyte *buf = (GLubyte *) bufObj->Pointer; |
| 1336 | GLuint i; |
| 1337 | /* check that last 100 bytes are still = magic value */ |
| 1338 | for (i = 0; i < 100; i++) { |
| 1339 | GLuint pos = bufObj->Size - i - 1; |
| 1340 | if (buf[pos] != 123) { |
| 1341 | _mesa_warning(ctx, "Out of bounds buffer object write detected" |
| 1342 | " at position %d (value = %u)\n", |
| 1343 | pos, buf[pos]); |
| 1344 | } |
| 1345 | } |
| 1346 | } |
| 1347 | #endif |
| 1348 | |
Brian Paul | e792762 | 2009-06-03 15:38:57 -0600 | [diff] [blame] | 1349 | #ifdef VBO_DEBUG |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1350 | if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) { |
Brian Paul | e792762 | 2009-06-03 15:38:57 -0600 | [diff] [blame] | 1351 | GLuint i, unchanged = 0; |
| 1352 | GLubyte *b = (GLubyte *) bufObj->Pointer; |
| 1353 | GLint pos = -1; |
| 1354 | /* check which bytes changed */ |
| 1355 | for (i = 0; i < bufObj->Size - 1; i++) { |
| 1356 | if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) { |
| 1357 | unchanged++; |
| 1358 | if (pos == -1) |
| 1359 | pos = i; |
| 1360 | } |
| 1361 | } |
| 1362 | if (unchanged) { |
Kristian Høgsberg | 298be2b | 2010-02-19 12:32:24 -0500 | [diff] [blame] | 1363 | printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n", |
Brian Paul | e792762 | 2009-06-03 15:38:57 -0600 | [diff] [blame] | 1364 | bufObj->Name, unchanged, bufObj->Size, pos); |
| 1365 | } |
| 1366 | } |
| 1367 | #endif |
| 1368 | |
Brian Paul | 67025f7 | 2009-02-27 13:10:45 -0700 | [diff] [blame] | 1369 | status = ctx->Driver.UnmapBuffer( ctx, target, bufObj ); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1370 | bufObj->AccessFlags = DEFAULT_ACCESS; |
Brian Paul | 822c796 | 2009-08-31 08:59:38 -0600 | [diff] [blame] | 1371 | ASSERT(bufObj->Pointer == NULL); |
| 1372 | ASSERT(bufObj->Offset == 0); |
| 1373 | ASSERT(bufObj->Length == 0); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1374 | |
| 1375 | return status; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1376 | } |
| 1377 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1378 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1379 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1380 | _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) |
| 1381 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1382 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1383 | struct gl_buffer_object *bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1384 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1385 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1386 | bufObj = get_buffer(ctx, target); |
| 1387 | if (!bufObj) { |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1388 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(target)" ); |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1389 | return; |
| 1390 | } |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1391 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1392 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameterivARB" ); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1393 | return; |
| 1394 | } |
| 1395 | |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1396 | switch (pname) { |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1397 | case GL_BUFFER_SIZE_ARB: |
| 1398 | *params = (GLint) bufObj->Size; |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1399 | return; |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1400 | case GL_BUFFER_USAGE_ARB: |
| 1401 | *params = bufObj->Usage; |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1402 | return; |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1403 | case GL_BUFFER_ACCESS_ARB: |
| 1404 | *params = simplified_access_mode(bufObj->AccessFlags); |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1405 | return; |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1406 | case GL_BUFFER_MAPPED_ARB: |
| 1407 | *params = _mesa_bufferobj_mapped(bufObj); |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1408 | return; |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1409 | case GL_BUFFER_ACCESS_FLAGS: |
| 1410 | if (ctx->VersionMajor < 3) |
| 1411 | goto invalid_pname; |
| 1412 | *params = bufObj->AccessFlags; |
| 1413 | return; |
| 1414 | case GL_BUFFER_MAP_OFFSET: |
| 1415 | if (ctx->VersionMajor < 3) |
| 1416 | goto invalid_pname; |
| 1417 | *params = (GLint) bufObj->Offset; |
| 1418 | return; |
| 1419 | case GL_BUFFER_MAP_LENGTH: |
| 1420 | if (ctx->VersionMajor < 3) |
| 1421 | goto invalid_pname; |
| 1422 | *params = (GLint) bufObj->Length; |
| 1423 | return; |
| 1424 | default: |
| 1425 | ; /* fall-through */ |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1426 | } |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1427 | |
| 1428 | invalid_pname: |
| 1429 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)", |
| 1430 | _mesa_lookup_enum_by_nr(pname)); |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1431 | } |
| 1432 | |
Brian Paul | c7b872a | 2003-09-09 13:44:40 +0000 | [diff] [blame] | 1433 | |
Brian Paul | 1fbc719 | 2010-01-01 17:50:02 -0700 | [diff] [blame] | 1434 | /** |
| 1435 | * New in GL 3.2 |
| 1436 | * This is pretty much a duplicate of GetBufferParameteriv() but the |
| 1437 | * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system. |
| 1438 | */ |
| 1439 | void GLAPIENTRY |
| 1440 | _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) |
| 1441 | { |
| 1442 | GET_CURRENT_CONTEXT(ctx); |
| 1443 | struct gl_buffer_object *bufObj; |
| 1444 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1445 | |
| 1446 | bufObj = get_buffer(ctx, target); |
| 1447 | if (!bufObj) { |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1448 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(target)" ); |
Brian Paul | 1fbc719 | 2010-01-01 17:50:02 -0700 | [diff] [blame] | 1449 | return; |
| 1450 | } |
| 1451 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1452 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferParameteri64v" ); |
Brian Paul | 1fbc719 | 2010-01-01 17:50:02 -0700 | [diff] [blame] | 1453 | return; |
| 1454 | } |
| 1455 | |
| 1456 | switch (pname) { |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1457 | case GL_BUFFER_SIZE_ARB: |
| 1458 | *params = bufObj->Size; |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1459 | return; |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1460 | case GL_BUFFER_USAGE_ARB: |
| 1461 | *params = bufObj->Usage; |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1462 | return; |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1463 | case GL_BUFFER_ACCESS_ARB: |
| 1464 | *params = simplified_access_mode(bufObj->AccessFlags); |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1465 | return; |
| 1466 | case GL_BUFFER_ACCESS_FLAGS: |
| 1467 | if (ctx->VersionMajor < 3) |
| 1468 | goto invalid_pname; |
| 1469 | *params = bufObj->AccessFlags; |
| 1470 | return; |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1471 | case GL_BUFFER_MAPPED_ARB: |
| 1472 | *params = _mesa_bufferobj_mapped(bufObj); |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1473 | return; |
| 1474 | case GL_BUFFER_MAP_OFFSET: |
| 1475 | if (ctx->VersionMajor < 3) |
| 1476 | goto invalid_pname; |
| 1477 | *params = bufObj->Offset; |
| 1478 | return; |
| 1479 | case GL_BUFFER_MAP_LENGTH: |
| 1480 | if (ctx->VersionMajor < 3) |
| 1481 | goto invalid_pname; |
| 1482 | *params = bufObj->Length; |
| 1483 | return; |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1484 | default: |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1485 | ; /* fall-through */ |
Brian Paul | 1fbc719 | 2010-01-01 17:50:02 -0700 | [diff] [blame] | 1486 | } |
Brian Paul | d6a9f5b | 2010-03-20 11:52:12 -0600 | [diff] [blame] | 1487 | |
| 1488 | invalid_pname: |
| 1489 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)", |
| 1490 | _mesa_lookup_enum_by_nr(pname)); |
Brian Paul | 1fbc719 | 2010-01-01 17:50:02 -0700 | [diff] [blame] | 1491 | } |
| 1492 | |
| 1493 | |
Kendall Bennett | c40d1dd | 2003-10-21 22:22:17 +0000 | [diff] [blame] | 1494 | void GLAPIENTRY |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1495 | _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) |
| 1496 | { |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1497 | GET_CURRENT_CONTEXT(ctx); |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1498 | struct gl_buffer_object * bufObj; |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1499 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1500 | |
| 1501 | if (pname != GL_BUFFER_MAP_POINTER_ARB) { |
| 1502 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)"); |
| 1503 | return; |
| 1504 | } |
| 1505 | |
Brian Paul | 4277ea4 | 2006-08-25 22:06:02 +0000 | [diff] [blame] | 1506 | bufObj = get_buffer(ctx, target); |
| 1507 | if (!bufObj) { |
| 1508 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" ); |
| 1509 | return; |
| 1510 | } |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1511 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | aa00d12 | 2003-09-15 19:55:10 +0000 | [diff] [blame] | 1512 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" ); |
Brian Paul | aac7325 | 2003-04-09 02:31:35 +0000 | [diff] [blame] | 1513 | return; |
| 1514 | } |
Ian Romanick | 0207b47 | 2003-09-09 00:10:12 +0000 | [diff] [blame] | 1515 | |
Brian Paul | 148a284 | 2003-09-17 03:40:11 +0000 | [diff] [blame] | 1516 | *params = bufObj->Pointer; |
Brian Paul | 6061df0 | 2003-03-29 17:01:00 +0000 | [diff] [blame] | 1517 | } |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1518 | |
| 1519 | |
| 1520 | void GLAPIENTRY |
| 1521 | _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, |
| 1522 | GLintptr readOffset, GLintptr writeOffset, |
| 1523 | GLsizeiptr size) |
| 1524 | { |
| 1525 | GET_CURRENT_CONTEXT(ctx); |
| 1526 | struct gl_buffer_object *src, *dst; |
| 1527 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1528 | |
| 1529 | src = get_buffer(ctx, readTarget); |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1530 | if (!src || !_mesa_is_bufferobj(src)) { |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1531 | _mesa_error(ctx, GL_INVALID_ENUM, |
| 1532 | "glCopyBuffserSubData(readTarget = 0x%x)", readTarget); |
| 1533 | return; |
| 1534 | } |
| 1535 | |
| 1536 | dst = get_buffer(ctx, writeTarget); |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1537 | if (!dst || !_mesa_is_bufferobj(dst)) { |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1538 | _mesa_error(ctx, GL_INVALID_ENUM, |
| 1539 | "glCopyBuffserSubData(writeTarget = 0x%x)", writeTarget); |
| 1540 | return; |
| 1541 | } |
| 1542 | |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1543 | if (_mesa_bufferobj_mapped(src)) { |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1544 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1545 | "glCopyBuffserSubData(readBuffer is mapped)"); |
| 1546 | return; |
| 1547 | } |
| 1548 | |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1549 | if (_mesa_bufferobj_mapped(dst)) { |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1550 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1551 | "glCopyBuffserSubData(writeBuffer is mapped)"); |
| 1552 | return; |
| 1553 | } |
| 1554 | |
| 1555 | if (readOffset < 0) { |
| 1556 | _mesa_error(ctx, GL_INVALID_VALUE, |
Brian Paul | 9eca0e2 | 2010-09-02 07:57:16 -0600 | [diff] [blame] | 1557 | "glCopyBuffserSubData(readOffset = %d)", (int) readOffset); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1558 | return; |
| 1559 | } |
| 1560 | |
| 1561 | if (writeOffset < 0) { |
| 1562 | _mesa_error(ctx, GL_INVALID_VALUE, |
Brian Paul | 9eca0e2 | 2010-09-02 07:57:16 -0600 | [diff] [blame] | 1563 | "glCopyBuffserSubData(writeOffset = %d)", (int) writeOffset); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1564 | return; |
| 1565 | } |
| 1566 | |
| 1567 | if (readOffset + size > src->Size) { |
| 1568 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1569 | "glCopyBuffserSubData(readOffset + size = %d)", |
Brian Paul | 9eca0e2 | 2010-09-02 07:57:16 -0600 | [diff] [blame] | 1570 | (int) (readOffset + size)); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1571 | return; |
| 1572 | } |
| 1573 | |
Brian Paul | 2813c08 | 2009-06-02 21:23:28 -0600 | [diff] [blame] | 1574 | if (writeOffset + size > dst->Size) { |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1575 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1576 | "glCopyBuffserSubData(writeOffset + size = %d)", |
Brian Paul | 9eca0e2 | 2010-09-02 07:57:16 -0600 | [diff] [blame] | 1577 | (int) (writeOffset + size)); |
Brian Paul | dc0b71f | 2009-06-02 20:29:57 -0600 | [diff] [blame] | 1578 | return; |
| 1579 | } |
| 1580 | |
| 1581 | if (src == dst) { |
| 1582 | if (readOffset + size <= writeOffset) { |
| 1583 | /* OK */ |
| 1584 | } |
| 1585 | else if (writeOffset + size <= readOffset) { |
| 1586 | /* OK */ |
| 1587 | } |
| 1588 | else { |
| 1589 | /* overlapping src/dst is illegal */ |
| 1590 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1591 | "glCopyBuffserSubData(overlapping src/dst)"); |
| 1592 | return; |
| 1593 | } |
| 1594 | } |
| 1595 | |
| 1596 | ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size); |
| 1597 | } |
| 1598 | |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1599 | |
| 1600 | /** |
| 1601 | * See GL_ARB_map_buffer_range spec |
| 1602 | */ |
| 1603 | void * GLAPIENTRY |
| 1604 | _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, |
| 1605 | GLbitfield access) |
| 1606 | { |
| 1607 | GET_CURRENT_CONTEXT(ctx); |
| 1608 | struct gl_buffer_object *bufObj; |
Brian Paul | 92033a9 | 2009-08-31 08:50:15 -0600 | [diff] [blame] | 1609 | void *map; |
| 1610 | |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1611 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); |
| 1612 | |
| 1613 | if (!ctx->Extensions.ARB_map_buffer_range) { |
| 1614 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1615 | "glMapBufferRange(extension not supported)"); |
| 1616 | return NULL; |
| 1617 | } |
| 1618 | |
| 1619 | if (offset < 0) { |
| 1620 | _mesa_error(ctx, GL_INVALID_VALUE, |
Eric Anholt | 86af037 | 2010-09-01 14:46:22 -0700 | [diff] [blame] | 1621 | "glMapBufferRange(offset = %ld)", (long)offset); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1622 | return NULL; |
| 1623 | } |
| 1624 | |
| 1625 | if (length < 0) { |
| 1626 | _mesa_error(ctx, GL_INVALID_VALUE, |
Eric Anholt | 86af037 | 2010-09-01 14:46:22 -0700 | [diff] [blame] | 1627 | "glMapBufferRange(length = %ld)", (long)length); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1628 | return NULL; |
| 1629 | } |
| 1630 | |
| 1631 | if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) { |
| 1632 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1633 | "glMapBufferRange(access indicates neither read or write)"); |
| 1634 | return NULL; |
| 1635 | } |
| 1636 | |
| 1637 | if (access & GL_MAP_READ_BIT) { |
| 1638 | if ((access & GL_MAP_INVALIDATE_RANGE_BIT) || |
| 1639 | (access & GL_MAP_INVALIDATE_BUFFER_BIT) || |
| 1640 | (access & GL_MAP_UNSYNCHRONIZED_BIT)) { |
| 1641 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1642 | "glMapBufferRange(invalid access flags)"); |
| 1643 | return NULL; |
| 1644 | } |
| 1645 | } |
| 1646 | |
| 1647 | if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) && |
| 1648 | ((access & GL_MAP_WRITE_BIT) == 0)) { |
| 1649 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1650 | "glMapBufferRange(invalid access flags)"); |
| 1651 | return NULL; |
| 1652 | } |
| 1653 | |
| 1654 | bufObj = get_buffer(ctx, target); |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1655 | if (!bufObj || !_mesa_is_bufferobj(bufObj)) { |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1656 | _mesa_error(ctx, GL_INVALID_ENUM, |
| 1657 | "glMapBufferRange(target = 0x%x)", target); |
| 1658 | return NULL; |
| 1659 | } |
| 1660 | |
| 1661 | if (offset + length > bufObj->Size) { |
| 1662 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1663 | "glMapBufferRange(offset + length > size)"); |
| 1664 | return NULL; |
| 1665 | } |
| 1666 | |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1667 | if (_mesa_bufferobj_mapped(bufObj)) { |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1668 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1669 | "glMapBufferRange(buffer already mapped)"); |
| 1670 | return NULL; |
| 1671 | } |
| 1672 | |
| 1673 | ASSERT(ctx->Driver.MapBufferRange); |
Brian Paul | 92033a9 | 2009-08-31 08:50:15 -0600 | [diff] [blame] | 1674 | map = ctx->Driver.MapBufferRange(ctx, target, offset, length, |
| 1675 | access, bufObj); |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 1676 | if (!map) { |
Brian Paul | f338de4 | 2009-09-22 13:47:49 -0600 | [diff] [blame] | 1677 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); |
Brian Paul | 2f6d2a9 | 2009-09-03 09:41:41 -0600 | [diff] [blame] | 1678 | } |
| 1679 | else { |
Brian Paul | 92033a9 | 2009-08-31 08:50:15 -0600 | [diff] [blame] | 1680 | /* The driver callback should have set all these fields. |
| 1681 | * This is important because other modules (like VBO) might call |
| 1682 | * the driver function directly. |
| 1683 | */ |
| 1684 | ASSERT(bufObj->Pointer == map); |
| 1685 | ASSERT(bufObj->Length == length); |
| 1686 | ASSERT(bufObj->Offset == offset); |
| 1687 | ASSERT(bufObj->AccessFlags == access); |
| 1688 | } |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1689 | |
Brian Paul | 92033a9 | 2009-08-31 08:50:15 -0600 | [diff] [blame] | 1690 | return map; |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1691 | } |
| 1692 | |
| 1693 | |
| 1694 | /** |
| 1695 | * See GL_ARB_map_buffer_range spec |
| 1696 | */ |
| 1697 | void GLAPIENTRY |
| 1698 | _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) |
| 1699 | { |
| 1700 | GET_CURRENT_CONTEXT(ctx); |
| 1701 | struct gl_buffer_object *bufObj; |
| 1702 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
| 1703 | |
| 1704 | if (!ctx->Extensions.ARB_map_buffer_range) { |
| 1705 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1706 | "glMapBufferRange(extension not supported)"); |
| 1707 | return; |
| 1708 | } |
| 1709 | |
| 1710 | if (offset < 0) { |
| 1711 | _mesa_error(ctx, GL_INVALID_VALUE, |
Eric Anholt | 86af037 | 2010-09-01 14:46:22 -0700 | [diff] [blame] | 1712 | "glMapBufferRange(offset = %ld)", (long)offset); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1713 | return; |
| 1714 | } |
| 1715 | |
| 1716 | if (length < 0) { |
| 1717 | _mesa_error(ctx, GL_INVALID_VALUE, |
Eric Anholt | 86af037 | 2010-09-01 14:46:22 -0700 | [diff] [blame] | 1718 | "glMapBufferRange(length = %ld)", (long)length); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1719 | return; |
| 1720 | } |
| 1721 | |
| 1722 | bufObj = get_buffer(ctx, target); |
| 1723 | if (!bufObj) { |
| 1724 | _mesa_error(ctx, GL_INVALID_ENUM, |
| 1725 | "glMapBufferRange(target = 0x%x)", target); |
| 1726 | return; |
| 1727 | } |
| 1728 | |
Brian Paul | 6040315 | 2009-08-12 13:46:03 -0600 | [diff] [blame] | 1729 | if (!_mesa_is_bufferobj(bufObj)) { |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1730 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1731 | "glMapBufferRange(current buffer is 0)"); |
| 1732 | return; |
| 1733 | } |
| 1734 | |
Brian Paul | 7bf6efe | 2009-08-07 09:40:37 -0600 | [diff] [blame] | 1735 | if (!_mesa_bufferobj_mapped(bufObj)) { |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1736 | /* buffer is not mapped */ |
| 1737 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1738 | "glMapBufferRange(buffer is not mapped)"); |
| 1739 | return; |
| 1740 | } |
| 1741 | |
| 1742 | if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { |
| 1743 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1744 | "glMapBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)"); |
| 1745 | return; |
| 1746 | } |
| 1747 | |
| 1748 | if (offset + length > bufObj->Length) { |
| 1749 | _mesa_error(ctx, GL_INVALID_VALUE, |
Eric Anholt | 86af037 | 2010-09-01 14:46:22 -0700 | [diff] [blame] | 1750 | "glMapBufferRange(offset %ld + length %ld > mapped length %ld)", |
| 1751 | (long)offset, (long)length, (long)bufObj->Length); |
Brian Paul | e75b283 | 2009-06-08 17:02:36 -0600 | [diff] [blame] | 1752 | return; |
| 1753 | } |
| 1754 | |
| 1755 | ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT); |
| 1756 | |
| 1757 | if (ctx->Driver.FlushMappedBufferRange) |
| 1758 | ctx->Driver.FlushMappedBufferRange(ctx, target, offset, length, bufObj); |
| 1759 | } |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1760 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1761 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1762 | #if FEATURE_APPLE_object_purgeable |
| 1763 | static GLenum |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 1764 | _mesa_BufferObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1765 | { |
| 1766 | struct gl_buffer_object *bufObj; |
| 1767 | GLenum retval; |
| 1768 | |
| 1769 | bufObj = _mesa_lookup_bufferobj(ctx, name); |
| 1770 | if (!bufObj) { |
| 1771 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1772 | "glObjectPurgeable(name = 0x%x)", name); |
| 1773 | return 0; |
| 1774 | } |
| 1775 | if (!_mesa_is_bufferobj(bufObj)) { |
| 1776 | _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(buffer 0)" ); |
| 1777 | return 0; |
| 1778 | } |
| 1779 | |
| 1780 | if (bufObj->Purgeable) { |
| 1781 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1782 | "glObjectPurgeable(name = 0x%x) is already purgeable", name); |
| 1783 | return GL_VOLATILE_APPLE; |
| 1784 | } |
| 1785 | |
| 1786 | bufObj->Purgeable = GL_TRUE; |
| 1787 | |
| 1788 | retval = GL_VOLATILE_APPLE; |
| 1789 | if (ctx->Driver.BufferObjectPurgeable) |
| 1790 | retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option); |
| 1791 | |
| 1792 | return retval; |
| 1793 | } |
| 1794 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1795 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1796 | static GLenum |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 1797 | _mesa_RenderObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1798 | { |
| 1799 | struct gl_renderbuffer *bufObj; |
| 1800 | GLenum retval; |
| 1801 | |
| 1802 | bufObj = _mesa_lookup_renderbuffer(ctx, name); |
| 1803 | if (!bufObj) { |
| 1804 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1805 | "glObjectUnpurgeable(name = 0x%x)", name); |
| 1806 | return 0; |
| 1807 | } |
| 1808 | |
| 1809 | if (bufObj->Purgeable) { |
| 1810 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1811 | "glObjectPurgeable(name = 0x%x) is already purgeable", name); |
| 1812 | return GL_VOLATILE_APPLE; |
| 1813 | } |
| 1814 | |
| 1815 | bufObj->Purgeable = GL_TRUE; |
| 1816 | |
| 1817 | retval = GL_VOLATILE_APPLE; |
| 1818 | if (ctx->Driver.RenderObjectPurgeable) |
| 1819 | retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option); |
| 1820 | |
| 1821 | return retval; |
| 1822 | } |
| 1823 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1824 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1825 | static GLenum |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 1826 | _mesa_TextureObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1827 | { |
| 1828 | struct gl_texture_object *bufObj; |
| 1829 | GLenum retval; |
| 1830 | |
| 1831 | bufObj = _mesa_lookup_texture(ctx, name); |
| 1832 | if (!bufObj) { |
| 1833 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1834 | "glObjectPurgeable(name = 0x%x)", name); |
| 1835 | return 0; |
| 1836 | } |
| 1837 | |
| 1838 | if (bufObj->Purgeable) { |
| 1839 | _mesa_error(ctx, GL_INVALID_OPERATION, |
| 1840 | "glObjectPurgeable(name = 0x%x) is already purgeable", name); |
| 1841 | return GL_VOLATILE_APPLE; |
| 1842 | } |
| 1843 | |
| 1844 | bufObj->Purgeable = GL_TRUE; |
| 1845 | |
| 1846 | retval = GL_VOLATILE_APPLE; |
| 1847 | if (ctx->Driver.TextureObjectPurgeable) |
| 1848 | retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option); |
| 1849 | |
| 1850 | return retval; |
| 1851 | } |
| 1852 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1853 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1854 | GLenum GLAPIENTRY |
| 1855 | _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) |
| 1856 | { |
Chris Wilson | 24f9011 | 2010-03-05 23:10:45 +0000 | [diff] [blame] | 1857 | GLenum retval; |
| 1858 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1859 | GET_CURRENT_CONTEXT(ctx); |
| 1860 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); |
| 1861 | |
| 1862 | if (name == 0) { |
| 1863 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1864 | "glObjectPurgeable(name = 0x%x)", name); |
| 1865 | return 0; |
| 1866 | } |
| 1867 | |
| 1868 | switch (option) { |
| 1869 | case GL_VOLATILE_APPLE: |
| 1870 | case GL_RELEASED_APPLE: |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1871 | /* legal */ |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1872 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1873 | default: |
| 1874 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1875 | "glObjectPurgeable(name = 0x%x) invalid option: %d", |
| 1876 | name, option); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1877 | return 0; |
| 1878 | } |
| 1879 | |
| 1880 | switch (objectType) { |
| 1881 | case GL_TEXTURE: |
Chris Wilson | 24f9011 | 2010-03-05 23:10:45 +0000 | [diff] [blame] | 1882 | retval = _mesa_TextureObjectPurgeable (ctx, name, option); |
| 1883 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1884 | case GL_RENDERBUFFER_EXT: |
Chris Wilson | 24f9011 | 2010-03-05 23:10:45 +0000 | [diff] [blame] | 1885 | retval = _mesa_RenderObjectPurgeable (ctx, name, option); |
| 1886 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1887 | case GL_BUFFER_OBJECT_APPLE: |
Chris Wilson | 24f9011 | 2010-03-05 23:10:45 +0000 | [diff] [blame] | 1888 | retval = _mesa_BufferObjectPurgeable (ctx, name, option); |
| 1889 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1890 | default: |
| 1891 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1892 | "glObjectPurgeable(name = 0x%x) invalid type: %d", |
| 1893 | name, objectType); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1894 | return 0; |
| 1895 | } |
Chris Wilson | 24f9011 | 2010-03-05 23:10:45 +0000 | [diff] [blame] | 1896 | |
| 1897 | /* In strict conformance to the spec, we must only return VOLATILE when |
| 1898 | * when passed the VOLATILE option. Madness. |
| 1899 | * |
| 1900 | * XXX First fix the spec, then fix me. |
| 1901 | */ |
| 1902 | return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1903 | } |
| 1904 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1905 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1906 | static GLenum |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 1907 | _mesa_BufferObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1908 | { |
| 1909 | struct gl_buffer_object *bufObj; |
| 1910 | GLenum retval; |
| 1911 | |
| 1912 | bufObj = _mesa_lookup_bufferobj(ctx, name); |
| 1913 | if (!bufObj) { |
| 1914 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1915 | "glObjectUnpurgeable(name = 0x%x)", name); |
| 1916 | return 0; |
| 1917 | } |
| 1918 | |
| 1919 | if (! bufObj->Purgeable) { |
| 1920 | _mesa_error(ctx, GL_INVALID_OPERATION, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1921 | "glObjectUnpurgeable(name = 0x%x) object is " |
| 1922 | " already \"unpurged\"", name); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1923 | return 0; |
| 1924 | } |
| 1925 | |
| 1926 | bufObj->Purgeable = GL_FALSE; |
| 1927 | |
Brian Paul | 2f4ce25 | 2010-07-14 15:11:32 -0600 | [diff] [blame] | 1928 | retval = option; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1929 | if (ctx->Driver.BufferObjectUnpurgeable) |
| 1930 | retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option); |
| 1931 | |
| 1932 | return retval; |
| 1933 | } |
| 1934 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1935 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1936 | static GLenum |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 1937 | _mesa_RenderObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1938 | { |
| 1939 | struct gl_renderbuffer *bufObj; |
| 1940 | GLenum retval; |
| 1941 | |
| 1942 | bufObj = _mesa_lookup_renderbuffer(ctx, name); |
| 1943 | if (!bufObj) { |
| 1944 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1945 | "glObjectUnpurgeable(name = 0x%x)", name); |
| 1946 | return 0; |
| 1947 | } |
| 1948 | |
| 1949 | if (! bufObj->Purgeable) { |
| 1950 | _mesa_error(ctx, GL_INVALID_OPERATION, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1951 | "glObjectUnpurgeable(name = 0x%x) object is " |
| 1952 | " already \"unpurged\"", name); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1953 | return 0; |
| 1954 | } |
| 1955 | |
| 1956 | bufObj->Purgeable = GL_FALSE; |
| 1957 | |
Brian Paul | 2f4ce25 | 2010-07-14 15:11:32 -0600 | [diff] [blame] | 1958 | retval = option; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1959 | if (ctx->Driver.RenderObjectUnpurgeable) |
| 1960 | retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option); |
| 1961 | |
Brian Paul | 41bcd8c | 2010-07-16 07:36:19 -0600 | [diff] [blame] | 1962 | return retval; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1963 | } |
| 1964 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1965 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1966 | static GLenum |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 1967 | _mesa_TextureObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1968 | { |
| 1969 | struct gl_texture_object *bufObj; |
| 1970 | GLenum retval; |
| 1971 | |
| 1972 | bufObj = _mesa_lookup_texture(ctx, name); |
| 1973 | if (!bufObj) { |
| 1974 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 1975 | "glObjectUnpurgeable(name = 0x%x)", name); |
| 1976 | return 0; |
| 1977 | } |
| 1978 | |
| 1979 | if (! bufObj->Purgeable) { |
| 1980 | _mesa_error(ctx, GL_INVALID_OPERATION, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1981 | "glObjectUnpurgeable(name = 0x%x) object is" |
| 1982 | " already \"unpurged\"", name); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1983 | return 0; |
| 1984 | } |
| 1985 | |
| 1986 | bufObj->Purgeable = GL_FALSE; |
| 1987 | |
Brian Paul | 2f4ce25 | 2010-07-14 15:11:32 -0600 | [diff] [blame] | 1988 | retval = option; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1989 | if (ctx->Driver.TextureObjectUnpurgeable) |
| 1990 | retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option); |
| 1991 | |
| 1992 | return retval; |
| 1993 | } |
| 1994 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 1995 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 1996 | GLenum GLAPIENTRY |
| 1997 | _mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) |
| 1998 | { |
| 1999 | GET_CURRENT_CONTEXT(ctx); |
| 2000 | ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0); |
| 2001 | |
| 2002 | if (name == 0) { |
| 2003 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 2004 | "glObjectUnpurgeable(name = 0x%x)", name); |
| 2005 | return 0; |
| 2006 | } |
| 2007 | |
| 2008 | switch (option) { |
| 2009 | case GL_RETAINED_APPLE: |
| 2010 | case GL_UNDEFINED_APPLE: |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2011 | /* legal */ |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2012 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2013 | default: |
| 2014 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2015 | "glObjectUnpurgeable(name = 0x%x) invalid option: %d", |
| 2016 | name, option); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2017 | return 0; |
| 2018 | } |
| 2019 | |
| 2020 | switch (objectType) { |
| 2021 | case GL_BUFFER_OBJECT_APPLE: |
| 2022 | return _mesa_BufferObjectUnpurgeable(ctx, name, option); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2023 | case GL_TEXTURE: |
| 2024 | return _mesa_TextureObjectUnpurgeable(ctx, name, option); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2025 | case GL_RENDERBUFFER_EXT: |
| 2026 | return _mesa_RenderObjectUnpurgeable(ctx, name, option); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2027 | default: |
| 2028 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2029 | "glObjectUnpurgeable(name = 0x%x) invalid type: %d", |
| 2030 | name, objectType); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2031 | return 0; |
| 2032 | } |
| 2033 | } |
| 2034 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2035 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2036 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 2037 | _mesa_GetBufferObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2038 | GLenum pname, GLint* params) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2039 | { |
| 2040 | struct gl_buffer_object *bufObj; |
| 2041 | |
| 2042 | bufObj = _mesa_lookup_bufferobj(ctx, name); |
| 2043 | if (!bufObj) { |
| 2044 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 2045 | "glGetObjectParameteriv(name = 0x%x) invalid object", name); |
| 2046 | return; |
| 2047 | } |
| 2048 | |
| 2049 | switch (pname) { |
| 2050 | case GL_PURGEABLE_APPLE: |
| 2051 | *params = bufObj->Purgeable; |
| 2052 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2053 | default: |
| 2054 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2055 | "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", |
| 2056 | name, pname); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2057 | break; |
| 2058 | } |
| 2059 | } |
| 2060 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2061 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2062 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 2063 | _mesa_GetRenderObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2064 | GLenum pname, GLint* params) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2065 | { |
| 2066 | struct gl_renderbuffer *bufObj; |
| 2067 | |
| 2068 | bufObj = _mesa_lookup_renderbuffer(ctx, name); |
| 2069 | if (!bufObj) { |
| 2070 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 2071 | "glObjectUnpurgeable(name = 0x%x)", name); |
| 2072 | return; |
| 2073 | } |
| 2074 | |
| 2075 | switch (pname) { |
| 2076 | case GL_PURGEABLE_APPLE: |
| 2077 | *params = bufObj->Purgeable; |
| 2078 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2079 | default: |
| 2080 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2081 | "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", |
| 2082 | name, pname); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2083 | break; |
| 2084 | } |
| 2085 | } |
| 2086 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2087 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2088 | static void |
Kristian Høgsberg | f9995b3 | 2010-10-12 12:26:10 -0400 | [diff] [blame] | 2089 | _mesa_GetTextureObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2090 | GLenum pname, GLint* params) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2091 | { |
| 2092 | struct gl_texture_object *bufObj; |
| 2093 | |
| 2094 | bufObj = _mesa_lookup_texture(ctx, name); |
| 2095 | if (!bufObj) { |
| 2096 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 2097 | "glObjectUnpurgeable(name = 0x%x)", name); |
| 2098 | return; |
| 2099 | } |
| 2100 | |
| 2101 | switch (pname) { |
| 2102 | case GL_PURGEABLE_APPLE: |
| 2103 | *params = bufObj->Purgeable; |
| 2104 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2105 | default: |
| 2106 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2107 | "glGetObjectParameteriv(name = 0x%x) invalid enum: %d", |
| 2108 | name, pname); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2109 | break; |
| 2110 | } |
| 2111 | } |
| 2112 | |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2113 | |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2114 | void GLAPIENTRY |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2115 | _mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, |
| 2116 | GLint* params) |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2117 | { |
| 2118 | GET_CURRENT_CONTEXT(ctx); |
| 2119 | |
| 2120 | if (name == 0) { |
| 2121 | _mesa_error(ctx, GL_INVALID_VALUE, |
| 2122 | "glGetObjectParameteriv(name = 0x%x)", name); |
| 2123 | return; |
| 2124 | } |
| 2125 | |
| 2126 | switch (objectType) { |
| 2127 | case GL_TEXTURE: |
| 2128 | _mesa_GetTextureObjectParameterivAPPLE (ctx, name, pname, params); |
| 2129 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2130 | case GL_BUFFER_OBJECT_APPLE: |
| 2131 | _mesa_GetBufferObjectParameterivAPPLE (ctx, name, pname, params); |
| 2132 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2133 | case GL_RENDERBUFFER_EXT: |
| 2134 | _mesa_GetRenderObjectParameterivAPPLE (ctx, name, pname, params); |
| 2135 | break; |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2136 | default: |
| 2137 | _mesa_error(ctx, GL_INVALID_ENUM, |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2138 | "glGetObjectParameteriv(name = 0x%x) invalid type: %d", |
| 2139 | name, objectType); |
Chris Wilson | 99864d5 | 2009-11-13 12:19:35 +0000 | [diff] [blame] | 2140 | } |
| 2141 | } |
Brian Paul | e176ae5 | 2010-03-05 09:23:43 -0700 | [diff] [blame] | 2142 | |
| 2143 | #endif /* FEATURE_APPLE_object_purgeable */ |