blob: a983376251825f35e485ae452234892e340b5b1c [file] [log] [blame]
Brian Paul6061df02003-03-29 17:01:00 +00001/*
2 * Mesa 3-D graphics library
Brian Paul395bcad2009-02-27 12:41:11 -07003 * Version: 7.5
Brian Paul6061df02003-03-29 17:01:00 +00004 *
Briana429a252008-03-21 13:41:00 -06005 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
Brian Paul395bcad2009-02-27 12:41:11 -07006 * Copyright (C) 1999-2009 VMware, Inc. All Rights Reserved.
Brian Paul6061df02003-03-29 17:01:00 +00007 *
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 Paul395bcad2009-02-27 12:41:11 -070029 * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
Brian Paulaa00d122003-09-15 19:55:10 +000030 * \author Brian Paul, Ian Romanick
Brian Paul6061df02003-03-29 17:01:00 +000031 */
32
33
34#include "glheader.h"
Ian Romanick0207b472003-09-09 00:10:12 +000035#include "hash.h"
Brian Paul6061df02003-03-29 17:01:00 +000036#include "imports.h"
Brian Paul7a6b71e2004-03-13 18:21:40 +000037#include "image.h"
Brian Paulaac73252003-04-09 02:31:35 +000038#include "context.h"
Brian Paul6061df02003-03-29 17:01:00 +000039#include "bufferobj.h"
40
Brian Paulc7b872a2003-09-09 13:44:40 +000041
Brian Paul6c72bc82008-09-25 11:46:27 -060042#ifdef FEATURE_OES_mapbuffer
43#define DEFAULT_ACCESS GL_WRITE_ONLY;
44#else
45#define DEFAULT_ACCESS GL_READ_WRITE;
46#endif
47
48
Ian Romanick0207b472003-09-09 00:10:12 +000049/**
50 * Get the buffer object bound to the specified target in a GL context.
51 *
52 * \param ctx GL context
53 * \param target Buffer object target to be retrieved. Currently this must
54 * be either \c GL_ARRAY_BUFFER or \c GL_ELEMENT_ARRAY_BUFFER.
Ian Romanick0207b472003-09-09 00:10:12 +000055 * \return A pointer to the buffer object bound to \c target in the
Brian Paul4277ea42006-08-25 22:06:02 +000056 * specified context or \c NULL if \c target is invalid.
Ian Romanick0207b472003-09-09 00:10:12 +000057 */
Brian Paulc7b872a2003-09-09 13:44:40 +000058static INLINE struct gl_buffer_object *
Brian Paul4277ea42006-08-25 22:06:02 +000059get_buffer(GLcontext *ctx, GLenum target)
Ian Romanick0207b472003-09-09 00:10:12 +000060{
61 struct gl_buffer_object * bufObj = NULL;
62
63 switch (target) {
64 case GL_ARRAY_BUFFER_ARB:
Brian Paul148a2842003-09-17 03:40:11 +000065 bufObj = ctx->Array.ArrayBufferObj;
Ian Romanick0207b472003-09-09 00:10:12 +000066 break;
67 case GL_ELEMENT_ARRAY_BUFFER_ARB:
Brian Paul148a2842003-09-17 03:40:11 +000068 bufObj = ctx->Array.ElementArrayBufferObj;
Ian Romanick0207b472003-09-09 00:10:12 +000069 break;
Brian Paul7a6b71e2004-03-13 18:21:40 +000070 case GL_PIXEL_PACK_BUFFER_EXT:
71 bufObj = ctx->Pack.BufferObj;
72 break;
73 case GL_PIXEL_UNPACK_BUFFER_EXT:
74 bufObj = ctx->Unpack.BufferObj;
75 break;
Ian Romanick0207b472003-09-09 00:10:12 +000076 default:
Brian Paul4277ea42006-08-25 22:06:02 +000077 /* error must be recorded by caller */
Brian Paul4b6f6e12003-10-14 14:49:39 +000078 return NULL;
Ian Romanick0207b472003-09-09 00:10:12 +000079 }
Brian Paul148a2842003-09-17 03:40:11 +000080
Brian Paul4277ea42006-08-25 22:06:02 +000081 /* bufObj should point to NullBufferObj or a user-created buffer object */
82 ASSERT(bufObj);
Brian Paul148a2842003-09-17 03:40:11 +000083
Ian Romanick0207b472003-09-09 00:10:12 +000084 return bufObj;
85}
86
87
88/**
89 * Tests the subdata range parameters and sets the GL error code for
90 * \c glBufferSubDataARB and \c glGetBufferSubDataARB.
91 *
92 * \param ctx GL context.
93 * \param target Buffer object target on which to operate.
94 * \param offset Offset of the first byte of the subdata range.
95 * \param size Size, in bytes, of the subdata range.
Brian Paul6f172f72006-06-02 22:51:45 +000096 * \param caller Name of calling function for recording errors.
Ian Romanick0207b472003-09-09 00:10:12 +000097 * \return A pointer to the buffer object bound to \c target in the
98 * specified context or \c NULL if any of the parameter or state
99 * conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB
100 * are invalid.
101 *
102 * \sa glBufferSubDataARB, glGetBufferSubDataARB
103 */
Ian Romanick0207b472003-09-09 00:10:12 +0000104static struct gl_buffer_object *
Brian Paulc7b872a2003-09-09 13:44:40 +0000105buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
106 GLintptrARB offset, GLsizeiptrARB size,
Brian Paul6f172f72006-06-02 22:51:45 +0000107 const char *caller )
Ian Romanick0207b472003-09-09 00:10:12 +0000108{
109 struct gl_buffer_object *bufObj;
110
111 if (size < 0) {
Brian Paul6f172f72006-06-02 22:51:45 +0000112 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
Ian Romanick0207b472003-09-09 00:10:12 +0000113 return NULL;
114 }
115
116 if (offset < 0) {
Brian Paul6f172f72006-06-02 22:51:45 +0000117 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
Ian Romanick0207b472003-09-09 00:10:12 +0000118 return NULL;
119 }
120
Brian Paul4277ea42006-08-25 22:06:02 +0000121 bufObj = get_buffer(ctx, target);
122 if (!bufObj) {
123 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller);
Ian Romanick0207b472003-09-09 00:10:12 +0000124 return NULL;
125 }
Brian Paul4277ea42006-08-25 22:06:02 +0000126 if (bufObj->Name == 0) {
127 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
128 return NULL;
129 }
Brian7e85b0a2007-01-23 12:50:08 -0700130 if (offset + size > bufObj->Size) {
Ian Romanick0207b472003-09-09 00:10:12 +0000131 _mesa_error(ctx, GL_INVALID_VALUE,
Brian Paul6f172f72006-06-02 22:51:45 +0000132 "%s(size + offset > buffer size)", caller);
Ian Romanick0207b472003-09-09 00:10:12 +0000133 return NULL;
134 }
Brian Paula7892522004-11-22 20:01:25 +0000135 if (bufObj->Pointer) {
Brian Paul2daa4132004-10-31 00:17:42 +0000136 /* Buffer is currently mapped */
Brian Paul6f172f72006-06-02 22:51:45 +0000137 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
Ian Romanick0207b472003-09-09 00:10:12 +0000138 return NULL;
139 }
140
141 return bufObj;
142}
143
144
145/**
146 * Allocate and initialize a new buffer object.
147 *
Brian Paul395bcad2009-02-27 12:41:11 -0700148 * Default callback for the \c dd_function_table::NewBufferObject() hook.
Ian Romanick0207b472003-09-09 00:10:12 +0000149 */
Ian Romanick0207b472003-09-09 00:10:12 +0000150struct gl_buffer_object *
151_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target )
152{
153 struct gl_buffer_object *obj;
Brian Paula6c423d2004-08-25 15:59:48 +0000154
155 (void) ctx;
156
Brian Paulaa00d122003-09-15 19:55:10 +0000157 obj = MALLOC_STRUCT(gl_buffer_object);
Ian Romanick0207b472003-09-09 00:10:12 +0000158 _mesa_initialize_buffer_object(obj, name, target);
159 return obj;
160}
161
162
163/**
Brian Paul148a2842003-09-17 03:40:11 +0000164 * Delete a buffer object.
165 *
Brian Paul395bcad2009-02-27 12:41:11 -0700166 * Default callback for the \c dd_function_table::DeleteBuffer() hook.
Brian Paul148a2842003-09-17 03:40:11 +0000167 */
168void
169_mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj )
170{
Brian Paula6c423d2004-08-25 15:59:48 +0000171 (void) ctx;
172
Brian Paul148a2842003-09-17 03:40:11 +0000173 if (bufObj->Data)
174 _mesa_free(bufObj->Data);
Brian Paul37c74af2008-09-04 14:58:02 -0600175
176 /* assign strange values here to help w/ debugging */
177 bufObj->RefCount = -1000;
178 bufObj->Name = ~0;
179
Brian Paul148a2842003-09-17 03:40:11 +0000180 _mesa_free(bufObj);
181}
182
183
Brian Paul37c74af2008-09-04 14:58:02 -0600184
185/**
186 * Set ptr to bufObj w/ reference counting.
187 */
Ian Romanickee34e6e2006-06-12 16:26:29 +0000188void
Brian Paul37c74af2008-09-04 14:58:02 -0600189_mesa_reference_buffer_object(GLcontext *ctx,
190 struct gl_buffer_object **ptr,
191 struct gl_buffer_object *bufObj)
Ian Romanickee34e6e2006-06-12 16:26:29 +0000192{
Brian Paul37c74af2008-09-04 14:58:02 -0600193 if (*ptr == bufObj)
194 return;
195
196 if (*ptr) {
Brian Paul105c8522009-05-07 13:10:48 -0600197 /* Unreference the old buffer */
Brian Paul37c74af2008-09-04 14:58:02 -0600198 GLboolean deleteFlag = GL_FALSE;
199 struct gl_buffer_object *oldObj = *ptr;
200
201 /*_glthread_LOCK_MUTEX(oldObj->Mutex);*/
202 ASSERT(oldObj->RefCount > 0);
203 oldObj->RefCount--;
204#if 0
205 printf("BufferObj %p %d DECR to %d\n",
206 (void *) oldObj, oldObj->Name, oldObj->RefCount);
207#endif
208 deleteFlag = (oldObj->RefCount == 0);
209 /*_glthread_UNLOCK_MUTEX(oldObj->Mutex);*/
210
211 if (deleteFlag) {
212
213 /* some sanity checking: don't delete a buffer still in use */
Brian Pauld36f4ef2008-09-15 09:07:32 -0600214#if 0
215 /* unfortunately, these tests are invalid during context tear-down */
Ian Romanickee34e6e2006-06-12 16:26:29 +0000216 ASSERT(ctx->Array.ArrayBufferObj != bufObj);
217 ASSERT(ctx->Array.ElementArrayBufferObj != bufObj);
218 ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj);
Brian Pauld36f4ef2008-09-15 09:07:32 -0600219#endif
Brian Paul37c74af2008-09-04 14:58:02 -0600220
Brian Pauld36f4ef2008-09-15 09:07:32 -0600221 ASSERT(ctx->Driver.DeleteBuffer);
Brian Paul37c74af2008-09-04 14:58:02 -0600222 ctx->Driver.DeleteBuffer(ctx, oldObj);
Ian Romanickee34e6e2006-06-12 16:26:29 +0000223 }
Brian Paul37c74af2008-09-04 14:58:02 -0600224
225 *ptr = NULL;
226 }
227 ASSERT(!*ptr);
228
229 if (bufObj) {
Brian Paul105c8522009-05-07 13:10:48 -0600230 /* reference new buffer */
Brian Paul37c74af2008-09-04 14:58:02 -0600231 /*_glthread_LOCK_MUTEX(tex->Mutex);*/
232 if (bufObj->RefCount == 0) {
233 /* this buffer's being deleted (look just above) */
234 /* Not sure this can every really happen. Warn if it does. */
235 _mesa_problem(NULL, "referencing deleted buffer object");
236 *ptr = NULL;
237 }
238 else {
239 bufObj->RefCount++;
240#if 0
241 printf("BufferObj %p %d INCR to %d\n",
242 (void *) bufObj, bufObj->Name, bufObj->RefCount);
243#endif
244 *ptr = bufObj;
245 }
246 /*_glthread_UNLOCK_MUTEX(tex->Mutex);*/
Ian Romanickee34e6e2006-06-12 16:26:29 +0000247 }
248}
249
250
Brian Paul148a2842003-09-17 03:40:11 +0000251/**
Ian Romanick0207b472003-09-09 00:10:12 +0000252 * Initialize a buffer object to default values.
253 */
Ian Romanick0207b472003-09-09 00:10:12 +0000254void
255_mesa_initialize_buffer_object( struct gl_buffer_object *obj,
256 GLuint name, GLenum target )
257{
Brian Paula6c423d2004-08-25 15:59:48 +0000258 (void) target;
259
Brian Paulaa00d122003-09-15 19:55:10 +0000260 _mesa_bzero(obj, sizeof(struct gl_buffer_object));
Ian Romanick0207b472003-09-09 00:10:12 +0000261 obj->RefCount = 1;
262 obj->Name = name;
Brian Paul85ad44b2004-02-13 14:04:26 +0000263 obj->Usage = GL_STATIC_DRAW_ARB;
Brian Paul6c72bc82008-09-25 11:46:27 -0600264 obj->Access = DEFAULT_ACCESS;
Ian Romanick0207b472003-09-09 00:10:12 +0000265}
266
267
268/**
Ian Romanick0207b472003-09-09 00:10:12 +0000269 * Allocate space for and store data in a buffer object. Any data that was
270 * previously stored in the buffer object is lost. If \c data is \c NULL,
271 * memory will be allocated, but no copy will occur.
272 *
Brian Paul395bcad2009-02-27 12:41:11 -0700273 * This is the default callback for \c dd_function_table::BufferData()
274 * Note that all GL error checking will have been done already.
Ian Romanick0207b472003-09-09 00:10:12 +0000275 *
276 * \param ctx GL context.
277 * \param target Buffer object target on which to operate.
278 * \param size Size, in bytes, of the new data store.
279 * \param data Pointer to the data to store in the buffer object. This
280 * pointer may be \c NULL.
281 * \param usage Hints about how the data will be used.
282 * \param bufObj Object to be used.
283 *
284 * \sa glBufferDataARB, dd_function_table::BufferData.
285 */
Ian Romanick0207b472003-09-09 00:10:12 +0000286void
287_mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
288 const GLvoid * data, GLenum usage,
289 struct gl_buffer_object * bufObj )
290{
291 void * new_data;
292
Brian Paula6c423d2004-08-25 15:59:48 +0000293 (void) ctx; (void) target;
Ian Romanick0207b472003-09-09 00:10:12 +0000294
Brian Paul148a2842003-09-17 03:40:11 +0000295 new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size );
Brian Paula7892522004-11-22 20:01:25 +0000296 if (new_data) {
Brian Paule4fcea22003-09-19 15:38:15 +0000297 bufObj->Data = (GLubyte *) new_data;
Brian Paul148a2842003-09-17 03:40:11 +0000298 bufObj->Size = size;
299 bufObj->Usage = usage;
Ian Romanick0207b472003-09-09 00:10:12 +0000300
Brian Paula7892522004-11-22 20:01:25 +0000301 if (data) {
Brian Paul148a2842003-09-17 03:40:11 +0000302 _mesa_memcpy( bufObj->Data, data, size );
Ian Romanick0207b472003-09-09 00:10:12 +0000303 }
304 }
305}
306
307
308/**
309 * Replace data in a subrange of buffer object. If the data range
310 * specified by \c size + \c offset extends beyond the end of the buffer or
311 * if \c data is \c NULL, no copy is performed.
312 *
Brian Paul395bcad2009-02-27 12:41:11 -0700313 * This is the default callback for \c dd_function_table::BufferSubData()
314 * Note that all GL error checking will have been done already.
Ian Romanick0207b472003-09-09 00:10:12 +0000315 *
316 * \param ctx GL context.
317 * \param target Buffer object target on which to operate.
318 * \param offset Offset of the first byte to be modified.
319 * \param size Size, in bytes, of the data range.
320 * \param data Pointer to the data to store in the buffer object.
321 * \param bufObj Object to be used.
322 *
323 * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
324 */
Ian Romanick0207b472003-09-09 00:10:12 +0000325void
326_mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
327 GLsizeiptrARB size, const GLvoid * data,
328 struct gl_buffer_object * bufObj )
329{
Brian Paula6c423d2004-08-25 15:59:48 +0000330 (void) ctx; (void) target;
331
Brian Paul76785cb2006-09-21 22:59:50 +0000332 /* this should have been caught in _mesa_BufferSubData() */
Brian7e85b0a2007-01-23 12:50:08 -0700333 ASSERT(size + offset <= bufObj->Size);
Brian Paul76785cb2006-09-21 22:59:50 +0000334
335 if (bufObj->Data) {
Brian Paul148a2842003-09-17 03:40:11 +0000336 _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size );
Ian Romanick0207b472003-09-09 00:10:12 +0000337 }
338}
339
340
341/**
342 * Retrieve data from a subrange of buffer object. If the data range
343 * specified by \c size + \c offset extends beyond the end of the buffer or
344 * if \c data is \c NULL, no copy is performed.
345 *
Brian Paul395bcad2009-02-27 12:41:11 -0700346 * This is the default callback for \c dd_function_table::GetBufferSubData()
347 * Note that all GL error checking will have been done already.
Ian Romanick0207b472003-09-09 00:10:12 +0000348 *
349 * \param ctx GL context.
350 * \param target Buffer object target on which to operate.
Brian Paul395bcad2009-02-27 12:41:11 -0700351 * \param offset Offset of the first byte to be fetched.
Ian Romanick0207b472003-09-09 00:10:12 +0000352 * \param size Size, in bytes, of the data range.
Brian Paul395bcad2009-02-27 12:41:11 -0700353 * \param data Destination for data
Ian Romanick0207b472003-09-09 00:10:12 +0000354 * \param bufObj Object to be used.
355 *
356 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
357 */
Ian Romanick0207b472003-09-09 00:10:12 +0000358void
359_mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
360 GLsizeiptrARB size, GLvoid * data,
361 struct gl_buffer_object * bufObj )
362{
Brian Paula6c423d2004-08-25 15:59:48 +0000363 (void) ctx; (void) target;
364
Brian Paulc1f2f902005-03-03 02:05:33 +0000365 if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) {
Brian Paul148a2842003-09-17 03:40:11 +0000366 _mesa_memcpy( data, (GLubyte *) bufObj->Data + offset, size );
Ian Romanick0207b472003-09-09 00:10:12 +0000367 }
368}
369
370
371/**
Brian Paul395bcad2009-02-27 12:41:11 -0700372 * Default callback for \c dd_function_tabel::MapBuffer().
Ian Romanick0207b472003-09-09 00:10:12 +0000373 *
Brian Paul76785cb2006-09-21 22:59:50 +0000374 * The function parameters will have been already tested for errors.
Ian Romanick0207b472003-09-09 00:10:12 +0000375 *
376 * \param ctx GL context.
377 * \param target Buffer object target on which to operate.
378 * \param access Information about how the buffer will be accessed.
Brian Paul2daa4132004-10-31 00:17:42 +0000379 * \param bufObj Object to be mapped.
Ian Romanick0207b472003-09-09 00:10:12 +0000380 * \return A pointer to the object's internal data store that can be accessed
381 * by the processor
382 *
383 * \sa glMapBufferARB, dd_function_table::MapBuffer
384 */
Ian Romanick0207b472003-09-09 00:10:12 +0000385void *
386_mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
Brian Paul2daa4132004-10-31 00:17:42 +0000387 struct gl_buffer_object *bufObj )
Ian Romanick0207b472003-09-09 00:10:12 +0000388{
Brian Paul2daa4132004-10-31 00:17:42 +0000389 (void) ctx;
390 (void) target;
391 (void) access;
Brian Paul2daa4132004-10-31 00:17:42 +0000392 /* Just return a direct pointer to the data */
393 if (bufObj->Pointer) {
394 /* already mapped! */
395 return NULL;
396 }
397 bufObj->Pointer = bufObj->Data;
398 return bufObj->Pointer;
399}
400
401
402/**
Brian Paul395bcad2009-02-27 12:41:11 -0700403 * Default callback for \c dd_function_table::MapBuffer().
Brian Paul2daa4132004-10-31 00:17:42 +0000404 *
405 * The input parameters will have been already tested for errors.
406 *
407 * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
408 */
409GLboolean
410_mesa_buffer_unmap( GLcontext *ctx, GLenum target,
411 struct gl_buffer_object *bufObj )
412{
413 (void) ctx;
414 (void) target;
Brian Paul2daa4132004-10-31 00:17:42 +0000415 /* XXX we might assert here that bufObj->Pointer is non-null */
416 bufObj->Pointer = NULL;
417 return GL_TRUE;
Ian Romanick0207b472003-09-09 00:10:12 +0000418}
419
Brian Paul6061df02003-03-29 17:01:00 +0000420
Brian Paul148a2842003-09-17 03:40:11 +0000421/**
422 * Initialize the state associated with buffer objects
423 */
424void
425_mesa_init_buffer_objects( GLcontext *ctx )
426{
Brian Paul20202782004-02-11 22:06:05 +0000427 /* Allocate the default buffer object and set refcount so high that
428 * it never gets deleted.
Brian Paul37c74af2008-09-04 14:58:02 -0600429 * XXX with recent/improved refcounting this may not longer be needed.
Brian Paul20202782004-02-11 22:06:05 +0000430 */
Brian Paul148a2842003-09-17 03:40:11 +0000431 ctx->Array.NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0);
Brian Paul20202782004-02-11 22:06:05 +0000432 if (ctx->Array.NullBufferObj)
433 ctx->Array.NullBufferObj->RefCount = 1000;
434
Brian Paul148a2842003-09-17 03:40:11 +0000435 ctx->Array.ArrayBufferObj = ctx->Array.NullBufferObj;
436 ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj;
Brian Paul148a2842003-09-17 03:40:11 +0000437}
438
Brian Paul395bcad2009-02-27 12:41:11 -0700439
Brian4b654d42007-08-23 08:53:43 +0100440/**
441 * Bind the specified target to buffer for the specified context.
442 */
443static void
444bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
445{
446 struct gl_buffer_object *oldBufObj;
447 struct gl_buffer_object *newBufObj = NULL;
448 struct gl_buffer_object **bindTarget = NULL;
449
450 switch (target) {
451 case GL_ARRAY_BUFFER_ARB:
452 bindTarget = &ctx->Array.ArrayBufferObj;
453 break;
454 case GL_ELEMENT_ARRAY_BUFFER_ARB:
455 bindTarget = &ctx->Array.ElementArrayBufferObj;
456 break;
457 case GL_PIXEL_PACK_BUFFER_EXT:
458 bindTarget = &ctx->Pack.BufferObj;
459 break;
460 case GL_PIXEL_UNPACK_BUFFER_EXT:
461 bindTarget = &ctx->Unpack.BufferObj;
462 break;
463 default:
464 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)");
465 return;
466 }
467
468 /* Get pointer to old buffer object (to be unbound) */
469 oldBufObj = get_buffer(ctx, target);
470 if (oldBufObj && oldBufObj->Name == buffer)
471 return; /* rebinding the same buffer object- no change */
472
473 /*
474 * Get pointer to new buffer object (newBufObj)
475 */
476 if (buffer == 0) {
477 /* The spec says there's not a buffer object named 0, but we use
478 * one internally because it simplifies things.
479 */
480 newBufObj = ctx->Array.NullBufferObj;
481 }
482 else {
483 /* non-default buffer object */
484 newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
485 if (!newBufObj) {
486 /* if this is a new buffer object id, allocate a buffer object now */
487 ASSERT(ctx->Driver.NewBufferObject);
488 newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target);
489 if (!newBufObj) {
490 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
491 return;
492 }
Brian Paul37c74af2008-09-04 14:58:02 -0600493 _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj);
Brian4b654d42007-08-23 08:53:43 +0100494 }
495 }
496
Brian Paul37c74af2008-09-04 14:58:02 -0600497 /* bind new buffer */
498 _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
Brian4b654d42007-08-23 08:53:43 +0100499
500 /* Pass BindBuffer call to device driver */
501 if (ctx->Driver.BindBuffer && newBufObj)
502 ctx->Driver.BindBuffer( ctx, target, newBufObj );
Brian4b654d42007-08-23 08:53:43 +0100503}
504
505
506/**
507 * Update the default buffer objects in the given context to reference those
508 * specified in the shared state and release those referencing the old
509 * shared state.
510 */
511void
512_mesa_update_default_objects_buffer_objects(GLcontext *ctx)
513{
514 /* Bind the NullBufferObj to remove references to those
515 * in the shared context hash table.
516 */
517 bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0);
518 bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
519 bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0);
520 bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0);
521}
522
Brian Paul148a2842003-09-17 03:40:11 +0000523
Brian Paul7a6b71e2004-03-13 18:21:40 +0000524/**
525 * When we're about to read pixel data out of a PBO (via glDrawPixels,
526 * glTexImage, etc) or write data into a PBO (via glReadPixels,
527 * glGetTexImage, etc) we call this function to check that we're not
528 * going to read out of bounds.
529 *
Brian Paul2daa4132004-10-31 00:17:42 +0000530 * XXX This would also be a convenient time to check that the PBO isn't
531 * currently mapped. Whoever calls this function should check for that.
532 * Remember, we can't use a PBO when it's mapped!
533 *
Brian Paul7a6b71e2004-03-13 18:21:40 +0000534 * \param width width of image to read/write
535 * \param height height of image to read/write
536 * \param depth depth of image to read/write
537 * \param format format of image to read/write
538 * \param type datatype of image to read/write
539 * \param ptr the user-provided pointer/offset
540 * \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
541 * go out of bounds.
542 */
543GLboolean
Brian Paul60909382004-11-10 15:46:52 +0000544_mesa_validate_pbo_access(GLuint dimensions,
545 const struct gl_pixelstore_attrib *pack,
Brian Paul7a6b71e2004-03-13 18:21:40 +0000546 GLsizei width, GLsizei height, GLsizei depth,
547 GLenum format, GLenum type, const GLvoid *ptr)
548{
549 GLvoid *start, *end;
Brian Paul6b251932005-12-01 00:59:51 +0000550 const GLubyte *sizeAddr; /* buffer size, cast to a pointer */
Brian Paul7a6b71e2004-03-13 18:21:40 +0000551
552 ASSERT(pack->BufferObj->Name != 0);
553
554 if (pack->BufferObj->Size == 0)
555 /* no buffer! */
556 return GL_FALSE;
557
558 /* get address of first pixel we'll read */
Brian Paul60909382004-11-10 15:46:52 +0000559 start = _mesa_image_address(dimensions, pack, ptr, width, height,
Brian Paul7a6b71e2004-03-13 18:21:40 +0000560 format, type, 0, 0, 0);
561
562 /* get address just past the last pixel we'll read */
Brian Paul60909382004-11-10 15:46:52 +0000563 end = _mesa_image_address(dimensions, pack, ptr, width, height,
Brian Paul7a6b71e2004-03-13 18:21:40 +0000564 format, type, depth-1, height-1, width);
565
566
Brian Paul6b251932005-12-01 00:59:51 +0000567 sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size;
568
569 if ((const GLubyte *) start > sizeAddr) {
Brian Paul7a6b71e2004-03-13 18:21:40 +0000570 /* This will catch negative values / wrap-around */
571 return GL_FALSE;
572 }
Brian Paul6b251932005-12-01 00:59:51 +0000573 if ((const GLubyte *) end > sizeAddr) {
Brian Paul7a6b71e2004-03-13 18:21:40 +0000574 /* Image read goes beyond end of buffer */
575 return GL_FALSE;
576 }
577
578 /* OK! */
579 return GL_TRUE;
580}
581
582
Brian Paul4cb9fff2006-06-03 15:32:27 +0000583/**
Briana429a252008-03-21 13:41:00 -0600584 * If the source of glBitmap data is a PBO, check that we won't read out
585 * of buffer bounds, then map the buffer.
586 * If not sourcing from a PBO, just return the bitmap pointer.
587 * This is a helper function for (some) drivers.
588 * Return NULL if error.
Briand933be62008-03-21 14:19:28 -0600589 * If non-null return, must call _mesa_unmap_bitmap_pbo() when done.
Briana429a252008-03-21 13:41:00 -0600590 */
591const GLubyte *
Briand933be62008-03-21 14:19:28 -0600592_mesa_map_bitmap_pbo(GLcontext *ctx,
593 const struct gl_pixelstore_attrib *unpack,
594 const GLubyte *bitmap)
Briana429a252008-03-21 13:41:00 -0600595{
596 const GLubyte *buf;
597
598 if (unpack->BufferObj->Name) {
599 /* unpack from PBO */
Briana429a252008-03-21 13:41:00 -0600600 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
601 GL_READ_ONLY_ARB,
602 unpack->BufferObj);
603 if (!buf)
604 return NULL;
605
606 buf = ADD_POINTERS(buf, bitmap);
607 }
608 else {
609 /* unpack from normal memory */
610 buf = bitmap;
611 }
612
613 return buf;
614}
615
616
617/**
Briand933be62008-03-21 14:19:28 -0600618 * Counterpart to _mesa_map_bitmap_pbo()
Briana429a252008-03-21 13:41:00 -0600619 * This is a helper function for (some) drivers.
620 */
621void
622_mesa_unmap_bitmap_pbo(GLcontext *ctx,
623 const struct gl_pixelstore_attrib *unpack)
624{
625 if (unpack->BufferObj->Name) {
626 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
627 unpack->BufferObj);
628 }
629}
630
631
632/**
Briand933be62008-03-21 14:19:28 -0600633 * \sa _mesa_map_bitmap_pbo
Briana429a252008-03-21 13:41:00 -0600634 */
635const GLvoid *
Briand933be62008-03-21 14:19:28 -0600636_mesa_map_drawpix_pbo(GLcontext *ctx,
637 const struct gl_pixelstore_attrib *unpack,
638 const GLvoid *pixels)
Briana429a252008-03-21 13:41:00 -0600639{
640 const GLvoid *buf;
641
642 if (unpack->BufferObj->Name) {
643 /* unpack from PBO */
Briana429a252008-03-21 13:41:00 -0600644 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
645 GL_READ_ONLY_ARB,
646 unpack->BufferObj);
647 if (!buf)
648 return NULL;
649
650 buf = ADD_POINTERS(buf, pixels);
651 }
652 else {
653 /* unpack from normal memory */
654 buf = pixels;
655 }
656
657 return buf;
658}
659
660
661/**
662 * \sa _mesa_unmap_bitmap_pbo
663 */
664void
Brian Paul1437b412008-04-25 14:15:42 -0600665_mesa_unmap_drawpix_pbo(GLcontext *ctx,
666 const struct gl_pixelstore_attrib *unpack)
Briana429a252008-03-21 13:41:00 -0600667{
668 if (unpack->BufferObj->Name) {
669 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
670 unpack->BufferObj);
671 }
672}
673
674
675/**
Briand933be62008-03-21 14:19:28 -0600676 * If PBO is bound, map the buffer, return dest pointer in mapped buffer.
Briana429a252008-03-21 13:41:00 -0600677 * Call _mesa_unmap_readpix_pbo() when finished
678 * \return NULL if error
679 */
680void *
Briand933be62008-03-21 14:19:28 -0600681_mesa_map_readpix_pbo(GLcontext *ctx,
682 const struct gl_pixelstore_attrib *pack,
683 GLvoid *dest)
Briana429a252008-03-21 13:41:00 -0600684{
685 void *buf;
686
687 if (pack->BufferObj->Name) {
688 /* pack into PBO */
Briana429a252008-03-21 13:41:00 -0600689 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
690 GL_WRITE_ONLY_ARB,
691 pack->BufferObj);
692 if (!buf)
693 return NULL;
694
695 buf = ADD_POINTERS(buf, dest);
696 }
697 else {
698 /* pack to normal memory */
699 buf = dest;
700 }
701
702 return buf;
703}
704
705
706/**
Briand933be62008-03-21 14:19:28 -0600707 * Counterpart to _mesa_map_readpix_pbo()
Briana429a252008-03-21 13:41:00 -0600708 */
709void
710_mesa_unmap_readpix_pbo(GLcontext *ctx,
711 const struct gl_pixelstore_attrib *pack)
712{
713 if (pack->BufferObj->Name) {
714 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
715 }
716}
717
718
Briand933be62008-03-21 14:19:28 -0600719
Briana429a252008-03-21 13:41:00 -0600720/**
Brian Paul4cb9fff2006-06-03 15:32:27 +0000721 * Return the gl_buffer_object for the given ID.
722 * Always return NULL for ID 0.
723 */
Brian Paul4d12a052006-08-23 23:10:14 +0000724struct gl_buffer_object *
725_mesa_lookup_bufferobj(GLcontext *ctx, GLuint buffer)
Brian Paul4cb9fff2006-06-03 15:32:27 +0000726{
727 if (buffer == 0)
728 return NULL;
729 else
730 return (struct gl_buffer_object *)
731 _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
732}
733
Brian Paul7a6b71e2004-03-13 18:21:40 +0000734
Brian Paul37c74af2008-09-04 14:58:02 -0600735/**
736 * If *ptr points to obj, set ptr = the Null/default buffer object.
737 * This is a helper for buffer object deletion.
738 * The GL spec says that deleting a buffer object causes it to get
739 * unbound from all arrays in the current context.
740 */
741static void
742unbind(GLcontext *ctx,
743 struct gl_buffer_object **ptr,
744 struct gl_buffer_object *obj)
745{
746 if (*ptr == obj) {
747 _mesa_reference_buffer_object(ctx, ptr, ctx->Array.NullBufferObj);
748 }
749}
750
751
Brian Paul148a2842003-09-17 03:40:11 +0000752
753/**********************************************************************/
754/* API Functions */
755/**********************************************************************/
756
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000757void GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +0000758_mesa_BindBufferARB(GLenum target, GLuint buffer)
759{
Brian Paulaac73252003-04-09 02:31:35 +0000760 GET_CURRENT_CONTEXT(ctx);
761 ASSERT_OUTSIDE_BEGIN_END(ctx);
762
Brian4b654d42007-08-23 08:53:43 +0100763 bind_buffer_object(ctx, target, buffer);
Brian Paul6061df02003-03-29 17:01:00 +0000764}
765
Ian Romanick0207b472003-09-09 00:10:12 +0000766
767/**
768 * Delete a set of buffer objects.
769 *
770 * \param n Number of buffer objects to delete.
Jose Fonseca375457b2004-09-09 22:23:24 +0000771 * \param ids Array of \c n buffer object IDs.
Ian Romanick0207b472003-09-09 00:10:12 +0000772 */
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000773void GLAPIENTRY
Ian Romanick0207b472003-09-09 00:10:12 +0000774_mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
Brian Paul6061df02003-03-29 17:01:00 +0000775{
Brian Paulaac73252003-04-09 02:31:35 +0000776 GET_CURRENT_CONTEXT(ctx);
Karl Schultzdf8d3372003-09-18 15:14:10 +0000777 GLsizei i;
Brian Paulaac73252003-04-09 02:31:35 +0000778 ASSERT_OUTSIDE_BEGIN_END(ctx);
779
780 if (n < 0) {
781 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
782 return;
783 }
784
Ian Romanick0207b472003-09-09 00:10:12 +0000785 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
786
787 for (i = 0; i < n; i++) {
Brian Paul4d12a052006-08-23 23:10:14 +0000788 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
Brian Paul4cb9fff2006-06-03 15:32:27 +0000789 if (bufObj) {
Brian Paul4cb9fff2006-06-03 15:32:27 +0000790 GLuint j;
Brian Paul94ec5252004-03-04 14:46:00 +0000791
Brian Paul4cb9fff2006-06-03 15:32:27 +0000792 ASSERT(bufObj->Name == ids[i]);
Brian Paul94ec5252004-03-04 14:46:00 +0000793
Brian Paula7f434b2009-02-27 13:04:38 -0700794 if (bufObj->Pointer) {
795 /* if mapped, unmap it now */
796 ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
Brian Paul67025f72009-02-27 13:10:45 -0700797 bufObj->Access = DEFAULT_ACCESS;
798 bufObj->Pointer = NULL;
Brian Paula7f434b2009-02-27 13:04:38 -0700799 }
800
Brian Paul395bcad2009-02-27 12:41:11 -0700801 /* unbind any vertex pointers bound to this buffer */
Brian Paul37c74af2008-09-04 14:58:02 -0600802 unbind(ctx, &ctx->Array.ArrayObj->Vertex.BufferObj, bufObj);
803 unbind(ctx, &ctx->Array.ArrayObj->Normal.BufferObj, bufObj);
804 unbind(ctx, &ctx->Array.ArrayObj->Color.BufferObj, bufObj);
805 unbind(ctx, &ctx->Array.ArrayObj->SecondaryColor.BufferObj, bufObj);
806 unbind(ctx, &ctx->Array.ArrayObj->FogCoord.BufferObj, bufObj);
807 unbind(ctx, &ctx->Array.ArrayObj->Index.BufferObj, bufObj);
808 unbind(ctx, &ctx->Array.ArrayObj->EdgeFlag.BufferObj, bufObj);
Brian Paule9b34882008-12-31 11:54:02 -0700809 for (j = 0; j < MAX_TEXTURE_COORD_UNITS; j++) {
Brian Paul37c74af2008-09-04 14:58:02 -0600810 unbind(ctx, &ctx->Array.ArrayObj->TexCoord[j].BufferObj, bufObj);
Ian Romanick0207b472003-09-09 00:10:12 +0000811 }
Brian Paul4cb9fff2006-06-03 15:32:27 +0000812 for (j = 0; j < VERT_ATTRIB_MAX; j++) {
Brian Paul37c74af2008-09-04 14:58:02 -0600813 unbind(ctx, &ctx->Array.ArrayObj->VertexAttrib[j].BufferObj, bufObj);
Brian Paul4cb9fff2006-06-03 15:32:27 +0000814 }
815
816 if (ctx->Array.ArrayBufferObj == bufObj) {
817 _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
818 }
819 if (ctx->Array.ElementArrayBufferObj == bufObj) {
820 _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
821 }
822
Brian Paul395bcad2009-02-27 12:41:11 -0700823 /* unbind any pixel pack/unpack pointers bound to this buffer */
Brian Paul4cb9fff2006-06-03 15:32:27 +0000824 if (ctx->Pack.BufferObj == bufObj) {
825 _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 );
826 }
827 if (ctx->Unpack.BufferObj == bufObj) {
828 _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
829 }
830
Brian4b654d42007-08-23 08:53:43 +0100831 /* The ID is immediately freed for re-use */
Brian Paul37c74af2008-09-04 14:58:02 -0600832 _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name);
833 _mesa_reference_buffer_object(ctx, &bufObj, NULL);
Ian Romanick0207b472003-09-09 00:10:12 +0000834 }
835 }
836
837 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
Brian Paul6061df02003-03-29 17:01:00 +0000838}
839
Ian Romanick0207b472003-09-09 00:10:12 +0000840
841/**
842 * Generate a set of unique buffer object IDs and store them in \c buffer.
843 *
844 * \param n Number of IDs to generate.
845 * \param buffer Array of \c n locations to store the IDs.
846 */
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000847void GLAPIENTRY
Brian Paulaac73252003-04-09 02:31:35 +0000848_mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
Brian Paul6061df02003-03-29 17:01:00 +0000849{
Brian Paulaac73252003-04-09 02:31:35 +0000850 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +0000851 GLuint first;
852 GLint i;
Brian Paulaac73252003-04-09 02:31:35 +0000853 ASSERT_OUTSIDE_BEGIN_END(ctx);
854
855 if (n < 0) {
Ian Romanick0207b472003-09-09 00:10:12 +0000856 _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
Brian Paulaac73252003-04-09 02:31:35 +0000857 return;
858 }
Ian Romanick0207b472003-09-09 00:10:12 +0000859
Brian Paula7892522004-11-22 20:01:25 +0000860 if (!buffer) {
Ian Romanick0207b472003-09-09 00:10:12 +0000861 return;
862 }
863
864 /*
865 * This must be atomic (generation and allocation of buffer object IDs)
866 */
867 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
868
869 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
870
Brian Paulaa00d122003-09-15 19:55:10 +0000871 /* Allocate new, empty buffer objects and return identifiers */
Ian Romanick0207b472003-09-09 00:10:12 +0000872 for (i = 0; i < n; i++) {
873 struct gl_buffer_object *bufObj;
874 GLuint name = first + i;
875 GLenum target = 0;
Brian Paul6f172f72006-06-02 22:51:45 +0000876 bufObj = ctx->Driver.NewBufferObject( ctx, name, target );
Brian Paul148a2842003-09-17 03:40:11 +0000877 if (!bufObj) {
Brian Paul27521772005-02-12 18:43:38 +0000878 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
Ian Romanick0207b472003-09-09 00:10:12 +0000879 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB");
880 return;
881 }
Brian Paul37c74af2008-09-04 14:58:02 -0600882 _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, bufObj);
Brian Paulaa00d122003-09-15 19:55:10 +0000883 buffer[i] = first + i;
Ian Romanick0207b472003-09-09 00:10:12 +0000884 }
885
886 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
Brian Paul6061df02003-03-29 17:01:00 +0000887}
888
Ian Romanick0207b472003-09-09 00:10:12 +0000889
890/**
891 * Determine if ID is the name of a buffer object.
892 *
893 * \param id ID of the potential buffer object.
894 * \return \c GL_TRUE if \c id is the name of a buffer object,
895 * \c GL_FALSE otherwise.
896 */
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000897GLboolean GLAPIENTRY
Ian Romanick0207b472003-09-09 00:10:12 +0000898_mesa_IsBufferARB(GLuint id)
Brian Paul6061df02003-03-29 17:01:00 +0000899{
Brian Paul4cb9fff2006-06-03 15:32:27 +0000900 struct gl_buffer_object *bufObj;
Ian Romanick0207b472003-09-09 00:10:12 +0000901 GET_CURRENT_CONTEXT(ctx);
902 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
903
Ian Romanick0207b472003-09-09 00:10:12 +0000904 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
Brian Paul4d12a052006-08-23 23:10:14 +0000905 bufObj = _mesa_lookup_bufferobj(ctx, id);
Ian Romanick0207b472003-09-09 00:10:12 +0000906 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
907
Brian Paulea2943e2005-01-20 04:02:02 +0000908 return bufObj ? GL_TRUE : GL_FALSE;
Brian Paul6061df02003-03-29 17:01:00 +0000909}
910
Ian Romanick0207b472003-09-09 00:10:12 +0000911
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000912void GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +0000913_mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
914 const GLvoid * data, GLenum usage)
915{
Brian Paulaac73252003-04-09 02:31:35 +0000916 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +0000917 struct gl_buffer_object *bufObj;
Brian Paulaac73252003-04-09 02:31:35 +0000918 ASSERT_OUTSIDE_BEGIN_END(ctx);
919
920 if (size < 0) {
921 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
922 return;
923 }
924
925 switch (usage) {
926 case GL_STREAM_DRAW_ARB:
927 case GL_STREAM_READ_ARB:
928 case GL_STREAM_COPY_ARB:
929 case GL_STATIC_DRAW_ARB:
930 case GL_STATIC_READ_ARB:
931 case GL_STATIC_COPY_ARB:
932 case GL_DYNAMIC_DRAW_ARB:
933 case GL_DYNAMIC_READ_ARB:
934 case GL_DYNAMIC_COPY_ARB:
935 /* OK */
936 break;
937 default:
938 _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)");
939 return;
940 }
941
Brian Paul4277ea42006-08-25 22:06:02 +0000942 bufObj = get_buffer(ctx, target);
943 if (!bufObj) {
944 _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" );
945 return;
946 }
947 if (bufObj->Name == 0) {
Brian Paulaa00d122003-09-15 19:55:10 +0000948 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB" );
Brian Paulaac73252003-04-09 02:31:35 +0000949 return;
950 }
Ian Romanick0207b472003-09-09 00:10:12 +0000951
Brian Paul66e6e3e2003-09-17 21:18:22 +0000952 if (bufObj->Pointer) {
Brian Paul75e3ccf2009-02-27 12:30:21 -0700953 /* Unmap the existing buffer. We'll replace it now. Not an error. */
954 ctx->Driver.UnmapBuffer(ctx, target, bufObj);
955 bufObj->Access = DEFAULT_ACCESS;
956 bufObj->Pointer = NULL;
Brian Paul66e6e3e2003-09-17 21:18:22 +0000957 }
958
Brian Paulb9d0f942009-05-06 15:17:25 -0600959 FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
960
Ian Romanick0207b472003-09-09 00:10:12 +0000961 ASSERT(ctx->Driver.BufferData);
962
Brian Pauldcca97a2009-05-06 15:23:09 -0600963 bufObj->Written = GL_TRUE;
964
Ian Romanick0207b472003-09-09 00:10:12 +0000965 /* Give the buffer object to the driver! <data> may be null! */
Brian Paul6f172f72006-06-02 22:51:45 +0000966 ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj );
Brian Paul6061df02003-03-29 17:01:00 +0000967}
968
Brian Paulc7b872a2003-09-09 13:44:40 +0000969
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000970void GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +0000971_mesa_BufferSubDataARB(GLenum target, GLintptrARB offset,
972 GLsizeiptrARB size, const GLvoid * data)
973{
Brian Paulaac73252003-04-09 02:31:35 +0000974 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +0000975 struct gl_buffer_object *bufObj;
Brian Paulaac73252003-04-09 02:31:35 +0000976 ASSERT_OUTSIDE_BEGIN_END(ctx);
977
Brian Paulc7b872a2003-09-09 13:44:40 +0000978 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
Brian Paul4277ea42006-08-25 22:06:02 +0000979 "glBufferSubDataARB" );
Brian Paulaa00d122003-09-15 19:55:10 +0000980 if (!bufObj) {
Brian Paul2daa4132004-10-31 00:17:42 +0000981 /* error already recorded */
Brian Paulaa00d122003-09-15 19:55:10 +0000982 return;
Brian Paulaac73252003-04-09 02:31:35 +0000983 }
Brian Paulaa00d122003-09-15 19:55:10 +0000984
Brian Pauldcca97a2009-05-06 15:23:09 -0600985 bufObj->Written = GL_TRUE;
986
Brian Paulaa00d122003-09-15 19:55:10 +0000987 ASSERT(ctx->Driver.BufferSubData);
Brian Paul6f172f72006-06-02 22:51:45 +0000988 ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj );
Brian Paul6061df02003-03-29 17:01:00 +0000989}
990
Brian Paulc7b872a2003-09-09 13:44:40 +0000991
Kendall Bennettc40d1dd2003-10-21 22:22:17 +0000992void GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +0000993_mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset,
994 GLsizeiptrARB size, void * data)
995{
Brian Paulaac73252003-04-09 02:31:35 +0000996 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +0000997 struct gl_buffer_object *bufObj;
Brian Paulaac73252003-04-09 02:31:35 +0000998 ASSERT_OUTSIDE_BEGIN_END(ctx);
999
Brian Paulc7b872a2003-09-09 13:44:40 +00001000 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
Brian Paul4277ea42006-08-25 22:06:02 +00001001 "glGetBufferSubDataARB" );
Brian Paulaa00d122003-09-15 19:55:10 +00001002 if (!bufObj) {
Brian Paul2daa4132004-10-31 00:17:42 +00001003 /* error already recorded */
Brian Paulaa00d122003-09-15 19:55:10 +00001004 return;
Brian Paulaac73252003-04-09 02:31:35 +00001005 }
Brian Paul66e6e3e2003-09-17 21:18:22 +00001006
Brian Paulaa00d122003-09-15 19:55:10 +00001007 ASSERT(ctx->Driver.GetBufferSubData);
Brian Paul6f172f72006-06-02 22:51:45 +00001008 ctx->Driver.GetBufferSubData( ctx, target, offset, size, data, bufObj );
Brian Paul6061df02003-03-29 17:01:00 +00001009}
1010
Brian Paulc7b872a2003-09-09 13:44:40 +00001011
Kendall Bennettc40d1dd2003-10-21 22:22:17 +00001012void * GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +00001013_mesa_MapBufferARB(GLenum target, GLenum access)
1014{
Brian Paulaac73252003-04-09 02:31:35 +00001015 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +00001016 struct gl_buffer_object * bufObj;
Brian Paulea31ca42003-05-10 04:35:09 +00001017 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
Brian Paulaac73252003-04-09 02:31:35 +00001018
1019 switch (access) {
1020 case GL_READ_ONLY_ARB:
1021 case GL_WRITE_ONLY_ARB:
1022 case GL_READ_WRITE_ARB:
1023 /* OK */
1024 break;
1025 default:
1026 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
Brian Paulea31ca42003-05-10 04:35:09 +00001027 return NULL;
Brian Paulaac73252003-04-09 02:31:35 +00001028 }
1029
Brian Paul4277ea42006-08-25 22:06:02 +00001030 bufObj = get_buffer(ctx, target);
1031 if (!bufObj) {
1032 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" );
1033 return NULL;
1034 }
1035 if (bufObj->Name == 0) {
Brian Paulaa00d122003-09-15 19:55:10 +00001036 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB" );
Brian Paulea31ca42003-05-10 04:35:09 +00001037 return NULL;
Brian Paulaac73252003-04-09 02:31:35 +00001038 }
Brian Paula7892522004-11-22 20:01:25 +00001039 if (bufObj->Pointer) {
Brian Paul66e6e3e2003-09-17 21:18:22 +00001040 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)");
Ian Romanick0207b472003-09-09 00:10:12 +00001041 return NULL;
1042 }
1043
1044 ASSERT(ctx->Driver.MapBuffer);
Brian Paul6f172f72006-06-02 22:51:45 +00001045 bufObj->Pointer = ctx->Driver.MapBuffer( ctx, target, access, bufObj );
Brian Paula7892522004-11-22 20:01:25 +00001046 if (!bufObj->Pointer) {
Ian Romanick0207b472003-09-09 00:10:12 +00001047 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
1048 }
1049
Brian Paul0bb281b2003-10-14 15:48:39 +00001050 bufObj->Access = access;
Brian Pauldcca97a2009-05-06 15:23:09 -06001051 if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
1052 bufObj->Written = GL_TRUE;
Brian Paul0bb281b2003-10-14 15:48:39 +00001053
Brian Paul148a2842003-09-17 03:40:11 +00001054 return bufObj->Pointer;
Brian Paul6061df02003-03-29 17:01:00 +00001055}
1056
Brian Paulc7b872a2003-09-09 13:44:40 +00001057
Kendall Bennettc40d1dd2003-10-21 22:22:17 +00001058GLboolean GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +00001059_mesa_UnmapBufferARB(GLenum target)
1060{
Brian Paulaac73252003-04-09 02:31:35 +00001061 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +00001062 struct gl_buffer_object *bufObj;
1063 GLboolean status = GL_TRUE;
Brian Paulaac73252003-04-09 02:31:35 +00001064 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1065
Brian Paul4277ea42006-08-25 22:06:02 +00001066 bufObj = get_buffer(ctx, target);
1067 if (!bufObj) {
1068 _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" );
1069 return GL_FALSE;
1070 }
1071 if (bufObj->Name == 0) {
Brian Paul148a2842003-09-17 03:40:11 +00001072 _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" );
Brian Paulaac73252003-04-09 02:31:35 +00001073 return GL_FALSE;
1074 }
Brian Paula7892522004-11-22 20:01:25 +00001075 if (!bufObj->Pointer) {
Ian Romanick0207b472003-09-09 00:10:12 +00001076 _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
1077 return GL_FALSE;
1078 }
1079
Brian Paul67025f72009-02-27 13:10:45 -07001080 status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
Brian Paul6c72bc82008-09-25 11:46:27 -06001081 bufObj->Access = DEFAULT_ACCESS;
Brian Paul148a2842003-09-17 03:40:11 +00001082 bufObj->Pointer = NULL;
Ian Romanick0207b472003-09-09 00:10:12 +00001083
1084 return status;
Brian Paul6061df02003-03-29 17:01:00 +00001085}
1086
Brian Paulc7b872a2003-09-09 13:44:40 +00001087
Kendall Bennettc40d1dd2003-10-21 22:22:17 +00001088void GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +00001089_mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
1090{
Brian Paulaac73252003-04-09 02:31:35 +00001091 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +00001092 struct gl_buffer_object *bufObj;
Brian Paulaac73252003-04-09 02:31:35 +00001093 ASSERT_OUTSIDE_BEGIN_END(ctx);
1094
Brian Paul4277ea42006-08-25 22:06:02 +00001095 bufObj = get_buffer(ctx, target);
1096 if (!bufObj) {
1097 _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" );
1098 return;
1099 }
1100 if (bufObj->Name == 0) {
Brian Paulaa00d122003-09-15 19:55:10 +00001101 _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" );
Ian Romanick0207b472003-09-09 00:10:12 +00001102 return;
1103 }
1104
Brian Paulaac73252003-04-09 02:31:35 +00001105 switch (pname) {
1106 case GL_BUFFER_SIZE_ARB:
Brian Paule4b23562005-05-04 20:11:35 +00001107 *params = (GLint) bufObj->Size;
Ian Romanick0207b472003-09-09 00:10:12 +00001108 break;
Brian Paulaac73252003-04-09 02:31:35 +00001109 case GL_BUFFER_USAGE_ARB:
Brian Paul148a2842003-09-17 03:40:11 +00001110 *params = bufObj->Usage;
Ian Romanick0207b472003-09-09 00:10:12 +00001111 break;
Brian Paulaac73252003-04-09 02:31:35 +00001112 case GL_BUFFER_ACCESS_ARB:
Brian Paul148a2842003-09-17 03:40:11 +00001113 *params = bufObj->Access;
Ian Romanick0207b472003-09-09 00:10:12 +00001114 break;
Brian Paulaac73252003-04-09 02:31:35 +00001115 case GL_BUFFER_MAPPED_ARB:
Brian Paul148a2842003-09-17 03:40:11 +00001116 *params = (bufObj->Pointer != NULL);
Brian Paulaac73252003-04-09 02:31:35 +00001117 break;
1118 default:
1119 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)");
1120 return;
1121 }
Brian Paul6061df02003-03-29 17:01:00 +00001122}
1123
Brian Paulc7b872a2003-09-09 13:44:40 +00001124
Kendall Bennettc40d1dd2003-10-21 22:22:17 +00001125void GLAPIENTRY
Brian Paul6061df02003-03-29 17:01:00 +00001126_mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
1127{
Brian Paulaac73252003-04-09 02:31:35 +00001128 GET_CURRENT_CONTEXT(ctx);
Ian Romanick0207b472003-09-09 00:10:12 +00001129 struct gl_buffer_object * bufObj;
Brian Paulaac73252003-04-09 02:31:35 +00001130 ASSERT_OUTSIDE_BEGIN_END(ctx);
1131
1132 if (pname != GL_BUFFER_MAP_POINTER_ARB) {
1133 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
1134 return;
1135 }
1136
Brian Paul4277ea42006-08-25 22:06:02 +00001137 bufObj = get_buffer(ctx, target);
1138 if (!bufObj) {
1139 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" );
1140 return;
1141 }
1142 if (bufObj->Name == 0) {
Brian Paulaa00d122003-09-15 19:55:10 +00001143 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" );
Brian Paulaac73252003-04-09 02:31:35 +00001144 return;
1145 }
Ian Romanick0207b472003-09-09 00:10:12 +00001146
Brian Paul148a2842003-09-17 03:40:11 +00001147 *params = bufObj->Pointer;
Brian Paul6061df02003-03-29 17:01:00 +00001148}