Some work on ARB_vertex_buffer_object.
[mesa.git] / src / mesa / main / bufferobj.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * \file bufferobj.c
28 * \brief Functions for the GL_ARB_vertex_buffer_object extension.
29 * \author Brian Paul, Ian Romanick
30 */
31
32
33 #include "glheader.h"
34 #include "hash.h"
35 #include "imports.h"
36 #include "context.h"
37 #include "bufferobj.h"
38
39
40 struct gl_buffer_object {
41 GLint RefCount;
42 GLuint Name;
43 GLenum Target;
44
45 GLenum usage;
46 GLenum access;
47 GLvoid * pointer;
48 GLuint size;
49
50 void * data;
51 };
52
53
54 /**
55 * Get the buffer object bound to the specified target in a GL context.
56 *
57 * \param ctx GL context
58 * \param target Buffer object target to be retrieved. Currently this must
59 * be either \c GL_ARRAY_BUFFER or \c GL_ELEMENT_ARRAY_BUFFER.
60 * \param str Name of caller for logging errors.
61 * \return A pointer to the buffer object bound to \c target in the
62 * specified context or \c NULL if \c target is invalid or no
63 * buffer object is bound.
64 */
65 static INLINE struct gl_buffer_object *
66 buffer_object_get_target( GLcontext *ctx, GLenum target, const char * str )
67 {
68 struct gl_buffer_object * bufObj = NULL;
69
70 switch (target) {
71 case GL_ARRAY_BUFFER_ARB:
72 bufObj = ctx->ArrayBuffer;
73 break;
74 case GL_ELEMENT_ARRAY_BUFFER_ARB:
75 bufObj = ctx->ElementArrayBuffer;
76 break;
77 default:
78 _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(target)", str);
79 break;
80 }
81
82 return bufObj;
83 }
84
85
86 /**
87 * Tests the subdata range parameters and sets the GL error code for
88 * \c glBufferSubDataARB and \c glGetBufferSubDataARB.
89 *
90 * \param ctx GL context.
91 * \param target Buffer object target on which to operate.
92 * \param offset Offset of the first byte of the subdata range.
93 * \param size Size, in bytes, of the subdata range.
94 * \param str Name of caller for logging errors.
95 * \return A pointer to the buffer object bound to \c target in the
96 * specified context or \c NULL if any of the parameter or state
97 * conditions for \c glBufferSubDataARB or \c glGetBufferSubDataARB
98 * are invalid.
99 *
100 * \sa glBufferSubDataARB, glGetBufferSubDataARB
101 */
102 static struct gl_buffer_object *
103 buffer_object_subdata_range_good( GLcontext * ctx, GLenum target,
104 GLintptrARB offset, GLsizeiptrARB size,
105 const char * str )
106 {
107 struct gl_buffer_object *bufObj;
108
109 if (size < 0) {
110 _mesa_error(ctx, GL_INVALID_VALUE, "gl%s(size < 0)", str);
111 return NULL;
112 }
113
114 if (offset < 0) {
115 _mesa_error(ctx, GL_INVALID_VALUE, "gl%s(offset < 0)", str);
116 return NULL;
117 }
118
119 bufObj = buffer_object_get_target( ctx, target, str );
120 if ( bufObj == NULL ) {
121 return NULL;
122 }
123
124 if ( (offset + size) > bufObj->size ) {
125 _mesa_error(ctx, GL_INVALID_VALUE,
126 "gl%s(size + offset > buffer size)", str);
127 return NULL;
128 }
129
130 if ( bufObj->pointer != NULL ) {
131 _mesa_error(ctx, GL_INVALID_OPERATION, "gl%s", str);
132 return NULL;
133 }
134
135 return bufObj;
136 }
137
138
139 /**
140 * Allocate and initialize a new buffer object.
141 *
142 * This function is intended to be called via
143 * \c dd_function_table::NewBufferObject.
144 */
145 struct gl_buffer_object *
146 _mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target )
147 {
148 struct gl_buffer_object *obj;
149 obj = MALLOC_STRUCT(gl_buffer_object);
150 _mesa_initialize_buffer_object(obj, name, target);
151 return obj;
152 }
153
154
155 /**
156 * Initialize a buffer object to default values.
157 */
158 void
159 _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
160 GLuint name, GLenum target )
161 {
162 _mesa_bzero(obj, sizeof(struct gl_buffer_object));
163 obj->RefCount = 1;
164 obj->Name = name;
165 }
166
167
168 /**
169 * Add the given buffer object to the buffer object pool.
170 */
171 void
172 _mesa_save_buffer_object( GLcontext *ctx, struct gl_buffer_object *obj )
173 {
174 if (obj->Name > 0) {
175 /* insert into hash table */
176 _mesa_HashInsert(ctx->Shared->BufferObjects, obj->Name, obj);
177 }
178 }
179
180
181 /**
182 * Remove the given buffer object from the buffer object pool.
183 * Do not deallocate the buffer object though.
184 */
185 void
186 _mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj )
187 {
188 if (bufObj->Name > 0) {
189 /* remove from hash table */
190 _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name);
191 }
192 }
193
194
195 /**
196 * Allocate space for and store data in a buffer object. Any data that was
197 * previously stored in the buffer object is lost. If \c data is \c NULL,
198 * memory will be allocated, but no copy will occur.
199 *
200 * This function is intended to be called via
201 * \c dd_function_table::BufferData. This function need not set GL error
202 * codes. The input parameters will have been tested before calling.
203 *
204 * \param ctx GL context.
205 * \param target Buffer object target on which to operate.
206 * \param size Size, in bytes, of the new data store.
207 * \param data Pointer to the data to store in the buffer object. This
208 * pointer may be \c NULL.
209 * \param usage Hints about how the data will be used.
210 * \param bufObj Object to be used.
211 *
212 * \sa glBufferDataARB, dd_function_table::BufferData.
213 */
214 void
215 _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size,
216 const GLvoid * data, GLenum usage,
217 struct gl_buffer_object * bufObj )
218 {
219 void * new_data;
220
221 (void) target;
222
223 new_data = _mesa_realloc( bufObj->data, bufObj->size, size );
224 if ( new_data != NULL ) {
225 bufObj->data = new_data;
226 bufObj->size = size;
227 bufObj->usage = usage;
228
229 if ( data != NULL ) {
230 _mesa_memcpy( bufObj->data, data, size );
231 }
232 }
233 }
234
235
236 /**
237 * Replace data in a subrange of buffer object. If the data range
238 * specified by \c size + \c offset extends beyond the end of the buffer or
239 * if \c data is \c NULL, no copy is performed.
240 *
241 * This function is intended to be called by
242 * \c dd_function_table::BufferSubData. This function need not set GL error
243 * codes. The input parameters will have been tested before calling.
244 *
245 * \param ctx GL context.
246 * \param target Buffer object target on which to operate.
247 * \param offset Offset of the first byte to be modified.
248 * \param size Size, in bytes, of the data range.
249 * \param data Pointer to the data to store in the buffer object.
250 * \param bufObj Object to be used.
251 *
252 * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
253 */
254 void
255 _mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
256 GLsizeiptrARB size, const GLvoid * data,
257 struct gl_buffer_object * bufObj )
258 {
259 if ( (bufObj->data != NULL)
260 && ((size + offset) <= bufObj->size) ) {
261 _mesa_memcpy( (GLubyte *) bufObj->data + offset, data, size );
262 }
263 }
264
265
266 /**
267 * Retrieve data from a subrange of buffer object. If the data range
268 * specified by \c size + \c offset extends beyond the end of the buffer or
269 * if \c data is \c NULL, no copy is performed.
270 *
271 * This function is intended to be called by
272 * \c dd_function_table::BufferGetSubData. This function need not set GL error
273 * codes. The input parameters will have been tested before calling.
274 *
275 * \param ctx GL context.
276 * \param target Buffer object target on which to operate.
277 * \param offset Offset of the first byte to be modified.
278 * \param size Size, in bytes, of the data range.
279 * \param data Pointer to the data to store in the buffer object.
280 * \param bufObj Object to be used.
281 *
282 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
283 */
284 void
285 _mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset,
286 GLsizeiptrARB size, GLvoid * data,
287 struct gl_buffer_object * bufObj )
288 {
289 if ( (bufObj->data != NULL)
290 && ((size + offset) <= bufObj->size) ) {
291 _mesa_memcpy( data, (GLubyte *) bufObj->data + offset, size );
292 }
293 }
294
295
296 /**
297 * Maps the private data buffer into the processor's address space.
298 *
299 * This function is intended to be called by \c dd_function_table::MapBuffer.
300 * This function need not set GL error codes. The input parameters will have
301 * been tested before calling.
302 *
303 * \param ctx GL context.
304 * \param target Buffer object target on which to operate.
305 * \param access Information about how the buffer will be accessed.
306 * \param bufObj Object to be used.
307 * \return A pointer to the object's internal data store that can be accessed
308 * by the processor
309 *
310 * \sa glMapBufferARB, dd_function_table::MapBuffer
311 */
312 void *
313 _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
314 struct gl_buffer_object * bufObj )
315 {
316 return bufObj->data;
317 }
318
319
320 void
321 _mesa_BindBufferARB(GLenum target, GLuint buffer)
322 {
323 GET_CURRENT_CONTEXT(ctx);
324 struct gl_buffer_object *oldBufObj;
325 struct gl_buffer_object *newBufObj = 0;
326 ASSERT_OUTSIDE_BEGIN_END(ctx);
327
328 oldBufObj = buffer_object_get_target( ctx, target, "BindBufferARB" );
329 if ( (oldBufObj != NULL) && (oldBufObj->Name == buffer) )
330 return; /* rebinding the same buffer object- no change */
331
332 /*
333 * Get pointer to new buffer object (newBufObj)
334 */
335 if ( buffer == 0 ) {
336 newBufObj = NULL;
337 }
338 else {
339 /* non-default buffer object */
340 const struct _mesa_HashTable *hash = ctx->Shared->BufferObjects;
341 newBufObj = (struct gl_buffer_object *) _mesa_HashLookup(hash, buffer);
342 if ( newBufObj != NULL ) {
343 /* error checking */
344 if (newBufObj->Target != 0 && newBufObj->Target != target) {
345 /* the named buffer object's target doesn't match the target */
346 _mesa_error( ctx, GL_INVALID_OPERATION,
347 "glBindBufferARB(wrong target)" );
348 return;
349 }
350 }
351 else {
352 /* if this is a new buffer object id, allocate a buffer object now */
353 newBufObj = (*ctx->Driver.NewBufferObject)(ctx, buffer, target);
354 if (!newBufObj) {
355 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
356 return;
357 }
358 _mesa_save_buffer_object(ctx, newBufObj);
359 }
360 newBufObj->Target = target;
361 newBufObj->RefCount++;
362 }
363
364 switch (target) {
365 case GL_ARRAY_BUFFER_ARB:
366 ctx->ArrayBuffer = newBufObj;
367 break;
368 case GL_ELEMENT_ARRAY_BUFFER_ARB:
369 ctx->ElementArrayBuffer = newBufObj;
370 break;
371 }
372
373 /* Pass BindBuffer call to device driver */
374 if ( (ctx->Driver.BindBuffer != NULL) && (newBufObj != NULL) )
375 (*ctx->Driver.BindBuffer)( ctx, target, newBufObj );
376
377 if ( oldBufObj != NULL ) {
378 oldBufObj->RefCount--;
379 assert(oldBufObj->RefCount >= 0);
380 if (oldBufObj->RefCount == 0) {
381 assert(oldBufObj->Name != 0);
382 _mesa_remove_buffer_object(ctx, oldBufObj);
383 ASSERT(ctx->Driver.DeleteBuffer);
384 (*ctx->Driver.DeleteBuffer)( ctx, oldBufObj );
385 }
386 }
387 }
388
389
390 /**
391 * Delete a set of buffer objects.
392 *
393 * \param n Number of buffer objects to delete.
394 * \param buffer Array of \c n buffer object IDs.
395 */
396 void
397 _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
398 {
399 GET_CURRENT_CONTEXT(ctx);
400 unsigned i;
401 ASSERT_OUTSIDE_BEGIN_END(ctx);
402
403 if (n < 0) {
404 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
405 return;
406 }
407
408 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
409
410 for (i = 0; i < n; i++) {
411 if (ids[i] != 0) {
412 struct gl_buffer_object *bufObj = (struct gl_buffer_object *)
413 _mesa_HashLookup(ctx->Shared->BufferObjects, ids[i]);
414 if (bufObj) {
415 if ( (bufObj->Target == GL_ARRAY_BUFFER_ARB)
416 || (bufObj->Target == GL_ELEMENT_ARRAY_BUFFER_ARB) ) {
417 _mesa_BindBufferARB( bufObj->Target, 0 );
418 }
419 else if (bufObj->Target == 0) {
420 /* The buffer object is not bound.
421 */
422 }
423 else {
424 _mesa_problem(ctx, "bad target in glDeleteBufferARB");
425 return;
426 }
427 bufObj->RefCount--;
428 if (bufObj->RefCount <= 0) {
429 ASSERT(bufObj->Name != 0);
430 _mesa_remove_buffer_object(ctx, bufObj);
431 ASSERT(ctx->Driver.DeleteBuffer);
432 (*ctx->Driver.DeleteBuffer)(ctx, bufObj);
433 }
434 }
435 }
436 }
437
438 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
439 }
440
441
442 /**
443 * Generate a set of unique buffer object IDs and store them in \c buffer.
444 *
445 * \param n Number of IDs to generate.
446 * \param buffer Array of \c n locations to store the IDs.
447 */
448 void
449 _mesa_GenBuffersARB(GLsizei n, GLuint *buffer)
450 {
451 GET_CURRENT_CONTEXT(ctx);
452 GLuint first;
453 GLint i;
454 ASSERT_OUTSIDE_BEGIN_END(ctx);
455
456 if (n < 0) {
457 _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
458 return;
459 }
460
461 if ( buffer == NULL ) {
462 return;
463 }
464
465 /*
466 * This must be atomic (generation and allocation of buffer object IDs)
467 */
468 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
469
470 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
471
472 /* Allocate new, empty buffer objects and return identifiers */
473 for (i = 0; i < n; i++) {
474 struct gl_buffer_object *bufObj;
475 GLuint name = first + i;
476 GLenum target = 0;
477 bufObj = (*ctx->Driver.NewBufferObject)( ctx, name, target );
478 if ( bufObj != NULL ) {
479 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB");
480 return;
481 }
482 _mesa_save_buffer_object(ctx, bufObj);
483 buffer[i] = first + i;
484 }
485
486 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
487 }
488
489
490 /**
491 * Determine if ID is the name of a buffer object.
492 *
493 * \param id ID of the potential buffer object.
494 * \return \c GL_TRUE if \c id is the name of a buffer object,
495 * \c GL_FALSE otherwise.
496 */
497 GLboolean
498 _mesa_IsBufferARB(GLuint id)
499 {
500 struct gl_buffer_object * bufObj;
501 GET_CURRENT_CONTEXT(ctx);
502 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
503
504 if (id == 0)
505 return GL_FALSE;
506
507 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
508 bufObj = (struct gl_buffer_object *) _mesa_HashLookup(ctx->Shared->BufferObjects, id);
509 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
510
511 return (bufObj != NULL);
512 }
513
514
515 void
516 _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
517 const GLvoid * data, GLenum usage)
518 {
519 GET_CURRENT_CONTEXT(ctx);
520 struct gl_buffer_object *bufObj;
521 ASSERT_OUTSIDE_BEGIN_END(ctx);
522
523 if (size < 0) {
524 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
525 return;
526 }
527
528 switch (usage) {
529 case GL_STREAM_DRAW_ARB:
530 case GL_STREAM_READ_ARB:
531 case GL_STREAM_COPY_ARB:
532 case GL_STATIC_DRAW_ARB:
533 case GL_STATIC_READ_ARB:
534 case GL_STATIC_COPY_ARB:
535 case GL_DYNAMIC_DRAW_ARB:
536 case GL_DYNAMIC_READ_ARB:
537 case GL_DYNAMIC_COPY_ARB:
538 /* OK */
539 break;
540 default:
541 _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)");
542 return;
543 }
544
545 bufObj = buffer_object_get_target( ctx, target, "BufferDataARB" );
546 if ( bufObj == NULL ) {
547 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB" );
548 return;
549 }
550
551 ASSERT(ctx->Driver.BufferData);
552
553 /* Give the buffer object to the driver! <data> may be null! */
554 (*ctx->Driver.BufferData)( ctx, target, size, data, usage, bufObj );
555 }
556
557
558 void
559 _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset,
560 GLsizeiptrARB size, const GLvoid * data)
561 {
562 GET_CURRENT_CONTEXT(ctx);
563 struct gl_buffer_object *bufObj;
564 ASSERT_OUTSIDE_BEGIN_END(ctx);
565
566 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
567 "glBufferSubDataARB" );
568 if (!bufObj) {
569 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubDataARB" );
570 return;
571 }
572
573 ASSERT(ctx->Driver.BufferSubData);
574 (*ctx->Driver.BufferSubData)( ctx, target, offset, size, data, bufObj );
575 }
576
577
578 void
579 _mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset,
580 GLsizeiptrARB size, void * data)
581 {
582 GET_CURRENT_CONTEXT(ctx);
583 struct gl_buffer_object *bufObj;
584 ASSERT_OUTSIDE_BEGIN_END(ctx);
585
586 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
587 "glGetBufferSubDataARB" );
588 if (!bufObj) {
589 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferSubDataARB" );
590 return;
591 }
592 ASSERT(ctx->Driver.GetBufferSubData);
593 (*ctx->Driver.GetBufferSubData)( ctx, target, offset, size, data, bufObj );
594 }
595
596
597 void *
598 _mesa_MapBufferARB(GLenum target, GLenum access)
599 {
600 GET_CURRENT_CONTEXT(ctx);
601 struct gl_buffer_object * bufObj;
602 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
603
604 switch (access) {
605 case GL_READ_ONLY_ARB:
606 case GL_WRITE_ONLY_ARB:
607 case GL_READ_WRITE_ARB:
608 /* OK */
609 break;
610 default:
611 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
612 return NULL;
613 }
614
615 bufObj = buffer_object_get_target( ctx, target, "MapBufferARB" );
616 if ( bufObj == NULL ) {
617 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB" );
618 return NULL;
619 }
620
621 if ( bufObj->pointer != NULL ) {
622 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB");
623 return NULL;
624 }
625
626 ASSERT(ctx->Driver.MapBuffer);
627 bufObj->pointer = (*ctx->Driver.MapBuffer)( ctx, target, access, bufObj );
628 if ( bufObj->pointer == NULL ) {
629 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
630 }
631
632 return bufObj->pointer;
633 }
634
635
636 GLboolean
637 _mesa_UnmapBufferARB(GLenum target)
638 {
639 GET_CURRENT_CONTEXT(ctx);
640 struct gl_buffer_object *bufObj;
641 GLboolean status = GL_TRUE;
642 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
643
644
645 bufObj = buffer_object_get_target( ctx, target, "UnmapBufferARB" );
646 if ( bufObj == NULL ) {
647 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferSubDataARB" );
648 return GL_FALSE;
649 }
650
651 if ( bufObj->pointer == NULL ) {
652 _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
653 return GL_FALSE;
654 }
655
656 if ( ctx->Driver.UnmapBuffer != NULL ) {
657 status = (*ctx->Driver.UnmapBuffer)( ctx, target, bufObj );
658 }
659
660 bufObj->pointer = NULL;
661
662 return status;
663 }
664
665
666 void
667 _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
668 {
669 GET_CURRENT_CONTEXT(ctx);
670 struct gl_buffer_object *bufObj;
671 ASSERT_OUTSIDE_BEGIN_END(ctx);
672
673 bufObj = buffer_object_get_target( ctx, target, "GetBufferParameterivARB" );
674 if (!bufObj) {
675 _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" );
676 return;
677 }
678
679 switch (pname) {
680 case GL_BUFFER_SIZE_ARB:
681 *params = bufObj->size;
682 break;
683 case GL_BUFFER_USAGE_ARB:
684 *params = bufObj->usage;
685 break;
686 case GL_BUFFER_ACCESS_ARB:
687 *params = bufObj->access;
688 break;
689 case GL_BUFFER_MAPPED_ARB:
690 *params = (bufObj->pointer != NULL);
691 break;
692 default:
693 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)");
694 return;
695 }
696 }
697
698
699 void
700 _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
701 {
702 GET_CURRENT_CONTEXT(ctx);
703 struct gl_buffer_object * bufObj;
704 ASSERT_OUTSIDE_BEGIN_END(ctx);
705
706 if (pname != GL_BUFFER_MAP_POINTER_ARB) {
707 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
708 return;
709 }
710
711 bufObj = buffer_object_get_target( ctx, target, "GetBufferPointervARB" );
712 if ( bufObj == NULL ) {
713 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" );
714 return;
715 }
716
717 *params = bufObj->pointer;
718 }