glsl: Change _mesa_glsl_parse_state ctor to use gl_shader_stage enum.
[mesa.git] / src / mesa / main / bufferobj.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. 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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /**
28 * \file bufferobj.c
29 * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
30 * \author Brian Paul, Ian Romanick
31 */
32
33 #include <stdbool.h>
34 #include "glheader.h"
35 #include "enums.h"
36 #include "hash.h"
37 #include "imports.h"
38 #include "image.h"
39 #include "context.h"
40 #include "bufferobj.h"
41 #include "fbobject.h"
42 #include "mtypes.h"
43 #include "texobj.h"
44 #include "teximage.h"
45 #include "glformats.h"
46 #include "texstore.h"
47 #include "transformfeedback.h"
48 #include "dispatch.h"
49
50
51 /* Debug flags */
52 /*#define VBO_DEBUG*/
53 /*#define BOUNDS_CHECK*/
54
55
56 /**
57 * Used as a placeholder for buffer objects between glGenBuffers() and
58 * glBindBuffer() so that glIsBuffer() can work correctly.
59 */
60 static struct gl_buffer_object DummyBufferObject;
61
62
63 /**
64 * Return pointer to address of a buffer object target.
65 * \param ctx the GL context
66 * \param target the buffer object target to be retrieved.
67 * \return pointer to pointer to the buffer object bound to \c target in the
68 * specified context or \c NULL if \c target is invalid.
69 */
70 static inline struct gl_buffer_object **
71 get_buffer_target(struct gl_context *ctx, GLenum target)
72 {
73 /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0.
74 */
75 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)
76 && target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER)
77 return NULL;
78
79 switch (target) {
80 case GL_ARRAY_BUFFER_ARB:
81 return &ctx->Array.ArrayBufferObj;
82 case GL_ELEMENT_ARRAY_BUFFER_ARB:
83 return &ctx->Array.ArrayObj->ElementArrayBufferObj;
84 case GL_PIXEL_PACK_BUFFER_EXT:
85 return &ctx->Pack.BufferObj;
86 case GL_PIXEL_UNPACK_BUFFER_EXT:
87 return &ctx->Unpack.BufferObj;
88 case GL_COPY_READ_BUFFER:
89 return &ctx->CopyReadBuffer;
90 case GL_COPY_WRITE_BUFFER:
91 return &ctx->CopyWriteBuffer;
92 case GL_DRAW_INDIRECT_BUFFER:
93 if (ctx->API == API_OPENGL_CORE &&
94 ctx->Extensions.ARB_draw_indirect) {
95 return &ctx->DrawIndirectBuffer;
96 }
97 break;
98 case GL_TRANSFORM_FEEDBACK_BUFFER:
99 if (ctx->Extensions.EXT_transform_feedback) {
100 return &ctx->TransformFeedback.CurrentBuffer;
101 }
102 break;
103 case GL_TEXTURE_BUFFER:
104 if (ctx->API == API_OPENGL_CORE &&
105 ctx->Extensions.ARB_texture_buffer_object) {
106 return &ctx->Texture.BufferObject;
107 }
108 break;
109 case GL_UNIFORM_BUFFER:
110 if (ctx->Extensions.ARB_uniform_buffer_object) {
111 return &ctx->UniformBuffer;
112 }
113 break;
114 case GL_ATOMIC_COUNTER_BUFFER:
115 if (ctx->Extensions.ARB_shader_atomic_counters) {
116 return &ctx->AtomicBuffer;
117 }
118 break;
119 default:
120 return NULL;
121 }
122 return NULL;
123 }
124
125
126 /**
127 * Get the buffer object bound to the specified target in a GL context.
128 * \param ctx the GL context
129 * \param target the buffer object target to be retrieved.
130 * \param error the GL error to record if target is illegal.
131 * \return pointer to the buffer object bound to \c target in the
132 * specified context or \c NULL if \c target is invalid.
133 */
134 static inline struct gl_buffer_object *
135 get_buffer(struct gl_context *ctx, const char *func, GLenum target,
136 GLenum error)
137 {
138 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
139
140 if (!bufObj) {
141 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
142 return NULL;
143 }
144
145 if (!_mesa_is_bufferobj(*bufObj)) {
146 _mesa_error(ctx, error, "%s(no buffer bound)", func);
147 return NULL;
148 }
149
150 return *bufObj;
151 }
152
153
154 /**
155 * Convert a GLbitfield describing the mapped buffer access flags
156 * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
157 */
158 static GLenum
159 simplified_access_mode(struct gl_context *ctx, GLbitfield access)
160 {
161 const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
162 if ((access & rwFlags) == rwFlags)
163 return GL_READ_WRITE;
164 if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
165 return GL_READ_ONLY;
166 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
167 return GL_WRITE_ONLY;
168
169 /* Otherwise, AccessFlags is zero (the default state).
170 *
171 * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says:
172 *
173 * Name Type Initial Value Legal Values
174 * ... ... ... ...
175 * BUFFER_ACCESS enum READ_WRITE READ_ONLY, WRITE_ONLY
176 * READ_WRITE
177 *
178 * However, table 6.8 in the GL_OES_mapbuffer extension says:
179 *
180 * Get Value Type Get Command Value Description
181 * --------- ---- ----------- ----- -----------
182 * BUFFER_ACCESS_OES Z1 GetBufferParameteriv WRITE_ONLY_OES buffer map flag
183 *
184 * The difference is because GL_OES_mapbuffer only supports mapping buffers
185 * write-only.
186 */
187 assert(access == 0);
188
189 return _mesa_is_gles(ctx) ? GL_WRITE_ONLY : GL_READ_WRITE;
190 }
191
192
193 /**
194 * Test if the buffer is mapped, and if so, if the mapped range overlaps the
195 * given range.
196 * The regions do not overlap if and only if the end of the given
197 * region is before the mapped region or the start of the given region
198 * is after the mapped region.
199 *
200 * \param obj Buffer object target on which to operate.
201 * \param offset Offset of the first byte of the subdata range.
202 * \param size Size, in bytes, of the subdata range.
203 * \return true if ranges overlap, false otherwise
204 *
205 */
206 static bool
207 bufferobj_range_mapped(const struct gl_buffer_object *obj,
208 GLintptr offset, GLsizeiptr size)
209 {
210 if (_mesa_bufferobj_mapped(obj)) {
211 const GLintptr end = offset + size;
212 const GLintptr mapEnd = obj->Offset + obj->Length;
213
214 if (!(end <= obj->Offset || offset >= mapEnd)) {
215 return true;
216 }
217 }
218 return false;
219 }
220
221
222 /**
223 * Tests the subdata range parameters and sets the GL error code for
224 * \c glBufferSubDataARB, \c glGetBufferSubDataARB and
225 * \c glClearBufferSubData.
226 *
227 * \param ctx GL context.
228 * \param target Buffer object target on which to operate.
229 * \param offset Offset of the first byte of the subdata range.
230 * \param size Size, in bytes, of the subdata range.
231 * \param mappedRange If true, checks if an overlapping range is mapped.
232 * If false, checks if buffer is mapped.
233 * \param errorNoBuffer Error code if no buffer is bound to target.
234 * \param caller Name of calling function for recording errors.
235 * \return A pointer to the buffer object bound to \c target in the
236 * specified context or \c NULL if any of the parameter or state
237 * conditions are invalid.
238 *
239 * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData
240 */
241 static struct gl_buffer_object *
242 buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target,
243 GLintptrARB offset, GLsizeiptrARB size,
244 bool mappedRange, GLenum errorNoBuffer,
245 const char *caller)
246 {
247 struct gl_buffer_object *bufObj;
248
249 if (size < 0) {
250 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
251 return NULL;
252 }
253
254 if (offset < 0) {
255 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
256 return NULL;
257 }
258
259 bufObj = get_buffer(ctx, caller, target, errorNoBuffer);
260 if (!bufObj)
261 return NULL;
262
263 if (offset + size > bufObj->Size) {
264 _mesa_error(ctx, GL_INVALID_VALUE,
265 "%s(offset %lu + size %lu > buffer size %lu)", caller,
266 (unsigned long) offset,
267 (unsigned long) size,
268 (unsigned long) bufObj->Size);
269 return NULL;
270 }
271
272 if (mappedRange) {
273 if (bufferobj_range_mapped(bufObj, offset, size)) {
274 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
275 return NULL;
276 }
277 }
278 else {
279 if (_mesa_bufferobj_mapped(bufObj)) {
280 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
281 return NULL;
282 }
283 }
284
285 return bufObj;
286 }
287
288
289 /**
290 * Test the format and type parameters and set the GL error code for
291 * \c glClearBufferData and \c glClearBufferSubData.
292 *
293 * \param ctx GL context.
294 * \param internalformat Format to which the data is to be converted.
295 * \param format Format of the supplied data.
296 * \param type Type of the supplied data.
297 * \param caller Name of calling function for recording errors.
298 * \return If internalformat, format and type are legal the gl_format
299 * corresponding to internalformat, otherwise MESA_FORMAT_NONE.
300 *
301 * \sa glClearBufferData and glClearBufferSubData
302 */
303 static gl_format
304 validate_clear_buffer_format(struct gl_context *ctx,
305 GLenum internalformat,
306 GLenum format, GLenum type,
307 const char *caller)
308 {
309 gl_format mesaFormat;
310 GLenum errorFormatType;
311
312 mesaFormat = _mesa_validate_texbuffer_format(ctx, internalformat);
313 if (mesaFormat == MESA_FORMAT_NONE) {
314 _mesa_error(ctx, GL_INVALID_ENUM,
315 "%s(invalid internalformat)", caller);
316 return MESA_FORMAT_NONE;
317 }
318
319 /* NOTE: not mentioned in ARB_clear_buffer_object but according to
320 * EXT_texture_integer there is no conversion between integer and
321 * non-integer formats
322 */
323 if (_mesa_is_enum_format_signed_int(format) !=
324 _mesa_is_format_integer_color(mesaFormat)) {
325 _mesa_error(ctx, GL_INVALID_OPERATION,
326 "%s(integer vs non-integer)", caller);
327 return MESA_FORMAT_NONE;
328 }
329
330 if (!_mesa_is_color_format(format)) {
331 _mesa_error(ctx, GL_INVALID_ENUM,
332 "%s(format is not a color format)", caller);
333 return MESA_FORMAT_NONE;
334 }
335
336 errorFormatType = _mesa_error_check_format_and_type(ctx, format, type);
337 if (errorFormatType != GL_NO_ERROR) {
338 _mesa_error(ctx, GL_INVALID_ENUM,
339 "%s(invalid format or type)", caller);
340 return MESA_FORMAT_NONE;
341 }
342
343 return mesaFormat;
344 }
345
346
347 /**
348 * Convert user-specified clear value to the specified internal format.
349 *
350 * \param ctx GL context.
351 * \param internalformat Format to which the data is converted.
352 * \param clearValue Points to the converted clear value.
353 * \param format Format of the supplied data.
354 * \param type Type of the supplied data.
355 * \param data Data which is to be converted to internalformat.
356 * \param caller Name of calling function for recording errors.
357 * \return true if data could be converted, false otherwise.
358 *
359 * \sa glClearBufferData, glClearBufferSubData
360 */
361 static bool
362 convert_clear_buffer_data(struct gl_context *ctx,
363 gl_format internalformat,
364 GLubyte *clearValue, GLenum format, GLenum type,
365 const GLvoid *data, const char *caller)
366 {
367 GLenum internalformatBase = _mesa_get_format_base_format(internalformat);
368
369 if (_mesa_texstore(ctx, 1, internalformatBase, internalformat,
370 0, &clearValue, 1, 1, 1,
371 format, type, data, &ctx->Unpack)) {
372 return true;
373 }
374 else {
375 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
376 return false;
377 }
378 }
379
380
381 /**
382 * Allocate and initialize a new buffer object.
383 *
384 * Default callback for the \c dd_function_table::NewBufferObject() hook.
385 */
386 static struct gl_buffer_object *
387 _mesa_new_buffer_object( struct gl_context *ctx, GLuint name, GLenum target )
388 {
389 struct gl_buffer_object *obj;
390
391 (void) ctx;
392
393 obj = MALLOC_STRUCT(gl_buffer_object);
394 _mesa_initialize_buffer_object(ctx, obj, name, target);
395 return obj;
396 }
397
398
399 /**
400 * Delete a buffer object.
401 *
402 * Default callback for the \c dd_function_table::DeleteBuffer() hook.
403 */
404 static void
405 _mesa_delete_buffer_object(struct gl_context *ctx,
406 struct gl_buffer_object *bufObj)
407 {
408 (void) ctx;
409
410 free(bufObj->Data);
411
412 /* assign strange values here to help w/ debugging */
413 bufObj->RefCount = -1000;
414 bufObj->Name = ~0;
415
416 _glthread_DESTROY_MUTEX(bufObj->Mutex);
417 free(bufObj->Label);
418 free(bufObj);
419 }
420
421
422
423 /**
424 * Set ptr to bufObj w/ reference counting.
425 * This is normally only called from the _mesa_reference_buffer_object() macro
426 * when there's a real pointer change.
427 */
428 void
429 _mesa_reference_buffer_object_(struct gl_context *ctx,
430 struct gl_buffer_object **ptr,
431 struct gl_buffer_object *bufObj)
432 {
433 if (*ptr) {
434 /* Unreference the old buffer */
435 GLboolean deleteFlag = GL_FALSE;
436 struct gl_buffer_object *oldObj = *ptr;
437
438 _glthread_LOCK_MUTEX(oldObj->Mutex);
439 ASSERT(oldObj->RefCount > 0);
440 oldObj->RefCount--;
441 #if 0
442 printf("BufferObj %p %d DECR to %d\n",
443 (void *) oldObj, oldObj->Name, oldObj->RefCount);
444 #endif
445 deleteFlag = (oldObj->RefCount == 0);
446 _glthread_UNLOCK_MUTEX(oldObj->Mutex);
447
448 if (deleteFlag) {
449
450 /* some sanity checking: don't delete a buffer still in use */
451 #if 0
452 /* unfortunately, these tests are invalid during context tear-down */
453 ASSERT(ctx->Array.ArrayBufferObj != bufObj);
454 ASSERT(ctx->Array.ArrayObj->ElementArrayBufferObj != bufObj);
455 ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj);
456 #endif
457
458 ASSERT(ctx->Driver.DeleteBuffer);
459 ctx->Driver.DeleteBuffer(ctx, oldObj);
460 }
461
462 *ptr = NULL;
463 }
464 ASSERT(!*ptr);
465
466 if (bufObj) {
467 /* reference new buffer */
468 _glthread_LOCK_MUTEX(bufObj->Mutex);
469 if (bufObj->RefCount == 0) {
470 /* this buffer's being deleted (look just above) */
471 /* Not sure this can every really happen. Warn if it does. */
472 _mesa_problem(NULL, "referencing deleted buffer object");
473 *ptr = NULL;
474 }
475 else {
476 bufObj->RefCount++;
477 #if 0
478 printf("BufferObj %p %d INCR to %d\n",
479 (void *) bufObj, bufObj->Name, bufObj->RefCount);
480 #endif
481 *ptr = bufObj;
482 }
483 _glthread_UNLOCK_MUTEX(bufObj->Mutex);
484 }
485 }
486
487
488 /**
489 * Initialize a buffer object to default values.
490 */
491 void
492 _mesa_initialize_buffer_object( struct gl_context *ctx,
493 struct gl_buffer_object *obj,
494 GLuint name, GLenum target )
495 {
496 (void) target;
497
498 memset(obj, 0, sizeof(struct gl_buffer_object));
499 _glthread_INIT_MUTEX(obj->Mutex);
500 obj->RefCount = 1;
501 obj->Name = name;
502 obj->Usage = GL_STATIC_DRAW_ARB;
503 obj->AccessFlags = 0;
504 }
505
506
507
508 /**
509 * Callback called from _mesa_HashWalk()
510 */
511 static void
512 count_buffer_size(GLuint key, void *data, void *userData)
513 {
514 const struct gl_buffer_object *bufObj =
515 (const struct gl_buffer_object *) data;
516 GLuint *total = (GLuint *) userData;
517
518 *total = *total + bufObj->Size;
519 }
520
521
522 /**
523 * Compute total size (in bytes) of all buffer objects for the given context.
524 * For debugging purposes.
525 */
526 GLuint
527 _mesa_total_buffer_object_memory(struct gl_context *ctx)
528 {
529 GLuint total = 0;
530
531 _mesa_HashWalk(ctx->Shared->BufferObjects, count_buffer_size, &total);
532
533 return total;
534 }
535
536
537 /**
538 * Allocate space for and store data in a buffer object. Any data that was
539 * previously stored in the buffer object is lost. If \c data is \c NULL,
540 * memory will be allocated, but no copy will occur.
541 *
542 * This is the default callback for \c dd_function_table::BufferData()
543 * Note that all GL error checking will have been done already.
544 *
545 * \param ctx GL context.
546 * \param target Buffer object target on which to operate.
547 * \param size Size, in bytes, of the new data store.
548 * \param data Pointer to the data to store in the buffer object. This
549 * pointer may be \c NULL.
550 * \param usage Hints about how the data will be used.
551 * \param bufObj Object to be used.
552 *
553 * \return GL_TRUE for success, GL_FALSE for failure
554 * \sa glBufferDataARB, dd_function_table::BufferData.
555 */
556 static GLboolean
557 _mesa_buffer_data( struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
558 const GLvoid * data, GLenum usage,
559 struct gl_buffer_object * bufObj )
560 {
561 void * new_data;
562
563 (void) ctx; (void) target;
564
565 new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size );
566 if (new_data) {
567 bufObj->Data = (GLubyte *) new_data;
568 bufObj->Size = size;
569 bufObj->Usage = usage;
570
571 if (data) {
572 memcpy( bufObj->Data, data, size );
573 }
574
575 return GL_TRUE;
576 }
577 else {
578 return GL_FALSE;
579 }
580 }
581
582
583 /**
584 * Replace data in a subrange of buffer object. If the data range
585 * specified by \c size + \c offset extends beyond the end of the buffer or
586 * if \c data is \c NULL, no copy is performed.
587 *
588 * This is the default callback for \c dd_function_table::BufferSubData()
589 * Note that all GL error checking will have been done already.
590 *
591 * \param ctx GL context.
592 * \param offset Offset of the first byte to be modified.
593 * \param size Size, in bytes, of the data range.
594 * \param data Pointer to the data to store in the buffer object.
595 * \param bufObj Object to be used.
596 *
597 * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
598 */
599 static void
600 _mesa_buffer_subdata( struct gl_context *ctx, GLintptrARB offset,
601 GLsizeiptrARB size, const GLvoid * data,
602 struct gl_buffer_object * bufObj )
603 {
604 (void) ctx;
605
606 /* this should have been caught in _mesa_BufferSubData() */
607 ASSERT(size + offset <= bufObj->Size);
608
609 if (bufObj->Data) {
610 memcpy( (GLubyte *) bufObj->Data + offset, data, size );
611 }
612 }
613
614
615 /**
616 * Retrieve data from a subrange of buffer object. If the data range
617 * specified by \c size + \c offset extends beyond the end of the buffer or
618 * if \c data is \c NULL, no copy is performed.
619 *
620 * This is the default callback for \c dd_function_table::GetBufferSubData()
621 * Note that all GL error checking will have been done already.
622 *
623 * \param ctx GL context.
624 * \param target Buffer object target on which to operate.
625 * \param offset Offset of the first byte to be fetched.
626 * \param size Size, in bytes, of the data range.
627 * \param data Destination for data
628 * \param bufObj Object to be used.
629 *
630 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
631 */
632 static void
633 _mesa_buffer_get_subdata( struct gl_context *ctx, GLintptrARB offset,
634 GLsizeiptrARB size, GLvoid * data,
635 struct gl_buffer_object * bufObj )
636 {
637 (void) ctx;
638
639 if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) {
640 memcpy( data, (GLubyte *) bufObj->Data + offset, size );
641 }
642 }
643
644
645 /**
646 * Clear a subrange of the buffer object with copies of the supplied data.
647 * If data is NULL the buffer is filled with zeros.
648 *
649 * This is the default callback for \c dd_function_table::ClearBufferSubData()
650 * Note that all GL error checking will have been done already.
651 *
652 * \param ctx GL context.
653 * \param offset Offset of the first byte to be cleared.
654 * \param size Size, in bytes, of the to be cleared range.
655 * \param clearValue Source of the data.
656 * \param clearValueSize Size, in bytes, of the supplied data.
657 * \param bufObj Object to be cleared.
658 *
659 * \sa glClearBufferSubData, glClearBufferData and
660 * dd_function_table::ClearBufferSubData.
661 */
662 static void
663 _mesa_buffer_clear_subdata(struct gl_context *ctx,
664 GLintptr offset, GLsizeiptr size,
665 const GLvoid *clearValue,
666 GLsizeiptr clearValueSize,
667 struct gl_buffer_object *bufObj)
668 {
669 GLsizeiptr i;
670 GLubyte *dest;
671
672 if (_mesa_bufferobj_mapped(bufObj)) {
673 GLubyte *data = malloc(size);
674 GLubyte *dataStart = data;
675 if (data == NULL) {
676 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data");
677 return;
678 }
679
680 if (clearValue == NULL) {
681 /* Clear with zeros, per the spec */
682 memset(data, 0, size);
683 }
684 else {
685 for (i = 0; i < size/clearValueSize; ++i) {
686 memcpy(data, clearValue, clearValueSize);
687 data += clearValueSize;
688 }
689 }
690 ctx->Driver.BufferSubData(ctx, offset, size, dataStart, bufObj);
691 return;
692 }
693
694 ASSERT(ctx->Driver.MapBufferRange);
695 dest = ctx->Driver.MapBufferRange(ctx, offset, size,
696 GL_MAP_WRITE_BIT |
697 GL_MAP_INVALIDATE_RANGE_BIT,
698 bufObj);
699
700 if (!dest) {
701 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data");
702 return;
703 }
704
705 if (clearValue == NULL) {
706 /* Clear with zeros, per the spec */
707 memset(dest, 0, size);
708 ctx->Driver.UnmapBuffer(ctx, bufObj);
709 return;
710 }
711
712 for (i = 0; i < size/clearValueSize; ++i) {
713 memcpy(dest, clearValue, clearValueSize);
714 dest += clearValueSize;
715 }
716
717 ctx->Driver.UnmapBuffer(ctx, bufObj);
718 }
719
720
721 /**
722 * Default fallback for \c dd_function_table::MapBufferRange().
723 * Called via glMapBufferRange().
724 */
725 static void *
726 _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset,
727 GLsizeiptr length, GLbitfield access,
728 struct gl_buffer_object *bufObj )
729 {
730 (void) ctx;
731 assert(!_mesa_bufferobj_mapped(bufObj));
732 /* Just return a direct pointer to the data */
733 bufObj->Pointer = bufObj->Data + offset;
734 bufObj->Length = length;
735 bufObj->Offset = offset;
736 bufObj->AccessFlags = access;
737 return bufObj->Pointer;
738 }
739
740
741 /**
742 * Default fallback for \c dd_function_table::FlushMappedBufferRange().
743 * Called via glFlushMappedBufferRange().
744 */
745 static void
746 _mesa_buffer_flush_mapped_range( struct gl_context *ctx,
747 GLintptr offset, GLsizeiptr length,
748 struct gl_buffer_object *obj )
749 {
750 (void) ctx;
751 (void) offset;
752 (void) length;
753 (void) obj;
754 /* no-op */
755 }
756
757
758 /**
759 * Default callback for \c dd_function_table::MapBuffer().
760 *
761 * The input parameters will have been already tested for errors.
762 *
763 * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
764 */
765 static GLboolean
766 _mesa_buffer_unmap( struct gl_context *ctx, struct gl_buffer_object *bufObj )
767 {
768 (void) ctx;
769 /* XXX we might assert here that bufObj->Pointer is non-null */
770 bufObj->Pointer = NULL;
771 bufObj->Length = 0;
772 bufObj->Offset = 0;
773 bufObj->AccessFlags = 0x0;
774 return GL_TRUE;
775 }
776
777
778 /**
779 * Default fallback for \c dd_function_table::CopyBufferSubData().
780 * Called via glCopyBufferSubData().
781 */
782 static void
783 _mesa_copy_buffer_subdata(struct gl_context *ctx,
784 struct gl_buffer_object *src,
785 struct gl_buffer_object *dst,
786 GLintptr readOffset, GLintptr writeOffset,
787 GLsizeiptr size)
788 {
789 GLubyte *srcPtr, *dstPtr;
790
791 /* the buffers should not be mapped */
792 assert(!_mesa_bufferobj_mapped(src));
793 assert(!_mesa_bufferobj_mapped(dst));
794
795 if (src == dst) {
796 srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size,
797 GL_MAP_READ_BIT |
798 GL_MAP_WRITE_BIT, src);
799
800 if (!srcPtr)
801 return;
802
803 srcPtr += readOffset;
804 dstPtr += writeOffset;
805 } else {
806 srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size,
807 GL_MAP_READ_BIT, src);
808 dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size,
809 (GL_MAP_WRITE_BIT |
810 GL_MAP_INVALIDATE_RANGE_BIT), dst);
811 }
812
813 /* Note: the src and dst regions will never overlap. Trying to do so
814 * would generate GL_INVALID_VALUE earlier.
815 */
816 if (srcPtr && dstPtr)
817 memcpy(dstPtr, srcPtr, size);
818
819 ctx->Driver.UnmapBuffer(ctx, src);
820 if (dst != src)
821 ctx->Driver.UnmapBuffer(ctx, dst);
822 }
823
824
825
826 /**
827 * Initialize the state associated with buffer objects
828 */
829 void
830 _mesa_init_buffer_objects( struct gl_context *ctx )
831 {
832 GLuint i;
833
834 memset(&DummyBufferObject, 0, sizeof(DummyBufferObject));
835 _glthread_INIT_MUTEX(DummyBufferObject.Mutex);
836 DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */
837
838 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj,
839 ctx->Shared->NullBufferObj);
840
841 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer,
842 ctx->Shared->NullBufferObj);
843 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer,
844 ctx->Shared->NullBufferObj);
845
846 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer,
847 ctx->Shared->NullBufferObj);
848
849 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer,
850 ctx->Shared->NullBufferObj);
851
852 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
853 _mesa_reference_buffer_object(ctx,
854 &ctx->UniformBufferBindings[i].BufferObject,
855 ctx->Shared->NullBufferObj);
856 ctx->UniformBufferBindings[i].Offset = -1;
857 ctx->UniformBufferBindings[i].Size = -1;
858 }
859 }
860
861
862 void
863 _mesa_free_buffer_objects( struct gl_context *ctx )
864 {
865 GLuint i;
866
867 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
868
869 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL);
870 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL);
871
872 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL);
873
874 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
875 _mesa_reference_buffer_object(ctx,
876 &ctx->UniformBufferBindings[i].BufferObject,
877 NULL);
878 }
879 }
880
881 bool
882 _mesa_handle_bind_buffer_gen(struct gl_context *ctx,
883 GLenum target,
884 GLuint buffer,
885 struct gl_buffer_object **buf_handle,
886 const char *caller)
887 {
888 struct gl_buffer_object *buf = *buf_handle;
889
890 if (!buf && ctx->API == API_OPENGL_CORE) {
891 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller);
892 return false;
893 }
894
895 if (!buf || buf == &DummyBufferObject) {
896 /* If this is a new buffer object id, or one which was generated but
897 * never used before, allocate a buffer object now.
898 */
899 ASSERT(ctx->Driver.NewBufferObject);
900 buf = ctx->Driver.NewBufferObject(ctx, buffer, target);
901 if (!buf) {
902 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
903 return false;
904 }
905 _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf);
906 *buf_handle = buf;
907 }
908
909 return true;
910 }
911
912 /**
913 * Bind the specified target to buffer for the specified context.
914 * Called by glBindBuffer() and other functions.
915 */
916 static void
917 bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer)
918 {
919 struct gl_buffer_object *oldBufObj;
920 struct gl_buffer_object *newBufObj = NULL;
921 struct gl_buffer_object **bindTarget = NULL;
922
923 bindTarget = get_buffer_target(ctx, target);
924 if (!bindTarget) {
925 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)", target);
926 return;
927 }
928
929 /* Get pointer to old buffer object (to be unbound) */
930 oldBufObj = *bindTarget;
931 if (oldBufObj && oldBufObj->Name == buffer && !oldBufObj->DeletePending)
932 return; /* rebinding the same buffer object- no change */
933
934 /*
935 * Get pointer to new buffer object (newBufObj)
936 */
937 if (buffer == 0) {
938 /* The spec says there's not a buffer object named 0, but we use
939 * one internally because it simplifies things.
940 */
941 newBufObj = ctx->Shared->NullBufferObj;
942 }
943 else {
944 /* non-default buffer object */
945 newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
946 if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer,
947 &newBufObj, "glBindBuffer"))
948 return;
949 }
950
951 /* bind new buffer */
952 _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
953
954 /* Pass BindBuffer call to device driver */
955 if (ctx->Driver.BindBuffer)
956 ctx->Driver.BindBuffer( ctx, target, newBufObj );
957 }
958
959
960 /**
961 * Update the default buffer objects in the given context to reference those
962 * specified in the shared state and release those referencing the old
963 * shared state.
964 */
965 void
966 _mesa_update_default_objects_buffer_objects(struct gl_context *ctx)
967 {
968 /* Bind the NullBufferObj to remove references to those
969 * in the shared context hash table.
970 */
971 bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0);
972 bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
973 bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0);
974 bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0);
975 }
976
977
978
979 /**
980 * Return the gl_buffer_object for the given ID.
981 * Always return NULL for ID 0.
982 */
983 struct gl_buffer_object *
984 _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer)
985 {
986 if (buffer == 0)
987 return NULL;
988 else
989 return (struct gl_buffer_object *)
990 _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
991 }
992
993
994 /**
995 * If *ptr points to obj, set ptr = the Null/default buffer object.
996 * This is a helper for buffer object deletion.
997 * The GL spec says that deleting a buffer object causes it to get
998 * unbound from all arrays in the current context.
999 */
1000 static void
1001 unbind(struct gl_context *ctx,
1002 struct gl_buffer_object **ptr,
1003 struct gl_buffer_object *obj)
1004 {
1005 if (*ptr == obj) {
1006 _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj);
1007 }
1008 }
1009
1010
1011 /**
1012 * Plug default/fallback buffer object functions into the device
1013 * driver hooks.
1014 */
1015 void
1016 _mesa_init_buffer_object_functions(struct dd_function_table *driver)
1017 {
1018 /* GL_ARB_vertex/pixel_buffer_object */
1019 driver->NewBufferObject = _mesa_new_buffer_object;
1020 driver->DeleteBuffer = _mesa_delete_buffer_object;
1021 driver->BindBuffer = NULL;
1022 driver->BufferData = _mesa_buffer_data;
1023 driver->BufferSubData = _mesa_buffer_subdata;
1024 driver->GetBufferSubData = _mesa_buffer_get_subdata;
1025 driver->UnmapBuffer = _mesa_buffer_unmap;
1026
1027 /* GL_ARB_clear_buffer_object */
1028 driver->ClearBufferSubData = _mesa_buffer_clear_subdata;
1029
1030 /* GL_ARB_map_buffer_range */
1031 driver->MapBufferRange = _mesa_buffer_map_range;
1032 driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range;
1033
1034 /* GL_ARB_copy_buffer */
1035 driver->CopyBufferSubData = _mesa_copy_buffer_subdata;
1036 }
1037
1038
1039
1040 /**********************************************************************/
1041 /* API Functions */
1042 /**********************************************************************/
1043
1044 void GLAPIENTRY
1045 _mesa_BindBuffer(GLenum target, GLuint buffer)
1046 {
1047 GET_CURRENT_CONTEXT(ctx);
1048
1049 if (MESA_VERBOSE & VERBOSE_API)
1050 _mesa_debug(ctx, "glBindBuffer(%s, %u)\n",
1051 _mesa_lookup_enum_by_nr(target), buffer);
1052
1053 bind_buffer_object(ctx, target, buffer);
1054 }
1055
1056
1057 /**
1058 * Delete a set of buffer objects.
1059 *
1060 * \param n Number of buffer objects to delete.
1061 * \param ids Array of \c n buffer object IDs.
1062 */
1063 void GLAPIENTRY
1064 _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
1065 {
1066 GET_CURRENT_CONTEXT(ctx);
1067 GLsizei i;
1068 FLUSH_VERTICES(ctx, 0);
1069
1070 if (n < 0) {
1071 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
1072 return;
1073 }
1074
1075 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1076
1077 for (i = 0; i < n; i++) {
1078 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
1079 if (bufObj) {
1080 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1081 GLuint j;
1082
1083 ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject);
1084
1085 if (_mesa_bufferobj_mapped(bufObj)) {
1086 /* if mapped, unmap it now */
1087 ctx->Driver.UnmapBuffer(ctx, bufObj);
1088 bufObj->AccessFlags = 0;
1089 bufObj->Pointer = NULL;
1090 }
1091
1092 /* unbind any vertex pointers bound to this buffer */
1093 for (j = 0; j < Elements(arrayObj->VertexBinding); j++) {
1094 unbind(ctx, &arrayObj->VertexBinding[j].BufferObj, bufObj);
1095 }
1096
1097 if (ctx->Array.ArrayBufferObj == bufObj) {
1098 _mesa_BindBuffer( GL_ARRAY_BUFFER_ARB, 0 );
1099 }
1100 if (arrayObj->ElementArrayBufferObj == bufObj) {
1101 _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
1102 }
1103
1104 /* unbind ARB_draw_indirect binding point */
1105 if (ctx->DrawIndirectBuffer == bufObj) {
1106 _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 );
1107 }
1108
1109 /* unbind ARB_copy_buffer binding points */
1110 if (ctx->CopyReadBuffer == bufObj) {
1111 _mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 );
1112 }
1113 if (ctx->CopyWriteBuffer == bufObj) {
1114 _mesa_BindBuffer( GL_COPY_WRITE_BUFFER, 0 );
1115 }
1116
1117 /* unbind transform feedback binding points */
1118 if (ctx->TransformFeedback.CurrentBuffer == bufObj) {
1119 _mesa_BindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, 0 );
1120 }
1121 for (j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
1122 if (ctx->TransformFeedback.CurrentObject->Buffers[j] == bufObj) {
1123 _mesa_BindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, j, 0 );
1124 }
1125 }
1126
1127 /* unbind UBO binding points */
1128 for (j = 0; j < ctx->Const.MaxUniformBufferBindings; j++) {
1129 if (ctx->UniformBufferBindings[j].BufferObject == bufObj) {
1130 _mesa_BindBufferBase( GL_UNIFORM_BUFFER, j, 0 );
1131 }
1132 }
1133
1134 if (ctx->UniformBuffer == bufObj) {
1135 _mesa_BindBuffer( GL_UNIFORM_BUFFER, 0 );
1136 }
1137
1138 /* unbind any pixel pack/unpack pointers bound to this buffer */
1139 if (ctx->Pack.BufferObj == bufObj) {
1140 _mesa_BindBuffer( GL_PIXEL_PACK_BUFFER_EXT, 0 );
1141 }
1142 if (ctx->Unpack.BufferObj == bufObj) {
1143 _mesa_BindBuffer( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
1144 }
1145
1146 if (ctx->Texture.BufferObject == bufObj) {
1147 _mesa_BindBuffer( GL_TEXTURE_BUFFER, 0 );
1148 }
1149
1150 /* The ID is immediately freed for re-use */
1151 _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]);
1152 /* Make sure we do not run into the classic ABA problem on bind.
1153 * We don't want to allow re-binding a buffer object that's been
1154 * "deleted" by glDeleteBuffers().
1155 *
1156 * The explicit rebinding to the default object in the current context
1157 * prevents the above in the current context, but another context
1158 * sharing the same objects might suffer from this problem.
1159 * The alternative would be to do the hash lookup in any case on bind
1160 * which would introduce more runtime overhead than this.
1161 */
1162 bufObj->DeletePending = GL_TRUE;
1163 _mesa_reference_buffer_object(ctx, &bufObj, NULL);
1164 }
1165 }
1166
1167 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1168 }
1169
1170
1171 /**
1172 * Generate a set of unique buffer object IDs and store them in \c buffer.
1173 *
1174 * \param n Number of IDs to generate.
1175 * \param buffer Array of \c n locations to store the IDs.
1176 */
1177 void GLAPIENTRY
1178 _mesa_GenBuffers(GLsizei n, GLuint *buffer)
1179 {
1180 GET_CURRENT_CONTEXT(ctx);
1181 GLuint first;
1182 GLint i;
1183
1184 if (MESA_VERBOSE & VERBOSE_API)
1185 _mesa_debug(ctx, "glGenBuffers(%d)\n", n);
1186
1187 if (n < 0) {
1188 _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB");
1189 return;
1190 }
1191
1192 if (!buffer) {
1193 return;
1194 }
1195
1196 /*
1197 * This must be atomic (generation and allocation of buffer object IDs)
1198 */
1199 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1200
1201 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
1202
1203 /* Insert the ID and pointer to dummy buffer object into hash table */
1204 for (i = 0; i < n; i++) {
1205 _mesa_HashInsert(ctx->Shared->BufferObjects, first + i,
1206 &DummyBufferObject);
1207 buffer[i] = first + i;
1208 }
1209
1210 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1211 }
1212
1213
1214 /**
1215 * Determine if ID is the name of a buffer object.
1216 *
1217 * \param id ID of the potential buffer object.
1218 * \return \c GL_TRUE if \c id is the name of a buffer object,
1219 * \c GL_FALSE otherwise.
1220 */
1221 GLboolean GLAPIENTRY
1222 _mesa_IsBuffer(GLuint id)
1223 {
1224 struct gl_buffer_object *bufObj;
1225 GET_CURRENT_CONTEXT(ctx);
1226 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1227
1228 _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1229 bufObj = _mesa_lookup_bufferobj(ctx, id);
1230 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1231
1232 return bufObj && bufObj != &DummyBufferObject;
1233 }
1234
1235
1236 void GLAPIENTRY
1237 _mesa_BufferData(GLenum target, GLsizeiptrARB size,
1238 const GLvoid * data, GLenum usage)
1239 {
1240 GET_CURRENT_CONTEXT(ctx);
1241 struct gl_buffer_object *bufObj;
1242 bool valid_usage;
1243
1244 if (MESA_VERBOSE & VERBOSE_API)
1245 _mesa_debug(ctx, "glBufferData(%s, %ld, %p, %s)\n",
1246 _mesa_lookup_enum_by_nr(target),
1247 (long int) size, data,
1248 _mesa_lookup_enum_by_nr(usage));
1249
1250 if (size < 0) {
1251 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)");
1252 return;
1253 }
1254
1255 switch (usage) {
1256 case GL_STREAM_DRAW_ARB:
1257 valid_usage = (ctx->API != API_OPENGLES);
1258 break;
1259
1260 case GL_STATIC_DRAW_ARB:
1261 case GL_DYNAMIC_DRAW_ARB:
1262 valid_usage = true;
1263 break;
1264
1265 case GL_STREAM_READ_ARB:
1266 case GL_STREAM_COPY_ARB:
1267 case GL_STATIC_READ_ARB:
1268 case GL_STATIC_COPY_ARB:
1269 case GL_DYNAMIC_READ_ARB:
1270 case GL_DYNAMIC_COPY_ARB:
1271 valid_usage = _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx);
1272 break;
1273
1274 default:
1275 valid_usage = false;
1276 break;
1277 }
1278
1279 if (!valid_usage) {
1280 _mesa_error(ctx, GL_INVALID_ENUM, "glBufferData(usage)");
1281 return;
1282 }
1283
1284 bufObj = get_buffer(ctx, "glBufferDataARB", target, GL_INVALID_OPERATION);
1285 if (!bufObj)
1286 return;
1287
1288 if (_mesa_bufferobj_mapped(bufObj)) {
1289 /* Unmap the existing buffer. We'll replace it now. Not an error. */
1290 ctx->Driver.UnmapBuffer(ctx, bufObj);
1291 bufObj->AccessFlags = 0;
1292 ASSERT(bufObj->Pointer == NULL);
1293 }
1294
1295 FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
1296
1297 bufObj->Written = GL_TRUE;
1298
1299 #ifdef VBO_DEBUG
1300 printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
1301 bufObj->Name, size, data, usage);
1302 #endif
1303
1304 #ifdef BOUNDS_CHECK
1305 size += 100;
1306 #endif
1307
1308 ASSERT(ctx->Driver.BufferData);
1309 if (!ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj )) {
1310 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()");
1311 }
1312 }
1313
1314
1315 void GLAPIENTRY
1316 _mesa_BufferSubData(GLenum target, GLintptrARB offset,
1317 GLsizeiptrARB size, const GLvoid * data)
1318 {
1319 GET_CURRENT_CONTEXT(ctx);
1320 struct gl_buffer_object *bufObj;
1321
1322 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size,
1323 false, GL_INVALID_OPERATION,
1324 "glBufferSubDataARB" );
1325 if (!bufObj) {
1326 /* error already recorded */
1327 return;
1328 }
1329
1330 if (size == 0)
1331 return;
1332
1333 bufObj->Written = GL_TRUE;
1334
1335 ASSERT(ctx->Driver.BufferSubData);
1336 ctx->Driver.BufferSubData( ctx, offset, size, data, bufObj );
1337 }
1338
1339
1340 void GLAPIENTRY
1341 _mesa_GetBufferSubData(GLenum target, GLintptrARB offset,
1342 GLsizeiptrARB size, void * data)
1343 {
1344 GET_CURRENT_CONTEXT(ctx);
1345 struct gl_buffer_object *bufObj;
1346
1347 bufObj = buffer_object_subdata_range_good(ctx, target, offset, size,
1348 false, GL_INVALID_OPERATION,
1349 "glGetBufferSubDataARB");
1350 if (!bufObj) {
1351 /* error already recorded */
1352 return;
1353 }
1354
1355 ASSERT(ctx->Driver.GetBufferSubData);
1356 ctx->Driver.GetBufferSubData( ctx, offset, size, data, bufObj );
1357 }
1358
1359
1360 void GLAPIENTRY
1361 _mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format,
1362 GLenum type, const GLvoid* data)
1363 {
1364 GET_CURRENT_CONTEXT(ctx);
1365 struct gl_buffer_object* bufObj;
1366 gl_format mesaFormat;
1367 GLubyte clearValue[MAX_PIXEL_BYTES];
1368 GLsizeiptr clearValueSize;
1369
1370 bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE);
1371 if (!bufObj) {
1372 return;
1373 }
1374
1375 if (_mesa_bufferobj_mapped(bufObj)) {
1376 _mesa_error(ctx, GL_INVALID_OPERATION,
1377 "glClearBufferData(buffer currently mapped)");
1378 return;
1379 }
1380
1381 mesaFormat = validate_clear_buffer_format(ctx, internalformat,
1382 format, type,
1383 "glClearBufferData");
1384 if (mesaFormat == MESA_FORMAT_NONE) {
1385 return;
1386 }
1387
1388 clearValueSize = _mesa_get_format_bytes(mesaFormat);
1389 if (bufObj->Size % clearValueSize != 0) {
1390 _mesa_error(ctx, GL_INVALID_VALUE,
1391 "glClearBufferData(size is not a multiple of "
1392 "internalformat size)");
1393 return;
1394 }
1395
1396 if (data == NULL) {
1397 /* clear to zeros, per the spec */
1398 ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size,
1399 NULL, 0, bufObj);
1400 return;
1401 }
1402
1403 if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue,
1404 format, type, data, "glClearBufferData")) {
1405 return;
1406 }
1407
1408 ctx->Driver.ClearBufferSubData(ctx, 0, bufObj->Size,
1409 clearValue, clearValueSize, bufObj);
1410 }
1411
1412
1413 void GLAPIENTRY
1414 _mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
1415 GLintptr offset, GLsizeiptr size,
1416 GLenum format, GLenum type,
1417 const GLvoid* data)
1418 {
1419 GET_CURRENT_CONTEXT(ctx);
1420 struct gl_buffer_object* bufObj;
1421 gl_format mesaFormat;
1422 GLubyte clearValue[MAX_PIXEL_BYTES];
1423 GLsizeiptr clearValueSize;
1424
1425 bufObj = buffer_object_subdata_range_good(ctx, target, offset, size,
1426 true, GL_INVALID_VALUE,
1427 "glClearBufferSubData");
1428 if (!bufObj) {
1429 return;
1430 }
1431
1432 mesaFormat = validate_clear_buffer_format(ctx, internalformat,
1433 format, type,
1434 "glClearBufferSubData");
1435 if (mesaFormat == MESA_FORMAT_NONE) {
1436 return;
1437 }
1438
1439 clearValueSize = _mesa_get_format_bytes(mesaFormat);
1440 if (offset % clearValueSize != 0 || size % clearValueSize != 0) {
1441 _mesa_error(ctx, GL_INVALID_VALUE,
1442 "glClearBufferSubData(offset or size is not a multiple of "
1443 "internalformat size)");
1444 return;
1445 }
1446
1447 if (data == NULL) {
1448 /* clear to zeros, per the spec */
1449 ctx->Driver.ClearBufferSubData(ctx, offset, size,
1450 NULL, 0, bufObj);
1451 return;
1452 }
1453
1454 if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue,
1455 format, type, data,
1456 "glClearBufferSubData")) {
1457 return;
1458 }
1459
1460 ctx->Driver.ClearBufferSubData(ctx, offset, size,
1461 clearValue, clearValueSize, bufObj);
1462 }
1463
1464
1465 void * GLAPIENTRY
1466 _mesa_MapBuffer(GLenum target, GLenum access)
1467 {
1468 GET_CURRENT_CONTEXT(ctx);
1469 struct gl_buffer_object * bufObj;
1470 GLbitfield accessFlags;
1471 void *map;
1472 bool valid_access;
1473
1474 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
1475
1476 switch (access) {
1477 case GL_READ_ONLY_ARB:
1478 accessFlags = GL_MAP_READ_BIT;
1479 valid_access = _mesa_is_desktop_gl(ctx);
1480 break;
1481 case GL_WRITE_ONLY_ARB:
1482 accessFlags = GL_MAP_WRITE_BIT;
1483 valid_access = true;
1484 break;
1485 case GL_READ_WRITE_ARB:
1486 accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
1487 valid_access = _mesa_is_desktop_gl(ctx);
1488 break;
1489 default:
1490 valid_access = false;
1491 break;
1492 }
1493
1494 if (!valid_access) {
1495 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
1496 return NULL;
1497 }
1498
1499 bufObj = get_buffer(ctx, "glMapBufferARB", target, GL_INVALID_OPERATION);
1500 if (!bufObj)
1501 return NULL;
1502
1503 if (_mesa_bufferobj_mapped(bufObj)) {
1504 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)");
1505 return NULL;
1506 }
1507
1508 if (!bufObj->Size) {
1509 _mesa_error(ctx, GL_OUT_OF_MEMORY,
1510 "glMapBuffer(buffer size = 0)");
1511 return NULL;
1512 }
1513
1514 ASSERT(ctx->Driver.MapBufferRange);
1515 map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj);
1516 if (!map) {
1517 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
1518 return NULL;
1519 }
1520 else {
1521 /* The driver callback should have set these fields.
1522 * This is important because other modules (like VBO) might call
1523 * the driver function directly.
1524 */
1525 ASSERT(bufObj->Pointer == map);
1526 ASSERT(bufObj->Length == bufObj->Size);
1527 ASSERT(bufObj->Offset == 0);
1528 bufObj->AccessFlags = accessFlags;
1529 }
1530
1531 if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
1532 bufObj->Written = GL_TRUE;
1533
1534 #ifdef VBO_DEBUG
1535 printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n",
1536 bufObj->Name, bufObj->Size, access);
1537 if (access == GL_WRITE_ONLY_ARB) {
1538 GLuint i;
1539 GLubyte *b = (GLubyte *) bufObj->Pointer;
1540 for (i = 0; i < bufObj->Size; i++)
1541 b[i] = i & 0xff;
1542 }
1543 #endif
1544
1545 #ifdef BOUNDS_CHECK
1546 {
1547 GLubyte *buf = (GLubyte *) bufObj->Pointer;
1548 GLuint i;
1549 /* buffer is 100 bytes larger than requested, fill with magic value */
1550 for (i = 0; i < 100; i++) {
1551 buf[bufObj->Size - i - 1] = 123;
1552 }
1553 }
1554 #endif
1555
1556 return bufObj->Pointer;
1557 }
1558
1559
1560 GLboolean GLAPIENTRY
1561 _mesa_UnmapBuffer(GLenum target)
1562 {
1563 GET_CURRENT_CONTEXT(ctx);
1564 struct gl_buffer_object *bufObj;
1565 GLboolean status = GL_TRUE;
1566 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1567
1568 bufObj = get_buffer(ctx, "glUnmapBufferARB", target, GL_INVALID_OPERATION);
1569 if (!bufObj)
1570 return GL_FALSE;
1571
1572 if (!_mesa_bufferobj_mapped(bufObj)) {
1573 _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB");
1574 return GL_FALSE;
1575 }
1576
1577 #ifdef BOUNDS_CHECK
1578 if (bufObj->Access != GL_READ_ONLY_ARB) {
1579 GLubyte *buf = (GLubyte *) bufObj->Pointer;
1580 GLuint i;
1581 /* check that last 100 bytes are still = magic value */
1582 for (i = 0; i < 100; i++) {
1583 GLuint pos = bufObj->Size - i - 1;
1584 if (buf[pos] != 123) {
1585 _mesa_warning(ctx, "Out of bounds buffer object write detected"
1586 " at position %d (value = %u)\n",
1587 pos, buf[pos]);
1588 }
1589 }
1590 }
1591 #endif
1592
1593 #ifdef VBO_DEBUG
1594 if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
1595 GLuint i, unchanged = 0;
1596 GLubyte *b = (GLubyte *) bufObj->Pointer;
1597 GLint pos = -1;
1598 /* check which bytes changed */
1599 for (i = 0; i < bufObj->Size - 1; i++) {
1600 if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
1601 unchanged++;
1602 if (pos == -1)
1603 pos = i;
1604 }
1605 }
1606 if (unchanged) {
1607 printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
1608 bufObj->Name, unchanged, bufObj->Size, pos);
1609 }
1610 }
1611 #endif
1612
1613 status = ctx->Driver.UnmapBuffer( ctx, bufObj );
1614 bufObj->AccessFlags = 0;
1615 ASSERT(bufObj->Pointer == NULL);
1616 ASSERT(bufObj->Offset == 0);
1617 ASSERT(bufObj->Length == 0);
1618
1619 return status;
1620 }
1621
1622
1623 void GLAPIENTRY
1624 _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
1625 {
1626 GET_CURRENT_CONTEXT(ctx);
1627 struct gl_buffer_object *bufObj;
1628
1629 bufObj = get_buffer(ctx, "glGetBufferParameterivARB", target,
1630 GL_INVALID_OPERATION);
1631 if (!bufObj)
1632 return;
1633
1634 switch (pname) {
1635 case GL_BUFFER_SIZE_ARB:
1636 *params = (GLint) bufObj->Size;
1637 return;
1638 case GL_BUFFER_USAGE_ARB:
1639 *params = bufObj->Usage;
1640 return;
1641 case GL_BUFFER_ACCESS_ARB:
1642 *params = simplified_access_mode(ctx, bufObj->AccessFlags);
1643 return;
1644 case GL_BUFFER_MAPPED_ARB:
1645 *params = _mesa_bufferobj_mapped(bufObj);
1646 return;
1647 case GL_BUFFER_ACCESS_FLAGS:
1648 if (!ctx->Extensions.ARB_map_buffer_range)
1649 goto invalid_pname;
1650 *params = bufObj->AccessFlags;
1651 return;
1652 case GL_BUFFER_MAP_OFFSET:
1653 if (!ctx->Extensions.ARB_map_buffer_range)
1654 goto invalid_pname;
1655 *params = (GLint) bufObj->Offset;
1656 return;
1657 case GL_BUFFER_MAP_LENGTH:
1658 if (!ctx->Extensions.ARB_map_buffer_range)
1659 goto invalid_pname;
1660 *params = (GLint) bufObj->Length;
1661 return;
1662 default:
1663 ; /* fall-through */
1664 }
1665
1666 invalid_pname:
1667 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname=%s)",
1668 _mesa_lookup_enum_by_nr(pname));
1669 }
1670
1671
1672 /**
1673 * New in GL 3.2
1674 * This is pretty much a duplicate of GetBufferParameteriv() but the
1675 * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system.
1676 */
1677 void GLAPIENTRY
1678 _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
1679 {
1680 GET_CURRENT_CONTEXT(ctx);
1681 struct gl_buffer_object *bufObj;
1682
1683 bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target,
1684 GL_INVALID_OPERATION);
1685 if (!bufObj)
1686 return;
1687
1688 switch (pname) {
1689 case GL_BUFFER_SIZE_ARB:
1690 *params = bufObj->Size;
1691 return;
1692 case GL_BUFFER_USAGE_ARB:
1693 *params = bufObj->Usage;
1694 return;
1695 case GL_BUFFER_ACCESS_ARB:
1696 *params = simplified_access_mode(ctx, bufObj->AccessFlags);
1697 return;
1698 case GL_BUFFER_ACCESS_FLAGS:
1699 if (!ctx->Extensions.ARB_map_buffer_range)
1700 goto invalid_pname;
1701 *params = bufObj->AccessFlags;
1702 return;
1703 case GL_BUFFER_MAPPED_ARB:
1704 *params = _mesa_bufferobj_mapped(bufObj);
1705 return;
1706 case GL_BUFFER_MAP_OFFSET:
1707 if (!ctx->Extensions.ARB_map_buffer_range)
1708 goto invalid_pname;
1709 *params = bufObj->Offset;
1710 return;
1711 case GL_BUFFER_MAP_LENGTH:
1712 if (!ctx->Extensions.ARB_map_buffer_range)
1713 goto invalid_pname;
1714 *params = bufObj->Length;
1715 return;
1716 default:
1717 ; /* fall-through */
1718 }
1719
1720 invalid_pname:
1721 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameteri64v(pname=%s)",
1722 _mesa_lookup_enum_by_nr(pname));
1723 }
1724
1725
1726 void GLAPIENTRY
1727 _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params)
1728 {
1729 GET_CURRENT_CONTEXT(ctx);
1730 struct gl_buffer_object * bufObj;
1731
1732 if (pname != GL_BUFFER_MAP_POINTER_ARB) {
1733 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)");
1734 return;
1735 }
1736
1737 bufObj = get_buffer(ctx, "glGetBufferPointervARB", target,
1738 GL_INVALID_OPERATION);
1739 if (!bufObj)
1740 return;
1741
1742 *params = bufObj->Pointer;
1743 }
1744
1745
1746 void GLAPIENTRY
1747 _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
1748 GLintptr readOffset, GLintptr writeOffset,
1749 GLsizeiptr size)
1750 {
1751 GET_CURRENT_CONTEXT(ctx);
1752 struct gl_buffer_object *src, *dst;
1753
1754 src = get_buffer(ctx, "glCopyBufferSubData", readTarget,
1755 GL_INVALID_OPERATION);
1756 if (!src)
1757 return;
1758
1759 dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget,
1760 GL_INVALID_OPERATION);
1761 if (!dst)
1762 return;
1763
1764 if (_mesa_bufferobj_mapped(src)) {
1765 _mesa_error(ctx, GL_INVALID_OPERATION,
1766 "glCopyBufferSubData(readBuffer is mapped)");
1767 return;
1768 }
1769
1770 if (_mesa_bufferobj_mapped(dst)) {
1771 _mesa_error(ctx, GL_INVALID_OPERATION,
1772 "glCopyBufferSubData(writeBuffer is mapped)");
1773 return;
1774 }
1775
1776 if (readOffset < 0) {
1777 _mesa_error(ctx, GL_INVALID_VALUE,
1778 "glCopyBufferSubData(readOffset = %d)", (int) readOffset);
1779 return;
1780 }
1781
1782 if (writeOffset < 0) {
1783 _mesa_error(ctx, GL_INVALID_VALUE,
1784 "glCopyBufferSubData(writeOffset = %d)", (int) writeOffset);
1785 return;
1786 }
1787
1788 if (size < 0) {
1789 _mesa_error(ctx, GL_INVALID_VALUE,
1790 "glCopyBufferSubData(writeOffset = %d)", (int) size);
1791 return;
1792 }
1793
1794 if (readOffset + size > src->Size) {
1795 _mesa_error(ctx, GL_INVALID_VALUE,
1796 "glCopyBufferSubData(readOffset + size = %d)",
1797 (int) (readOffset + size));
1798 return;
1799 }
1800
1801 if (writeOffset + size > dst->Size) {
1802 _mesa_error(ctx, GL_INVALID_VALUE,
1803 "glCopyBufferSubData(writeOffset + size = %d)",
1804 (int) (writeOffset + size));
1805 return;
1806 }
1807
1808 if (src == dst) {
1809 if (readOffset + size <= writeOffset) {
1810 /* OK */
1811 }
1812 else if (writeOffset + size <= readOffset) {
1813 /* OK */
1814 }
1815 else {
1816 /* overlapping src/dst is illegal */
1817 _mesa_error(ctx, GL_INVALID_VALUE,
1818 "glCopyBufferSubData(overlapping src/dst)");
1819 return;
1820 }
1821 }
1822
1823 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
1824 }
1825
1826
1827 /**
1828 * See GL_ARB_map_buffer_range spec
1829 */
1830 void * GLAPIENTRY
1831 _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
1832 GLbitfield access)
1833 {
1834 GET_CURRENT_CONTEXT(ctx);
1835 struct gl_buffer_object *bufObj;
1836 void *map;
1837
1838 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
1839
1840 if (!ctx->Extensions.ARB_map_buffer_range) {
1841 _mesa_error(ctx, GL_INVALID_OPERATION,
1842 "glMapBufferRange(extension not supported)");
1843 return NULL;
1844 }
1845
1846 if (offset < 0) {
1847 _mesa_error(ctx, GL_INVALID_VALUE,
1848 "glMapBufferRange(offset = %ld)", (long)offset);
1849 return NULL;
1850 }
1851
1852 if (length < 0) {
1853 _mesa_error(ctx, GL_INVALID_VALUE,
1854 "glMapBufferRange(length = %ld)", (long)length);
1855 return NULL;
1856 }
1857
1858 /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
1859 *
1860 * "An INVALID_OPERATION error is generated for any of the following
1861 * conditions:
1862 *
1863 * * <length> is zero."
1864 */
1865 if (_mesa_is_gles(ctx) && length == 0) {
1866 _mesa_error(ctx, GL_INVALID_OPERATION,
1867 "glMapBufferRange(length = 0)");
1868 return NULL;
1869 }
1870
1871 if (access & ~(GL_MAP_READ_BIT |
1872 GL_MAP_WRITE_BIT |
1873 GL_MAP_INVALIDATE_RANGE_BIT |
1874 GL_MAP_INVALIDATE_BUFFER_BIT |
1875 GL_MAP_FLUSH_EXPLICIT_BIT |
1876 GL_MAP_UNSYNCHRONIZED_BIT)) {
1877 /* generate an error if any undefind bit is set */
1878 _mesa_error(ctx, GL_INVALID_VALUE, "glMapBufferRange(access)");
1879 return NULL;
1880 }
1881
1882 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
1883 _mesa_error(ctx, GL_INVALID_OPERATION,
1884 "glMapBufferRange(access indicates neither read or write)");
1885 return NULL;
1886 }
1887
1888 if ((access & GL_MAP_READ_BIT) &&
1889 (access & (GL_MAP_INVALIDATE_RANGE_BIT |
1890 GL_MAP_INVALIDATE_BUFFER_BIT |
1891 GL_MAP_UNSYNCHRONIZED_BIT))) {
1892 _mesa_error(ctx, GL_INVALID_OPERATION,
1893 "glMapBufferRange(invalid access flags)");
1894 return NULL;
1895 }
1896
1897 if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
1898 ((access & GL_MAP_WRITE_BIT) == 0)) {
1899 _mesa_error(ctx, GL_INVALID_OPERATION,
1900 "glMapBufferRange(invalid access flags)");
1901 return NULL;
1902 }
1903
1904 bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION);
1905 if (!bufObj)
1906 return NULL;
1907
1908 if (offset + length > bufObj->Size) {
1909 _mesa_error(ctx, GL_INVALID_VALUE,
1910 "glMapBufferRange(offset + length > size)");
1911 return NULL;
1912 }
1913
1914 if (_mesa_bufferobj_mapped(bufObj)) {
1915 _mesa_error(ctx, GL_INVALID_OPERATION,
1916 "glMapBufferRange(buffer already mapped)");
1917 return NULL;
1918 }
1919
1920 if (!bufObj->Size) {
1921 _mesa_error(ctx, GL_OUT_OF_MEMORY,
1922 "glMapBufferRange(buffer size = 0)");
1923 return NULL;
1924 }
1925
1926 /* Mapping zero bytes should return a non-null pointer. */
1927 if (!length) {
1928 static long dummy = 0;
1929 bufObj->Pointer = &dummy;
1930 bufObj->Length = length;
1931 bufObj->Offset = offset;
1932 bufObj->AccessFlags = access;
1933 return bufObj->Pointer;
1934 }
1935
1936 ASSERT(ctx->Driver.MapBufferRange);
1937 map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj);
1938 if (!map) {
1939 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)");
1940 }
1941 else {
1942 /* The driver callback should have set all these fields.
1943 * This is important because other modules (like VBO) might call
1944 * the driver function directly.
1945 */
1946 ASSERT(bufObj->Pointer == map);
1947 ASSERT(bufObj->Length == length);
1948 ASSERT(bufObj->Offset == offset);
1949 ASSERT(bufObj->AccessFlags == access);
1950 }
1951
1952 return map;
1953 }
1954
1955
1956 /**
1957 * See GL_ARB_map_buffer_range spec
1958 */
1959 void GLAPIENTRY
1960 _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
1961 {
1962 GET_CURRENT_CONTEXT(ctx);
1963 struct gl_buffer_object *bufObj;
1964
1965 if (!ctx->Extensions.ARB_map_buffer_range) {
1966 _mesa_error(ctx, GL_INVALID_OPERATION,
1967 "glFlushMappedBufferRange(extension not supported)");
1968 return;
1969 }
1970
1971 if (offset < 0) {
1972 _mesa_error(ctx, GL_INVALID_VALUE,
1973 "glFlushMappedBufferRange(offset = %ld)", (long)offset);
1974 return;
1975 }
1976
1977 if (length < 0) {
1978 _mesa_error(ctx, GL_INVALID_VALUE,
1979 "glFlushMappedBufferRange(length = %ld)", (long)length);
1980 return;
1981 }
1982
1983 bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target,
1984 GL_INVALID_OPERATION);
1985 if (!bufObj)
1986 return;
1987
1988 if (!_mesa_bufferobj_mapped(bufObj)) {
1989 /* buffer is not mapped */
1990 _mesa_error(ctx, GL_INVALID_OPERATION,
1991 "glFlushMappedBufferRange(buffer is not mapped)");
1992 return;
1993 }
1994
1995 if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
1996 _mesa_error(ctx, GL_INVALID_OPERATION,
1997 "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
1998 return;
1999 }
2000
2001 if (offset + length > bufObj->Length) {
2002 _mesa_error(ctx, GL_INVALID_VALUE,
2003 "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)",
2004 (long)offset, (long)length, (long)bufObj->Length);
2005 return;
2006 }
2007
2008 ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT);
2009
2010 if (ctx->Driver.FlushMappedBufferRange)
2011 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj);
2012 }
2013
2014
2015 static GLenum
2016 buffer_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
2017 {
2018 struct gl_buffer_object *bufObj;
2019 GLenum retval;
2020
2021 bufObj = _mesa_lookup_bufferobj(ctx, name);
2022 if (!bufObj) {
2023 _mesa_error(ctx, GL_INVALID_VALUE,
2024 "glObjectPurgeable(name = 0x%x)", name);
2025 return 0;
2026 }
2027 if (!_mesa_is_bufferobj(bufObj)) {
2028 _mesa_error(ctx, GL_INVALID_OPERATION, "glObjectPurgeable(buffer 0)" );
2029 return 0;
2030 }
2031
2032 if (bufObj->Purgeable) {
2033 _mesa_error(ctx, GL_INVALID_OPERATION,
2034 "glObjectPurgeable(name = 0x%x) is already purgeable", name);
2035 return GL_VOLATILE_APPLE;
2036 }
2037
2038 bufObj->Purgeable = GL_TRUE;
2039
2040 retval = GL_VOLATILE_APPLE;
2041 if (ctx->Driver.BufferObjectPurgeable)
2042 retval = ctx->Driver.BufferObjectPurgeable(ctx, bufObj, option);
2043
2044 return retval;
2045 }
2046
2047
2048 static GLenum
2049 renderbuffer_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
2050 {
2051 struct gl_renderbuffer *bufObj;
2052 GLenum retval;
2053
2054 bufObj = _mesa_lookup_renderbuffer(ctx, name);
2055 if (!bufObj) {
2056 _mesa_error(ctx, GL_INVALID_VALUE,
2057 "glObjectUnpurgeable(name = 0x%x)", name);
2058 return 0;
2059 }
2060
2061 if (bufObj->Purgeable) {
2062 _mesa_error(ctx, GL_INVALID_OPERATION,
2063 "glObjectPurgeable(name = 0x%x) is already purgeable", name);
2064 return GL_VOLATILE_APPLE;
2065 }
2066
2067 bufObj->Purgeable = GL_TRUE;
2068
2069 retval = GL_VOLATILE_APPLE;
2070 if (ctx->Driver.RenderObjectPurgeable)
2071 retval = ctx->Driver.RenderObjectPurgeable(ctx, bufObj, option);
2072
2073 return retval;
2074 }
2075
2076
2077 static GLenum
2078 texture_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
2079 {
2080 struct gl_texture_object *bufObj;
2081 GLenum retval;
2082
2083 bufObj = _mesa_lookup_texture(ctx, name);
2084 if (!bufObj) {
2085 _mesa_error(ctx, GL_INVALID_VALUE,
2086 "glObjectPurgeable(name = 0x%x)", name);
2087 return 0;
2088 }
2089
2090 if (bufObj->Purgeable) {
2091 _mesa_error(ctx, GL_INVALID_OPERATION,
2092 "glObjectPurgeable(name = 0x%x) is already purgeable", name);
2093 return GL_VOLATILE_APPLE;
2094 }
2095
2096 bufObj->Purgeable = GL_TRUE;
2097
2098 retval = GL_VOLATILE_APPLE;
2099 if (ctx->Driver.TextureObjectPurgeable)
2100 retval = ctx->Driver.TextureObjectPurgeable(ctx, bufObj, option);
2101
2102 return retval;
2103 }
2104
2105
2106 GLenum GLAPIENTRY
2107 _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
2108 {
2109 GLenum retval;
2110
2111 GET_CURRENT_CONTEXT(ctx);
2112 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
2113
2114 if (name == 0) {
2115 _mesa_error(ctx, GL_INVALID_VALUE,
2116 "glObjectPurgeable(name = 0x%x)", name);
2117 return 0;
2118 }
2119
2120 switch (option) {
2121 case GL_VOLATILE_APPLE:
2122 case GL_RELEASED_APPLE:
2123 /* legal */
2124 break;
2125 default:
2126 _mesa_error(ctx, GL_INVALID_ENUM,
2127 "glObjectPurgeable(name = 0x%x) invalid option: %d",
2128 name, option);
2129 return 0;
2130 }
2131
2132 switch (objectType) {
2133 case GL_TEXTURE:
2134 retval = texture_object_purgeable(ctx, name, option);
2135 break;
2136 case GL_RENDERBUFFER_EXT:
2137 retval = renderbuffer_purgeable(ctx, name, option);
2138 break;
2139 case GL_BUFFER_OBJECT_APPLE:
2140 retval = buffer_object_purgeable(ctx, name, option);
2141 break;
2142 default:
2143 _mesa_error(ctx, GL_INVALID_ENUM,
2144 "glObjectPurgeable(name = 0x%x) invalid type: %d",
2145 name, objectType);
2146 return 0;
2147 }
2148
2149 /* In strict conformance to the spec, we must only return VOLATILE when
2150 * when passed the VOLATILE option. Madness.
2151 *
2152 * XXX First fix the spec, then fix me.
2153 */
2154 return option == GL_VOLATILE_APPLE ? GL_VOLATILE_APPLE : retval;
2155 }
2156
2157
2158 static GLenum
2159 buffer_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
2160 {
2161 struct gl_buffer_object *bufObj;
2162 GLenum retval;
2163
2164 bufObj = _mesa_lookup_bufferobj(ctx, name);
2165 if (!bufObj) {
2166 _mesa_error(ctx, GL_INVALID_VALUE,
2167 "glObjectUnpurgeable(name = 0x%x)", name);
2168 return 0;
2169 }
2170
2171 if (! bufObj->Purgeable) {
2172 _mesa_error(ctx, GL_INVALID_OPERATION,
2173 "glObjectUnpurgeable(name = 0x%x) object is "
2174 " already \"unpurged\"", name);
2175 return 0;
2176 }
2177
2178 bufObj->Purgeable = GL_FALSE;
2179
2180 retval = option;
2181 if (ctx->Driver.BufferObjectUnpurgeable)
2182 retval = ctx->Driver.BufferObjectUnpurgeable(ctx, bufObj, option);
2183
2184 return retval;
2185 }
2186
2187
2188 static GLenum
2189 renderbuffer_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
2190 {
2191 struct gl_renderbuffer *bufObj;
2192 GLenum retval;
2193
2194 bufObj = _mesa_lookup_renderbuffer(ctx, name);
2195 if (!bufObj) {
2196 _mesa_error(ctx, GL_INVALID_VALUE,
2197 "glObjectUnpurgeable(name = 0x%x)", name);
2198 return 0;
2199 }
2200
2201 if (! bufObj->Purgeable) {
2202 _mesa_error(ctx, GL_INVALID_OPERATION,
2203 "glObjectUnpurgeable(name = 0x%x) object is "
2204 " already \"unpurged\"", name);
2205 return 0;
2206 }
2207
2208 bufObj->Purgeable = GL_FALSE;
2209
2210 retval = option;
2211 if (ctx->Driver.RenderObjectUnpurgeable)
2212 retval = ctx->Driver.RenderObjectUnpurgeable(ctx, bufObj, option);
2213
2214 return retval;
2215 }
2216
2217
2218 static GLenum
2219 texture_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
2220 {
2221 struct gl_texture_object *bufObj;
2222 GLenum retval;
2223
2224 bufObj = _mesa_lookup_texture(ctx, name);
2225 if (!bufObj) {
2226 _mesa_error(ctx, GL_INVALID_VALUE,
2227 "glObjectUnpurgeable(name = 0x%x)", name);
2228 return 0;
2229 }
2230
2231 if (! bufObj->Purgeable) {
2232 _mesa_error(ctx, GL_INVALID_OPERATION,
2233 "glObjectUnpurgeable(name = 0x%x) object is"
2234 " already \"unpurged\"", name);
2235 return 0;
2236 }
2237
2238 bufObj->Purgeable = GL_FALSE;
2239
2240 retval = option;
2241 if (ctx->Driver.TextureObjectUnpurgeable)
2242 retval = ctx->Driver.TextureObjectUnpurgeable(ctx, bufObj, option);
2243
2244 return retval;
2245 }
2246
2247
2248 GLenum GLAPIENTRY
2249 _mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option)
2250 {
2251 GET_CURRENT_CONTEXT(ctx);
2252 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
2253
2254 if (name == 0) {
2255 _mesa_error(ctx, GL_INVALID_VALUE,
2256 "glObjectUnpurgeable(name = 0x%x)", name);
2257 return 0;
2258 }
2259
2260 switch (option) {
2261 case GL_RETAINED_APPLE:
2262 case GL_UNDEFINED_APPLE:
2263 /* legal */
2264 break;
2265 default:
2266 _mesa_error(ctx, GL_INVALID_ENUM,
2267 "glObjectUnpurgeable(name = 0x%x) invalid option: %d",
2268 name, option);
2269 return 0;
2270 }
2271
2272 switch (objectType) {
2273 case GL_BUFFER_OBJECT_APPLE:
2274 return buffer_object_unpurgeable(ctx, name, option);
2275 case GL_TEXTURE:
2276 return texture_object_unpurgeable(ctx, name, option);
2277 case GL_RENDERBUFFER_EXT:
2278 return renderbuffer_unpurgeable(ctx, name, option);
2279 default:
2280 _mesa_error(ctx, GL_INVALID_ENUM,
2281 "glObjectUnpurgeable(name = 0x%x) invalid type: %d",
2282 name, objectType);
2283 return 0;
2284 }
2285 }
2286
2287
2288 static void
2289 get_buffer_object_parameteriv(struct gl_context *ctx, GLuint name,
2290 GLenum pname, GLint *params)
2291 {
2292 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name);
2293 if (!bufObj) {
2294 _mesa_error(ctx, GL_INVALID_VALUE,
2295 "glGetObjectParameteriv(name = 0x%x) invalid object", name);
2296 return;
2297 }
2298
2299 switch (pname) {
2300 case GL_PURGEABLE_APPLE:
2301 *params = bufObj->Purgeable;
2302 break;
2303 default:
2304 _mesa_error(ctx, GL_INVALID_ENUM,
2305 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
2306 name, pname);
2307 break;
2308 }
2309 }
2310
2311
2312 static void
2313 get_renderbuffer_parameteriv(struct gl_context *ctx, GLuint name,
2314 GLenum pname, GLint *params)
2315 {
2316 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
2317 if (!rb) {
2318 _mesa_error(ctx, GL_INVALID_VALUE,
2319 "glObjectUnpurgeable(name = 0x%x)", name);
2320 return;
2321 }
2322
2323 switch (pname) {
2324 case GL_PURGEABLE_APPLE:
2325 *params = rb->Purgeable;
2326 break;
2327 default:
2328 _mesa_error(ctx, GL_INVALID_ENUM,
2329 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
2330 name, pname);
2331 break;
2332 }
2333 }
2334
2335
2336 static void
2337 get_texture_object_parameteriv(struct gl_context *ctx, GLuint name,
2338 GLenum pname, GLint *params)
2339 {
2340 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
2341 if (!texObj) {
2342 _mesa_error(ctx, GL_INVALID_VALUE,
2343 "glObjectUnpurgeable(name = 0x%x)", name);
2344 return;
2345 }
2346
2347 switch (pname) {
2348 case GL_PURGEABLE_APPLE:
2349 *params = texObj->Purgeable;
2350 break;
2351 default:
2352 _mesa_error(ctx, GL_INVALID_ENUM,
2353 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
2354 name, pname);
2355 break;
2356 }
2357 }
2358
2359
2360 void GLAPIENTRY
2361 _mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname,
2362 GLint *params)
2363 {
2364 GET_CURRENT_CONTEXT(ctx);
2365
2366 if (name == 0) {
2367 _mesa_error(ctx, GL_INVALID_VALUE,
2368 "glGetObjectParameteriv(name = 0x%x)", name);
2369 return;
2370 }
2371
2372 switch (objectType) {
2373 case GL_TEXTURE:
2374 get_texture_object_parameteriv(ctx, name, pname, params);
2375 break;
2376 case GL_BUFFER_OBJECT_APPLE:
2377 get_buffer_object_parameteriv(ctx, name, pname, params);
2378 break;
2379 case GL_RENDERBUFFER_EXT:
2380 get_renderbuffer_parameteriv(ctx, name, pname, params);
2381 break;
2382 default:
2383 _mesa_error(ctx, GL_INVALID_ENUM,
2384 "glGetObjectParameteriv(name = 0x%x) invalid type: %d",
2385 name, objectType);
2386 }
2387 }
2388
2389 static void
2390 set_ubo_binding(struct gl_context *ctx,
2391 int index,
2392 struct gl_buffer_object *bufObj,
2393 GLintptr offset,
2394 GLsizeiptr size,
2395 GLboolean autoSize)
2396 {
2397 struct gl_uniform_buffer_binding *binding;
2398
2399 binding = &ctx->UniformBufferBindings[index];
2400 if (binding->BufferObject == bufObj &&
2401 binding->Offset == offset &&
2402 binding->Size == size &&
2403 binding->AutomaticSize == autoSize) {
2404 return;
2405 }
2406
2407 FLUSH_VERTICES(ctx, 0);
2408 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
2409
2410 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
2411 binding->Offset = offset;
2412 binding->Size = size;
2413 binding->AutomaticSize = autoSize;
2414 }
2415
2416 /**
2417 * Bind a region of a buffer object to a uniform block binding point.
2418 * \param index the uniform buffer binding point index
2419 * \param bufObj the buffer object
2420 * \param offset offset to the start of buffer object region
2421 * \param size size of the buffer object region
2422 */
2423 static void
2424 bind_buffer_range_uniform_buffer(struct gl_context *ctx,
2425 GLuint index,
2426 struct gl_buffer_object *bufObj,
2427 GLintptr offset,
2428 GLsizeiptr size)
2429 {
2430 if (index >= ctx->Const.MaxUniformBufferBindings) {
2431 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
2432 return;
2433 }
2434
2435 if (offset & (ctx->Const.UniformBufferOffsetAlignment - 1)) {
2436 _mesa_error(ctx, GL_INVALID_VALUE,
2437 "glBindBufferRange(offset misalgned %d/%d)", (int) offset,
2438 ctx->Const.UniformBufferOffsetAlignment);
2439 return;
2440 }
2441
2442 if (bufObj == ctx->Shared->NullBufferObj) {
2443 offset = -1;
2444 size = -1;
2445 }
2446
2447 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
2448 set_ubo_binding(ctx, index, bufObj, offset, size, GL_FALSE);
2449 }
2450
2451
2452 /**
2453 * Bind a buffer object to a uniform block binding point.
2454 * As above, but offset = 0.
2455 */
2456 static void
2457 bind_buffer_base_uniform_buffer(struct gl_context *ctx,
2458 GLuint index,
2459 struct gl_buffer_object *bufObj)
2460 {
2461 if (index >= ctx->Const.MaxUniformBufferBindings) {
2462 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
2463 return;
2464 }
2465
2466 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
2467 if (bufObj == ctx->Shared->NullBufferObj)
2468 set_ubo_binding(ctx, index, bufObj, -1, -1, GL_TRUE);
2469 else
2470 set_ubo_binding(ctx, index, bufObj, 0, 0, GL_TRUE);
2471 }
2472
2473 static void
2474 set_atomic_buffer_binding(struct gl_context *ctx,
2475 unsigned index,
2476 struct gl_buffer_object *bufObj,
2477 GLintptr offset,
2478 GLsizeiptr size,
2479 const char *name)
2480 {
2481 struct gl_atomic_buffer_binding *binding;
2482
2483 if (index >= ctx->Const.MaxAtomicBufferBindings) {
2484 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index);
2485 return;
2486 }
2487
2488 if (offset & (ATOMIC_COUNTER_SIZE - 1)) {
2489 _mesa_error(ctx, GL_INVALID_VALUE,
2490 "%s(offset misalgned %d/%d)", name, (int) offset,
2491 ATOMIC_COUNTER_SIZE);
2492 return;
2493 }
2494
2495 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
2496
2497 binding = &ctx->AtomicBufferBindings[index];
2498 if (binding->BufferObject == bufObj &&
2499 binding->Offset == offset &&
2500 binding->Size == size) {
2501 return;
2502 }
2503
2504 FLUSH_VERTICES(ctx, 0);
2505 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
2506
2507 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
2508
2509 if (bufObj == ctx->Shared->NullBufferObj) {
2510 binding->Offset = -1;
2511 binding->Size = -1;
2512 } else {
2513 binding->Offset = offset;
2514 binding->Size = size;
2515 }
2516 }
2517
2518 void GLAPIENTRY
2519 _mesa_BindBufferRange(GLenum target, GLuint index,
2520 GLuint buffer, GLintptr offset, GLsizeiptr size)
2521 {
2522 GET_CURRENT_CONTEXT(ctx);
2523 struct gl_buffer_object *bufObj;
2524
2525 if (buffer == 0) {
2526 bufObj = ctx->Shared->NullBufferObj;
2527 } else {
2528 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2529 }
2530 if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer,
2531 &bufObj, "glBindBufferRange"))
2532 return;
2533
2534 if (!bufObj) {
2535 _mesa_error(ctx, GL_INVALID_OPERATION,
2536 "glBindBufferRange(invalid buffer=%u)", buffer);
2537 return;
2538 }
2539
2540 if (buffer != 0) {
2541 if (size <= 0) {
2542 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)",
2543 (int) size);
2544 return;
2545 }
2546 }
2547
2548 switch (target) {
2549 case GL_TRANSFORM_FEEDBACK_BUFFER:
2550 _mesa_bind_buffer_range_transform_feedback(ctx, index, bufObj,
2551 offset, size);
2552 return;
2553 case GL_UNIFORM_BUFFER:
2554 bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
2555 return;
2556 case GL_ATOMIC_COUNTER_BUFFER:
2557 set_atomic_buffer_binding(ctx, index, bufObj, offset, size,
2558 "glBindBufferRange");
2559 return;
2560 default:
2561 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
2562 return;
2563 }
2564 }
2565
2566 void GLAPIENTRY
2567 _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
2568 {
2569 GET_CURRENT_CONTEXT(ctx);
2570 struct gl_buffer_object *bufObj;
2571
2572 if (buffer == 0) {
2573 bufObj = ctx->Shared->NullBufferObj;
2574 } else {
2575 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2576 }
2577 if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer,
2578 &bufObj, "glBindBufferBase"))
2579 return;
2580
2581 if (!bufObj) {
2582 _mesa_error(ctx, GL_INVALID_OPERATION,
2583 "glBindBufferBase(invalid buffer=%u)", buffer);
2584 return;
2585 }
2586
2587 /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with
2588 * regards to BindBufferBase. It says (GL 3.1 core spec, page 63):
2589 *
2590 * "BindBufferBase is equivalent to calling BindBufferRange with offset
2591 * zero and size equal to the size of buffer."
2592 *
2593 * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230):
2594 *
2595 * "If the parameter (starting offset or size) was not specified when the
2596 * buffer object was bound, zero is returned."
2597 *
2598 * What happens if the size of the buffer changes? Does the size of the
2599 * buffer at the moment glBindBufferBase was called still play a role, like
2600 * the first quote would imply, or is the size meaningless in the
2601 * glBindBufferBase case like the second quote would suggest? The GL 4.1
2602 * core spec page 45 says:
2603 *
2604 * "It is equivalent to calling BindBufferRange with offset zero, while
2605 * size is determined by the size of the bound buffer at the time the
2606 * binding is used."
2607 *
2608 * My interpretation is that the GL 4.1 spec was a clarification of the
2609 * behavior, not a change. In particular, this choice will only make
2610 * rendering work in cases where it would have had undefined results.
2611 */
2612
2613 switch (target) {
2614 case GL_TRANSFORM_FEEDBACK_BUFFER:
2615 _mesa_bind_buffer_base_transform_feedback(ctx, index, bufObj);
2616 return;
2617 case GL_UNIFORM_BUFFER:
2618 bind_buffer_base_uniform_buffer(ctx, index, bufObj);
2619 return;
2620 case GL_ATOMIC_COUNTER_BUFFER:
2621 set_atomic_buffer_binding(ctx, index, bufObj, 0, 0,
2622 "glBindBufferBase");
2623 return;
2624 default:
2625 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
2626 return;
2627 }
2628 }
2629
2630 void GLAPIENTRY
2631 _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset,
2632 GLsizeiptr length)
2633 {
2634 GET_CURRENT_CONTEXT(ctx);
2635 struct gl_buffer_object *bufObj;
2636 const GLintptr end = offset + length;
2637
2638 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2639 if (!bufObj) {
2640 _mesa_error(ctx, GL_INVALID_VALUE,
2641 "glInvalidateBufferSubData(name = 0x%x) invalid object",
2642 buffer);
2643 return;
2644 }
2645
2646 /* The GL_ARB_invalidate_subdata spec says:
2647 *
2648 * "An INVALID_VALUE error is generated if <offset> or <length> is
2649 * negative, or if <offset> + <length> is greater than the value of
2650 * BUFFER_SIZE."
2651 */
2652 if (end < 0 || end > bufObj->Size) {
2653 _mesa_error(ctx, GL_INVALID_VALUE,
2654 "glInvalidateBufferSubData(invalid offset or length)");
2655 return;
2656 }
2657
2658 /* The GL_ARB_invalidate_subdata spec says:
2659 *
2660 * "An INVALID_OPERATION error is generated if the buffer is currently
2661 * mapped by MapBuffer, or if the invalidate range intersects the range
2662 * currently mapped by MapBufferRange."
2663 */
2664 if (bufferobj_range_mapped(bufObj, offset, length)) {
2665 _mesa_error(ctx, GL_INVALID_OPERATION,
2666 "glInvalidateBufferSubData(intersection with mapped "
2667 "range)");
2668 return;
2669 }
2670
2671 /* We don't actually do anything for this yet. Just return after
2672 * validating the parameters and generating the required errors.
2673 */
2674 return;
2675 }
2676
2677 void GLAPIENTRY
2678 _mesa_InvalidateBufferData(GLuint buffer)
2679 {
2680 GET_CURRENT_CONTEXT(ctx);
2681 struct gl_buffer_object *bufObj;
2682
2683 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2684 if (!bufObj) {
2685 _mesa_error(ctx, GL_INVALID_VALUE,
2686 "glInvalidateBufferData(name = 0x%x) invalid object",
2687 buffer);
2688 return;
2689 }
2690
2691 /* The GL_ARB_invalidate_subdata spec says:
2692 *
2693 * "An INVALID_OPERATION error is generated if the buffer is currently
2694 * mapped by MapBuffer, or if the invalidate range intersects the range
2695 * currently mapped by MapBufferRange."
2696 */
2697 if (_mesa_bufferobj_mapped(bufObj)) {
2698 _mesa_error(ctx, GL_INVALID_OPERATION,
2699 "glInvalidateBufferData(intersection with mapped "
2700 "range)");
2701 return;
2702 }
2703
2704 /* We don't actually do anything for this yet. Just return after
2705 * validating the parameters and generating the required errors.
2706 */
2707 return;
2708 }