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