vbo: cache/memoize the result of vbo_get_minmax_indices (v3)
[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 <inttypes.h> /* for PRId64 macro */
35 #include "glheader.h"
36 #include "enums.h"
37 #include "hash.h"
38 #include "imports.h"
39 #include "context.h"
40 #include "bufferobj.h"
41 #include "mtypes.h"
42 #include "teximage.h"
43 #include "glformats.h"
44 #include "texstore.h"
45 #include "transformfeedback.h"
46
47
48 /* Debug flags */
49 /*#define VBO_DEBUG*/
50 /*#define BOUNDS_CHECK*/
51
52
53 /**
54 * We count the number of buffer modification calls to check for
55 * inefficient buffer use. This is the number of such calls before we
56 * issue a warning.
57 */
58 #define BUFFER_WARNING_CALL_COUNT 4
59
60
61 /**
62 * Helper to warn of possible performance issues, such as frequently
63 * updating a buffer created with GL_STATIC_DRAW. Called via the macro
64 * below.
65 */
66 static void
67 buffer_usage_warning(struct gl_context *ctx, GLuint *id, const char *fmt, ...)
68 {
69 va_list args;
70
71 va_start(args, fmt);
72 _mesa_gl_vdebug(ctx, id,
73 MESA_DEBUG_SOURCE_API,
74 MESA_DEBUG_TYPE_PERFORMANCE,
75 MESA_DEBUG_SEVERITY_MEDIUM,
76 fmt, args);
77 va_end(args);
78 }
79
80 #define BUFFER_USAGE_WARNING(CTX, FMT, ...) \
81 do { \
82 static GLuint id = 0; \
83 buffer_usage_warning(CTX, &id, FMT, ##__VA_ARGS__); \
84 } while (0)
85
86
87 /**
88 * Used as a placeholder for buffer objects between glGenBuffers() and
89 * glBindBuffer() so that glIsBuffer() can work correctly.
90 */
91 static struct gl_buffer_object DummyBufferObject;
92
93
94 /**
95 * Return pointer to address of a buffer object target.
96 * \param ctx the GL context
97 * \param target the buffer object target to be retrieved.
98 * \return pointer to pointer to the buffer object bound to \c target in the
99 * specified context or \c NULL if \c target is invalid.
100 */
101 static inline struct gl_buffer_object **
102 get_buffer_target(struct gl_context *ctx, GLenum target)
103 {
104 /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0.
105 */
106 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)
107 && target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER)
108 return NULL;
109
110 switch (target) {
111 case GL_ARRAY_BUFFER_ARB:
112 return &ctx->Array.ArrayBufferObj;
113 case GL_ELEMENT_ARRAY_BUFFER_ARB:
114 return &ctx->Array.VAO->IndexBufferObj;
115 case GL_PIXEL_PACK_BUFFER_EXT:
116 return &ctx->Pack.BufferObj;
117 case GL_PIXEL_UNPACK_BUFFER_EXT:
118 return &ctx->Unpack.BufferObj;
119 case GL_COPY_READ_BUFFER:
120 return &ctx->CopyReadBuffer;
121 case GL_COPY_WRITE_BUFFER:
122 return &ctx->CopyWriteBuffer;
123 case GL_DRAW_INDIRECT_BUFFER:
124 if ((ctx->API == API_OPENGL_CORE &&
125 ctx->Extensions.ARB_draw_indirect) ||
126 _mesa_is_gles31(ctx)) {
127 return &ctx->DrawIndirectBuffer;
128 }
129 break;
130 case GL_PARAMETER_BUFFER_ARB:
131 if (_mesa_has_ARB_indirect_parameters(ctx)) {
132 return &ctx->ParameterBuffer;
133 }
134 break;
135 case GL_DISPATCH_INDIRECT_BUFFER:
136 if (_mesa_has_compute_shaders(ctx)) {
137 return &ctx->DispatchIndirectBuffer;
138 }
139 break;
140 case GL_TRANSFORM_FEEDBACK_BUFFER:
141 if (ctx->Extensions.EXT_transform_feedback) {
142 return &ctx->TransformFeedback.CurrentBuffer;
143 }
144 break;
145 case GL_TEXTURE_BUFFER:
146 if (ctx->API == API_OPENGL_CORE &&
147 ctx->Extensions.ARB_texture_buffer_object) {
148 return &ctx->Texture.BufferObject;
149 }
150 break;
151 case GL_UNIFORM_BUFFER:
152 if (ctx->Extensions.ARB_uniform_buffer_object) {
153 return &ctx->UniformBuffer;
154 }
155 break;
156 case GL_SHADER_STORAGE_BUFFER:
157 if (ctx->Extensions.ARB_shader_storage_buffer_object) {
158 return &ctx->ShaderStorageBuffer;
159 }
160 break;
161 case GL_ATOMIC_COUNTER_BUFFER:
162 if (ctx->Extensions.ARB_shader_atomic_counters) {
163 return &ctx->AtomicBuffer;
164 }
165 break;
166 case GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD:
167 if (ctx->Extensions.AMD_pinned_memory) {
168 return &ctx->ExternalVirtualMemoryBuffer;
169 }
170 break;
171 default:
172 return NULL;
173 }
174 return NULL;
175 }
176
177
178 /**
179 * Get the buffer object bound to the specified target in a GL context.
180 * \param ctx the GL context
181 * \param target the buffer object target to be retrieved.
182 * \param error the GL error to record if target is illegal.
183 * \return pointer to the buffer object bound to \c target in the
184 * specified context or \c NULL if \c target is invalid.
185 */
186 static inline struct gl_buffer_object *
187 get_buffer(struct gl_context *ctx, const char *func, GLenum target,
188 GLenum error)
189 {
190 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
191
192 if (!bufObj) {
193 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
194 return NULL;
195 }
196
197 if (!_mesa_is_bufferobj(*bufObj)) {
198 _mesa_error(ctx, error, "%s(no buffer bound)", func);
199 return NULL;
200 }
201
202 return *bufObj;
203 }
204
205
206 /**
207 * Convert a GLbitfield describing the mapped buffer access flags
208 * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
209 */
210 static GLenum
211 simplified_access_mode(struct gl_context *ctx, GLbitfield access)
212 {
213 const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
214 if ((access & rwFlags) == rwFlags)
215 return GL_READ_WRITE;
216 if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
217 return GL_READ_ONLY;
218 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
219 return GL_WRITE_ONLY;
220
221 /* Otherwise, AccessFlags is zero (the default state).
222 *
223 * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says:
224 *
225 * Name Type Initial Value Legal Values
226 * ... ... ... ...
227 * BUFFER_ACCESS enum READ_WRITE READ_ONLY, WRITE_ONLY
228 * READ_WRITE
229 *
230 * However, table 6.8 in the GL_OES_mapbuffer extension says:
231 *
232 * Get Value Type Get Command Value Description
233 * --------- ---- ----------- ----- -----------
234 * BUFFER_ACCESS_OES Z1 GetBufferParameteriv WRITE_ONLY_OES buffer map flag
235 *
236 * The difference is because GL_OES_mapbuffer only supports mapping buffers
237 * write-only.
238 */
239 assert(access == 0);
240
241 return _mesa_is_gles(ctx) ? GL_WRITE_ONLY : GL_READ_WRITE;
242 }
243
244
245 /**
246 * Test if the buffer is mapped, and if so, if the mapped range overlaps the
247 * given range.
248 * The regions do not overlap if and only if the end of the given
249 * region is before the mapped region or the start of the given region
250 * is after the mapped region.
251 *
252 * \param obj Buffer object target on which to operate.
253 * \param offset Offset of the first byte of the subdata range.
254 * \param size Size, in bytes, of the subdata range.
255 * \return true if ranges overlap, false otherwise
256 *
257 */
258 static bool
259 bufferobj_range_mapped(const struct gl_buffer_object *obj,
260 GLintptr offset, GLsizeiptr size)
261 {
262 if (_mesa_bufferobj_mapped(obj, MAP_USER)) {
263 const GLintptr end = offset + size;
264 const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset +
265 obj->Mappings[MAP_USER].Length;
266
267 if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) {
268 return true;
269 }
270 }
271 return false;
272 }
273
274
275 /**
276 * Tests the subdata range parameters and sets the GL error code for
277 * \c glBufferSubDataARB, \c glGetBufferSubDataARB and
278 * \c glClearBufferSubData.
279 *
280 * \param ctx GL context.
281 * \param bufObj The buffer object.
282 * \param offset Offset of the first byte of the subdata range.
283 * \param size Size, in bytes, of the subdata range.
284 * \param mappedRange If true, checks if an overlapping range is mapped.
285 * If false, checks if buffer is mapped.
286 * \param caller Name of calling function for recording errors.
287 * \return false if error, true otherwise
288 *
289 * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData
290 */
291 static bool
292 buffer_object_subdata_range_good(struct gl_context *ctx,
293 const struct gl_buffer_object *bufObj,
294 GLintptr offset, GLsizeiptr size,
295 bool mappedRange, const char *caller)
296 {
297 if (size < 0) {
298 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
299 return false;
300 }
301
302 if (offset < 0) {
303 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
304 return false;
305 }
306
307 if (offset + size > bufObj->Size) {
308 _mesa_error(ctx, GL_INVALID_VALUE,
309 "%s(offset %lu + size %lu > buffer size %lu)", caller,
310 (unsigned long) offset,
311 (unsigned long) size,
312 (unsigned long) bufObj->Size);
313 return false;
314 }
315
316 if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT)
317 return true;
318
319 if (mappedRange) {
320 if (bufferobj_range_mapped(bufObj, offset, size)) {
321 _mesa_error(ctx, GL_INVALID_OPERATION,
322 "%s(range is mapped without persistent bit)",
323 caller);
324 return false;
325 }
326 }
327 else {
328 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
329 _mesa_error(ctx, GL_INVALID_OPERATION,
330 "%s(buffer is mapped without persistent bit)",
331 caller);
332 return false;
333 }
334 }
335
336 return true;
337 }
338
339
340 /**
341 * Test the format and type parameters and set the GL error code for
342 * \c glClearBufferData and \c glClearBufferSubData.
343 *
344 * \param ctx GL context.
345 * \param internalformat Format to which the data is to be converted.
346 * \param format Format of the supplied data.
347 * \param type Type of the supplied data.
348 * \param caller Name of calling function for recording errors.
349 * \return If internalformat, format and type are legal the mesa_format
350 * corresponding to internalformat, otherwise MESA_FORMAT_NONE.
351 *
352 * \sa glClearBufferData and glClearBufferSubData
353 */
354 static mesa_format
355 validate_clear_buffer_format(struct gl_context *ctx,
356 GLenum internalformat,
357 GLenum format, GLenum type,
358 const char *caller)
359 {
360 mesa_format mesaFormat;
361 GLenum errorFormatType;
362
363 mesaFormat = _mesa_validate_texbuffer_format(ctx, internalformat);
364 if (mesaFormat == MESA_FORMAT_NONE) {
365 _mesa_error(ctx, GL_INVALID_ENUM,
366 "%s(invalid internalformat)", caller);
367 return MESA_FORMAT_NONE;
368 }
369
370 /* NOTE: not mentioned in ARB_clear_buffer_object but according to
371 * EXT_texture_integer there is no conversion between integer and
372 * non-integer formats
373 */
374 if (_mesa_is_enum_format_signed_int(format) !=
375 _mesa_is_format_integer_color(mesaFormat)) {
376 _mesa_error(ctx, GL_INVALID_OPERATION,
377 "%s(integer vs non-integer)", caller);
378 return MESA_FORMAT_NONE;
379 }
380
381 if (!_mesa_is_color_format(format)) {
382 _mesa_error(ctx, GL_INVALID_ENUM,
383 "%s(format is not a color format)", caller);
384 return MESA_FORMAT_NONE;
385 }
386
387 errorFormatType = _mesa_error_check_format_and_type(ctx, format, type);
388 if (errorFormatType != GL_NO_ERROR) {
389 _mesa_error(ctx, GL_INVALID_ENUM,
390 "%s(invalid format or type)", caller);
391 return MESA_FORMAT_NONE;
392 }
393
394 return mesaFormat;
395 }
396
397
398 /**
399 * Convert user-specified clear value to the specified internal format.
400 *
401 * \param ctx GL context.
402 * \param internalformat Format to which the data is converted.
403 * \param clearValue Points to the converted clear value.
404 * \param format Format of the supplied data.
405 * \param type Type of the supplied data.
406 * \param data Data which is to be converted to internalformat.
407 * \param caller Name of calling function for recording errors.
408 * \return true if data could be converted, false otherwise.
409 *
410 * \sa glClearBufferData, glClearBufferSubData
411 */
412 static bool
413 convert_clear_buffer_data(struct gl_context *ctx,
414 mesa_format internalformat,
415 GLubyte *clearValue, GLenum format, GLenum type,
416 const GLvoid *data, const char *caller)
417 {
418 GLenum internalformatBase = _mesa_get_format_base_format(internalformat);
419
420 if (_mesa_texstore(ctx, 1, internalformatBase, internalformat,
421 0, &clearValue, 1, 1, 1,
422 format, type, data, &ctx->Unpack)) {
423 return true;
424 }
425 else {
426 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
427 return false;
428 }
429 }
430
431
432 /**
433 * Allocate and initialize a new buffer object.
434 *
435 * Default callback for the \c dd_function_table::NewBufferObject() hook.
436 */
437 static struct gl_buffer_object *
438 _mesa_new_buffer_object(struct gl_context *ctx, GLuint name)
439 {
440 struct gl_buffer_object *obj;
441
442 (void) ctx;
443
444 obj = MALLOC_STRUCT(gl_buffer_object);
445 _mesa_initialize_buffer_object(ctx, obj, name);
446 return obj;
447 }
448
449
450 /**
451 * Delete a buffer object.
452 *
453 * Default callback for the \c dd_function_table::DeleteBuffer() hook.
454 */
455 void
456 _mesa_delete_buffer_object(struct gl_context *ctx,
457 struct gl_buffer_object *bufObj)
458 {
459 (void) ctx;
460
461 vbo_delete_minmax_cache(bufObj);
462 _mesa_align_free(bufObj->Data);
463
464 /* assign strange values here to help w/ debugging */
465 bufObj->RefCount = -1000;
466 bufObj->Name = ~0;
467
468 mtx_destroy(&bufObj->Mutex);
469 free(bufObj->Label);
470 free(bufObj);
471 }
472
473
474
475 /**
476 * Set ptr to bufObj w/ reference counting.
477 * This is normally only called from the _mesa_reference_buffer_object() macro
478 * when there's a real pointer change.
479 */
480 void
481 _mesa_reference_buffer_object_(struct gl_context *ctx,
482 struct gl_buffer_object **ptr,
483 struct gl_buffer_object *bufObj)
484 {
485 if (*ptr) {
486 /* Unreference the old buffer */
487 GLboolean deleteFlag = GL_FALSE;
488 struct gl_buffer_object *oldObj = *ptr;
489
490 mtx_lock(&oldObj->Mutex);
491 assert(oldObj->RefCount > 0);
492 oldObj->RefCount--;
493 deleteFlag = (oldObj->RefCount == 0);
494 mtx_unlock(&oldObj->Mutex);
495
496 if (deleteFlag) {
497 assert(ctx->Driver.DeleteBuffer);
498 ctx->Driver.DeleteBuffer(ctx, oldObj);
499 }
500
501 *ptr = NULL;
502 }
503 assert(!*ptr);
504
505 if (bufObj) {
506 /* reference new buffer */
507 mtx_lock(&bufObj->Mutex);
508 if (bufObj->RefCount == 0) {
509 /* this buffer's being deleted (look just above) */
510 /* Not sure this can every really happen. Warn if it does. */
511 _mesa_problem(NULL, "referencing deleted buffer object");
512 *ptr = NULL;
513 }
514 else {
515 bufObj->RefCount++;
516 *ptr = bufObj;
517 }
518 mtx_unlock(&bufObj->Mutex);
519 }
520 }
521
522
523 /**
524 * Initialize a buffer object to default values.
525 */
526 void
527 _mesa_initialize_buffer_object(struct gl_context *ctx,
528 struct gl_buffer_object *obj,
529 GLuint name)
530 {
531 memset(obj, 0, sizeof(struct gl_buffer_object));
532 mtx_init(&obj->Mutex, mtx_plain);
533 obj->RefCount = 1;
534 obj->Name = name;
535 obj->Usage = GL_STATIC_DRAW_ARB;
536 }
537
538
539
540 /**
541 * Callback called from _mesa_HashWalk()
542 */
543 static void
544 count_buffer_size(GLuint key, void *data, void *userData)
545 {
546 const struct gl_buffer_object *bufObj =
547 (const struct gl_buffer_object *) data;
548 GLuint *total = (GLuint *) userData;
549
550 (void) key;
551 *total = *total + bufObj->Size;
552 }
553
554
555 /**
556 * Compute total size (in bytes) of all buffer objects for the given context.
557 * For debugging purposes.
558 */
559 GLuint
560 _mesa_total_buffer_object_memory(struct gl_context *ctx)
561 {
562 GLuint total = 0;
563
564 _mesa_HashWalk(ctx->Shared->BufferObjects, count_buffer_size, &total);
565
566 return total;
567 }
568
569
570 /**
571 * Allocate space for and store data in a buffer object. Any data that was
572 * previously stored in the buffer object is lost. If \c data is \c NULL,
573 * memory will be allocated, but no copy will occur.
574 *
575 * This is the default callback for \c dd_function_table::BufferData()
576 * Note that all GL error checking will have been done already.
577 *
578 * \param ctx GL context.
579 * \param target Buffer object target on which to operate.
580 * \param size Size, in bytes, of the new data store.
581 * \param data Pointer to the data to store in the buffer object. This
582 * pointer may be \c NULL.
583 * \param usage Hints about how the data will be used.
584 * \param bufObj Object to be used.
585 *
586 * \return GL_TRUE for success, GL_FALSE for failure
587 * \sa glBufferDataARB, dd_function_table::BufferData.
588 */
589 static GLboolean
590 buffer_data_fallback(struct gl_context *ctx, GLenum target, GLsizeiptr size,
591 const GLvoid *data, GLenum usage, GLenum storageFlags,
592 struct gl_buffer_object *bufObj)
593 {
594 void * new_data;
595
596 (void) target;
597
598 _mesa_align_free( bufObj->Data );
599
600 new_data = _mesa_align_malloc( size, ctx->Const.MinMapBufferAlignment );
601 if (new_data) {
602 bufObj->Data = (GLubyte *) new_data;
603 bufObj->Size = size;
604 bufObj->Usage = usage;
605 bufObj->StorageFlags = storageFlags;
606
607 if (data) {
608 memcpy( bufObj->Data, data, size );
609 }
610
611 return GL_TRUE;
612 }
613 else {
614 return GL_FALSE;
615 }
616 }
617
618
619 /**
620 * Replace data in a subrange of buffer object. If the data range
621 * specified by \c size + \c offset extends beyond the end of the buffer or
622 * if \c data is \c NULL, no copy is performed.
623 *
624 * This is the default callback for \c dd_function_table::BufferSubData()
625 * Note that all GL error checking will have been done already.
626 *
627 * \param ctx GL context.
628 * \param offset Offset of the first byte to be modified.
629 * \param size Size, in bytes, of the data range.
630 * \param data Pointer to the data to store in the buffer object.
631 * \param bufObj Object to be used.
632 *
633 * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
634 */
635 static void
636 buffer_sub_data_fallback(struct gl_context *ctx, GLintptr offset,
637 GLsizeiptr size, const GLvoid *data,
638 struct gl_buffer_object *bufObj)
639 {
640 (void) ctx;
641
642 /* this should have been caught in _mesa_BufferSubData() */
643 assert(size + offset <= bufObj->Size);
644
645 if (bufObj->Data) {
646 memcpy( (GLubyte *) bufObj->Data + offset, data, size );
647 }
648 }
649
650
651 /**
652 * Retrieve data from a subrange of buffer object. If the data range
653 * specified by \c size + \c offset extends beyond the end of the buffer or
654 * if \c data is \c NULL, no copy is performed.
655 *
656 * This is the default callback for \c dd_function_table::GetBufferSubData()
657 * Note that all GL error checking will have been done already.
658 *
659 * \param ctx GL context.
660 * \param target Buffer object target on which to operate.
661 * \param offset Offset of the first byte to be fetched.
662 * \param size Size, in bytes, of the data range.
663 * \param data Destination for data
664 * \param bufObj Object to be used.
665 *
666 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
667 */
668 static void
669 _mesa_buffer_get_subdata( struct gl_context *ctx, GLintptrARB offset,
670 GLsizeiptrARB size, GLvoid * data,
671 struct gl_buffer_object * bufObj )
672 {
673 (void) ctx;
674
675 if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) {
676 memcpy( data, (GLubyte *) bufObj->Data + offset, size );
677 }
678 }
679
680
681 /**
682 * Clear a subrange of the buffer object with copies of the supplied data.
683 * If data is NULL the buffer is filled with zeros.
684 *
685 * This is the default callback for \c dd_function_table::ClearBufferSubData()
686 * Note that all GL error checking will have been done already.
687 *
688 * \param ctx GL context.
689 * \param offset Offset of the first byte to be cleared.
690 * \param size Size, in bytes, of the to be cleared range.
691 * \param clearValue Source of the data.
692 * \param clearValueSize Size, in bytes, of the supplied data.
693 * \param bufObj Object to be cleared.
694 *
695 * \sa glClearBufferSubData, glClearBufferData and
696 * dd_function_table::ClearBufferSubData.
697 */
698 void
699 _mesa_ClearBufferSubData_sw(struct gl_context *ctx,
700 GLintptr offset, GLsizeiptr size,
701 const GLvoid *clearValue,
702 GLsizeiptr clearValueSize,
703 struct gl_buffer_object *bufObj)
704 {
705 GLsizeiptr i;
706 GLubyte *dest;
707
708 assert(ctx->Driver.MapBufferRange);
709 dest = ctx->Driver.MapBufferRange(ctx, offset, size,
710 GL_MAP_WRITE_BIT |
711 GL_MAP_INVALIDATE_RANGE_BIT,
712 bufObj, MAP_INTERNAL);
713
714 if (!dest) {
715 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data");
716 return;
717 }
718
719 if (clearValue == NULL) {
720 /* Clear with zeros, per the spec */
721 memset(dest, 0, size);
722 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL);
723 return;
724 }
725
726 for (i = 0; i < size/clearValueSize; ++i) {
727 memcpy(dest, clearValue, clearValueSize);
728 dest += clearValueSize;
729 }
730
731 ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL);
732 }
733
734
735 /**
736 * Default fallback for \c dd_function_table::MapBufferRange().
737 * Called via glMapBufferRange().
738 */
739 static void *
740 map_buffer_range_fallback(struct gl_context *ctx, GLintptr offset,
741 GLsizeiptr length, GLbitfield access,
742 struct gl_buffer_object *bufObj,
743 gl_map_buffer_index index)
744 {
745 (void) ctx;
746 assert(!_mesa_bufferobj_mapped(bufObj, index));
747 /* Just return a direct pointer to the data */
748 bufObj->Mappings[index].Pointer = bufObj->Data + offset;
749 bufObj->Mappings[index].Length = length;
750 bufObj->Mappings[index].Offset = offset;
751 bufObj->Mappings[index].AccessFlags = access;
752 return bufObj->Mappings[index].Pointer;
753 }
754
755
756 /**
757 * Default fallback for \c dd_function_table::FlushMappedBufferRange().
758 * Called via glFlushMappedBufferRange().
759 */
760 static void
761 flush_mapped_buffer_range_fallback(struct gl_context *ctx,
762 GLintptr offset, GLsizeiptr length,
763 struct gl_buffer_object *obj,
764 gl_map_buffer_index index)
765 {
766 (void) ctx;
767 (void) offset;
768 (void) length;
769 (void) obj;
770 (void) index;
771 /* no-op */
772 }
773
774
775 /**
776 * Default callback for \c dd_function_table::UnmapBuffer().
777 *
778 * The input parameters will have been already tested for errors.
779 *
780 * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
781 */
782 static GLboolean
783 unmap_buffer_fallback(struct gl_context *ctx, struct gl_buffer_object *bufObj,
784 gl_map_buffer_index index)
785 {
786 (void) ctx;
787 /* XXX we might assert here that bufObj->Pointer is non-null */
788 bufObj->Mappings[index].Pointer = NULL;
789 bufObj->Mappings[index].Length = 0;
790 bufObj->Mappings[index].Offset = 0;
791 bufObj->Mappings[index].AccessFlags = 0x0;
792 return GL_TRUE;
793 }
794
795
796 /**
797 * Default fallback for \c dd_function_table::CopyBufferSubData().
798 * Called via glCopyBufferSubData().
799 */
800 static void
801 copy_buffer_sub_data_fallback(struct gl_context *ctx,
802 struct gl_buffer_object *src,
803 struct gl_buffer_object *dst,
804 GLintptr readOffset, GLintptr writeOffset,
805 GLsizeiptr size)
806 {
807 GLubyte *srcPtr, *dstPtr;
808
809 if (src == dst) {
810 srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size,
811 GL_MAP_READ_BIT |
812 GL_MAP_WRITE_BIT, src,
813 MAP_INTERNAL);
814
815 if (!srcPtr)
816 return;
817
818 srcPtr += readOffset;
819 dstPtr += writeOffset;
820 } else {
821 srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size,
822 GL_MAP_READ_BIT, src,
823 MAP_INTERNAL);
824 dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size,
825 (GL_MAP_WRITE_BIT |
826 GL_MAP_INVALIDATE_RANGE_BIT), dst,
827 MAP_INTERNAL);
828 }
829
830 /* Note: the src and dst regions will never overlap. Trying to do so
831 * would generate GL_INVALID_VALUE earlier.
832 */
833 if (srcPtr && dstPtr)
834 memcpy(dstPtr, srcPtr, size);
835
836 ctx->Driver.UnmapBuffer(ctx, src, MAP_INTERNAL);
837 if (dst != src)
838 ctx->Driver.UnmapBuffer(ctx, dst, MAP_INTERNAL);
839 }
840
841
842
843 /**
844 * Initialize the state associated with buffer objects
845 */
846 void
847 _mesa_init_buffer_objects( struct gl_context *ctx )
848 {
849 GLuint i;
850
851 memset(&DummyBufferObject, 0, sizeof(DummyBufferObject));
852 mtx_init(&DummyBufferObject.Mutex, mtx_plain);
853 DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */
854
855 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj,
856 ctx->Shared->NullBufferObj);
857
858 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer,
859 ctx->Shared->NullBufferObj);
860 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer,
861 ctx->Shared->NullBufferObj);
862
863 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer,
864 ctx->Shared->NullBufferObj);
865
866 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer,
867 ctx->Shared->NullBufferObj);
868
869 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer,
870 ctx->Shared->NullBufferObj);
871
872 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer,
873 ctx->Shared->NullBufferObj);
874
875 _mesa_reference_buffer_object(ctx, &ctx->ParameterBuffer,
876 ctx->Shared->NullBufferObj);
877
878 _mesa_reference_buffer_object(ctx, &ctx->DispatchIndirectBuffer,
879 ctx->Shared->NullBufferObj);
880
881 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
882 _mesa_reference_buffer_object(ctx,
883 &ctx->UniformBufferBindings[i].BufferObject,
884 ctx->Shared->NullBufferObj);
885 ctx->UniformBufferBindings[i].Offset = -1;
886 ctx->UniformBufferBindings[i].Size = -1;
887 }
888
889 for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) {
890 _mesa_reference_buffer_object(ctx,
891 &ctx->ShaderStorageBufferBindings[i].BufferObject,
892 ctx->Shared->NullBufferObj);
893 ctx->ShaderStorageBufferBindings[i].Offset = -1;
894 ctx->ShaderStorageBufferBindings[i].Size = -1;
895 }
896
897 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) {
898 _mesa_reference_buffer_object(ctx,
899 &ctx->AtomicBufferBindings[i].BufferObject,
900 ctx->Shared->NullBufferObj);
901 ctx->AtomicBufferBindings[i].Offset = 0;
902 ctx->AtomicBufferBindings[i].Size = 0;
903 }
904 }
905
906
907 void
908 _mesa_free_buffer_objects( struct gl_context *ctx )
909 {
910 GLuint i;
911
912 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
913
914 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL);
915 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL);
916
917 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL);
918
919 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, NULL);
920
921 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, NULL);
922
923 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, NULL);
924
925 _mesa_reference_buffer_object(ctx, &ctx->ParameterBuffer, NULL);
926
927 _mesa_reference_buffer_object(ctx, &ctx->DispatchIndirectBuffer, NULL);
928
929 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
930 _mesa_reference_buffer_object(ctx,
931 &ctx->UniformBufferBindings[i].BufferObject,
932 NULL);
933 }
934
935 for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) {
936 _mesa_reference_buffer_object(ctx,
937 &ctx->ShaderStorageBufferBindings[i].BufferObject,
938 NULL);
939 }
940
941 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) {
942 _mesa_reference_buffer_object(ctx,
943 &ctx->AtomicBufferBindings[i].BufferObject,
944 NULL);
945 }
946
947 }
948
949 bool
950 _mesa_handle_bind_buffer_gen(struct gl_context *ctx,
951 GLuint buffer,
952 struct gl_buffer_object **buf_handle,
953 const char *caller)
954 {
955 struct gl_buffer_object *buf = *buf_handle;
956
957 if (!buf && (ctx->API == API_OPENGL_CORE)) {
958 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller);
959 return false;
960 }
961
962 if (!buf || buf == &DummyBufferObject) {
963 /* If this is a new buffer object id, or one which was generated but
964 * never used before, allocate a buffer object now.
965 */
966 assert(ctx->Driver.NewBufferObject);
967 buf = ctx->Driver.NewBufferObject(ctx, buffer);
968 if (!buf) {
969 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
970 return false;
971 }
972 _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf);
973 *buf_handle = buf;
974 }
975
976 return true;
977 }
978
979 /**
980 * Bind the specified target to buffer for the specified context.
981 * Called by glBindBuffer() and other functions.
982 */
983 static void
984 bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer)
985 {
986 struct gl_buffer_object *oldBufObj;
987 struct gl_buffer_object *newBufObj = NULL;
988 struct gl_buffer_object **bindTarget = NULL;
989
990 bindTarget = get_buffer_target(ctx, target);
991 if (!bindTarget) {
992 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target 0x%x)", target);
993 return;
994 }
995
996 /* Get pointer to old buffer object (to be unbound) */
997 oldBufObj = *bindTarget;
998 if (oldBufObj && oldBufObj->Name == buffer && !oldBufObj->DeletePending)
999 return; /* rebinding the same buffer object- no change */
1000
1001 /*
1002 * Get pointer to new buffer object (newBufObj)
1003 */
1004 if (buffer == 0) {
1005 /* The spec says there's not a buffer object named 0, but we use
1006 * one internally because it simplifies things.
1007 */
1008 newBufObj = ctx->Shared->NullBufferObj;
1009 }
1010 else {
1011 /* non-default buffer object */
1012 newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
1013 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
1014 &newBufObj, "glBindBuffer"))
1015 return;
1016 }
1017
1018 /* record usage history */
1019 switch (target) {
1020 case GL_PIXEL_PACK_BUFFER:
1021 newBufObj->UsageHistory |= USAGE_PIXEL_PACK_BUFFER;
1022 break;
1023 default:
1024 break;
1025 }
1026
1027 /* bind new buffer */
1028 _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
1029 }
1030
1031
1032 /**
1033 * Update the default buffer objects in the given context to reference those
1034 * specified in the shared state and release those referencing the old
1035 * shared state.
1036 */
1037 void
1038 _mesa_update_default_objects_buffer_objects(struct gl_context *ctx)
1039 {
1040 /* Bind the NullBufferObj to remove references to those
1041 * in the shared context hash table.
1042 */
1043 bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0);
1044 bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1045 bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0);
1046 bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0);
1047 }
1048
1049
1050
1051 /**
1052 * Return the gl_buffer_object for the given ID.
1053 * Always return NULL for ID 0.
1054 */
1055 struct gl_buffer_object *
1056 _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer)
1057 {
1058 if (buffer == 0)
1059 return NULL;
1060 else
1061 return (struct gl_buffer_object *)
1062 _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
1063 }
1064
1065
1066 struct gl_buffer_object *
1067 _mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer)
1068 {
1069 return (struct gl_buffer_object *)
1070 _mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer);
1071 }
1072
1073 /**
1074 * A convenience function for direct state access functions that throws
1075 * GL_INVALID_OPERATION if buffer is not the name of an existing
1076 * buffer object.
1077 */
1078 struct gl_buffer_object *
1079 _mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer,
1080 const char *caller)
1081 {
1082 struct gl_buffer_object *bufObj;
1083
1084 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1085 if (!bufObj || bufObj == &DummyBufferObject) {
1086 _mesa_error(ctx, GL_INVALID_OPERATION,
1087 "%s(non-existent buffer object %u)", caller, buffer);
1088 return NULL;
1089 }
1090
1091 return bufObj;
1092 }
1093
1094
1095 void
1096 _mesa_begin_bufferobj_lookups(struct gl_context *ctx)
1097 {
1098 _mesa_HashLockMutex(ctx->Shared->BufferObjects);
1099 }
1100
1101
1102 void
1103 _mesa_end_bufferobj_lookups(struct gl_context *ctx)
1104 {
1105 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
1106 }
1107
1108
1109 /**
1110 * Look up a buffer object for a multi-bind function.
1111 *
1112 * Unlike _mesa_lookup_bufferobj(), this function also takes care
1113 * of generating an error if the buffer ID is not zero or the name
1114 * of an existing buffer object.
1115 *
1116 * If the buffer ID refers to an existing buffer object, a pointer
1117 * to the buffer object is returned. If the ID is zero, a pointer
1118 * to the shared NullBufferObj is returned. If the ID is not zero
1119 * and does not refer to a valid buffer object, this function
1120 * returns NULL.
1121 *
1122 * This function assumes that the caller has already locked the
1123 * hash table mutex by calling _mesa_begin_bufferobj_lookups().
1124 */
1125 struct gl_buffer_object *
1126 _mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx,
1127 const GLuint *buffers,
1128 GLuint index, const char *caller)
1129 {
1130 struct gl_buffer_object *bufObj;
1131
1132 if (buffers[index] != 0) {
1133 bufObj = _mesa_lookup_bufferobj_locked(ctx, buffers[index]);
1134
1135 /* The multi-bind functions don't create the buffer objects
1136 when they don't exist. */
1137 if (bufObj == &DummyBufferObject)
1138 bufObj = NULL;
1139 } else
1140 bufObj = ctx->Shared->NullBufferObj;
1141
1142 if (!bufObj) {
1143 /* The ARB_multi_bind spec says:
1144 *
1145 * "An INVALID_OPERATION error is generated if any value
1146 * in <buffers> is not zero or the name of an existing
1147 * buffer object (per binding)."
1148 */
1149 _mesa_error(ctx, GL_INVALID_OPERATION,
1150 "%s(buffers[%u]=%u is not zero or the name "
1151 "of an existing buffer object)",
1152 caller, index, buffers[index]);
1153 }
1154
1155 return bufObj;
1156 }
1157
1158
1159 /**
1160 * If *ptr points to obj, set ptr = the Null/default buffer object.
1161 * This is a helper for buffer object deletion.
1162 * The GL spec says that deleting a buffer object causes it to get
1163 * unbound from all arrays in the current context.
1164 */
1165 static void
1166 unbind(struct gl_context *ctx,
1167 struct gl_buffer_object **ptr,
1168 struct gl_buffer_object *obj)
1169 {
1170 if (*ptr == obj) {
1171 _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj);
1172 }
1173 }
1174
1175
1176 /**
1177 * Plug default/fallback buffer object functions into the device
1178 * driver hooks.
1179 */
1180 void
1181 _mesa_init_buffer_object_functions(struct dd_function_table *driver)
1182 {
1183 /* GL_ARB_vertex/pixel_buffer_object */
1184 driver->NewBufferObject = _mesa_new_buffer_object;
1185 driver->DeleteBuffer = _mesa_delete_buffer_object;
1186 driver->BufferData = buffer_data_fallback;
1187 driver->BufferSubData = buffer_sub_data_fallback;
1188 driver->GetBufferSubData = _mesa_buffer_get_subdata;
1189 driver->UnmapBuffer = unmap_buffer_fallback;
1190
1191 /* GL_ARB_clear_buffer_object */
1192 driver->ClearBufferSubData = _mesa_ClearBufferSubData_sw;
1193
1194 /* GL_ARB_map_buffer_range */
1195 driver->MapBufferRange = map_buffer_range_fallback;
1196 driver->FlushMappedBufferRange = flush_mapped_buffer_range_fallback;
1197
1198 /* GL_ARB_copy_buffer */
1199 driver->CopyBufferSubData = copy_buffer_sub_data_fallback;
1200 }
1201
1202
1203 void
1204 _mesa_buffer_unmap_all_mappings(struct gl_context *ctx,
1205 struct gl_buffer_object *bufObj)
1206 {
1207 int i;
1208
1209 for (i = 0; i < MAP_COUNT; i++) {
1210 if (_mesa_bufferobj_mapped(bufObj, i)) {
1211 ctx->Driver.UnmapBuffer(ctx, bufObj, i);
1212 assert(bufObj->Mappings[i].Pointer == NULL);
1213 bufObj->Mappings[i].AccessFlags = 0;
1214 }
1215 }
1216 }
1217
1218
1219 /**********************************************************************/
1220 /* API Functions */
1221 /**********************************************************************/
1222
1223 void GLAPIENTRY
1224 _mesa_BindBuffer(GLenum target, GLuint buffer)
1225 {
1226 GET_CURRENT_CONTEXT(ctx);
1227
1228 if (MESA_VERBOSE & VERBOSE_API) {
1229 _mesa_debug(ctx, "glBindBuffer(%s, %u)\n",
1230 _mesa_enum_to_string(target), buffer);
1231 }
1232
1233 bind_buffer_object(ctx, target, buffer);
1234 }
1235
1236
1237 /**
1238 * Delete a set of buffer objects.
1239 *
1240 * \param n Number of buffer objects to delete.
1241 * \param ids Array of \c n buffer object IDs.
1242 */
1243 void GLAPIENTRY
1244 _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
1245 {
1246 GET_CURRENT_CONTEXT(ctx);
1247 GLsizei i;
1248 FLUSH_VERTICES(ctx, 0);
1249
1250 if (n < 0) {
1251 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
1252 return;
1253 }
1254
1255 mtx_lock(&ctx->Shared->Mutex);
1256
1257 for (i = 0; i < n; i++) {
1258 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]);
1259 if (bufObj) {
1260 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1261 GLuint j;
1262
1263 assert(bufObj->Name == ids[i] || bufObj == &DummyBufferObject);
1264
1265 _mesa_buffer_unmap_all_mappings(ctx, bufObj);
1266
1267 /* unbind any vertex pointers bound to this buffer */
1268 for (j = 0; j < ARRAY_SIZE(vao->VertexBinding); j++) {
1269 unbind(ctx, &vao->VertexBinding[j].BufferObj, bufObj);
1270 }
1271
1272 if (ctx->Array.ArrayBufferObj == bufObj) {
1273 _mesa_BindBuffer( GL_ARRAY_BUFFER_ARB, 0 );
1274 }
1275 if (vao->IndexBufferObj == bufObj) {
1276 _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
1277 }
1278
1279 /* unbind ARB_draw_indirect binding point */
1280 if (ctx->DrawIndirectBuffer == bufObj) {
1281 _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 );
1282 }
1283
1284 /* unbind ARB_indirect_parameters binding point */
1285 if (ctx->ParameterBuffer == bufObj) {
1286 _mesa_BindBuffer(GL_PARAMETER_BUFFER_ARB, 0);
1287 }
1288
1289 /* unbind ARB_compute_shader binding point */
1290 if (ctx->DispatchIndirectBuffer == bufObj) {
1291 _mesa_BindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
1292 }
1293
1294 /* unbind ARB_copy_buffer binding points */
1295 if (ctx->CopyReadBuffer == bufObj) {
1296 _mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 );
1297 }
1298 if (ctx->CopyWriteBuffer == bufObj) {
1299 _mesa_BindBuffer( GL_COPY_WRITE_BUFFER, 0 );
1300 }
1301
1302 /* unbind transform feedback binding points */
1303 if (ctx->TransformFeedback.CurrentBuffer == bufObj) {
1304 _mesa_BindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, 0 );
1305 }
1306 for (j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
1307 if (ctx->TransformFeedback.CurrentObject->Buffers[j] == bufObj) {
1308 _mesa_BindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, j, 0 );
1309 }
1310 }
1311
1312 /* unbind UBO binding points */
1313 for (j = 0; j < ctx->Const.MaxUniformBufferBindings; j++) {
1314 if (ctx->UniformBufferBindings[j].BufferObject == bufObj) {
1315 _mesa_BindBufferBase( GL_UNIFORM_BUFFER, j, 0 );
1316 }
1317 }
1318
1319 if (ctx->UniformBuffer == bufObj) {
1320 _mesa_BindBuffer( GL_UNIFORM_BUFFER, 0 );
1321 }
1322
1323 /* unbind SSBO binding points */
1324 for (j = 0; j < ctx->Const.MaxShaderStorageBufferBindings; j++) {
1325 if (ctx->ShaderStorageBufferBindings[j].BufferObject == bufObj) {
1326 _mesa_BindBufferBase(GL_SHADER_STORAGE_BUFFER, j, 0);
1327 }
1328 }
1329
1330 if (ctx->ShaderStorageBuffer == bufObj) {
1331 _mesa_BindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1332 }
1333
1334 /* unbind Atomci Buffer binding points */
1335 for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) {
1336 if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) {
1337 _mesa_BindBufferBase( GL_ATOMIC_COUNTER_BUFFER, j, 0 );
1338 }
1339 }
1340
1341 if (ctx->AtomicBuffer == bufObj) {
1342 _mesa_BindBuffer( GL_ATOMIC_COUNTER_BUFFER, 0 );
1343 }
1344
1345 /* unbind any pixel pack/unpack pointers bound to this buffer */
1346 if (ctx->Pack.BufferObj == bufObj) {
1347 _mesa_BindBuffer( GL_PIXEL_PACK_BUFFER_EXT, 0 );
1348 }
1349 if (ctx->Unpack.BufferObj == bufObj) {
1350 _mesa_BindBuffer( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
1351 }
1352
1353 if (ctx->Texture.BufferObject == bufObj) {
1354 _mesa_BindBuffer( GL_TEXTURE_BUFFER, 0 );
1355 }
1356
1357 if (ctx->ExternalVirtualMemoryBuffer == bufObj) {
1358 _mesa_BindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
1359 }
1360
1361 /* The ID is immediately freed for re-use */
1362 _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]);
1363 /* Make sure we do not run into the classic ABA problem on bind.
1364 * We don't want to allow re-binding a buffer object that's been
1365 * "deleted" by glDeleteBuffers().
1366 *
1367 * The explicit rebinding to the default object in the current context
1368 * prevents the above in the current context, but another context
1369 * sharing the same objects might suffer from this problem.
1370 * The alternative would be to do the hash lookup in any case on bind
1371 * which would introduce more runtime overhead than this.
1372 */
1373 bufObj->DeletePending = GL_TRUE;
1374 _mesa_reference_buffer_object(ctx, &bufObj, NULL);
1375 }
1376 }
1377
1378 mtx_unlock(&ctx->Shared->Mutex);
1379 }
1380
1381
1382 /**
1383 * This is the implementation for glGenBuffers and glCreateBuffers. It is not
1384 * exposed to the rest of Mesa to encourage the use of nameless buffers in
1385 * driver internals.
1386 */
1387 static void
1388 create_buffers(GLsizei n, GLuint *buffers, bool dsa)
1389 {
1390 GET_CURRENT_CONTEXT(ctx);
1391 GLuint first;
1392 GLint i;
1393 struct gl_buffer_object *buf;
1394
1395 const char *func = dsa ? "glCreateBuffers" : "glGenBuffers";
1396
1397 if (MESA_VERBOSE & VERBOSE_API)
1398 _mesa_debug(ctx, "%s(%d)\n", func, n);
1399
1400 if (n < 0) {
1401 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n %d < 0)", func, n);
1402 return;
1403 }
1404
1405 if (!buffers) {
1406 return;
1407 }
1408
1409 /*
1410 * This must be atomic (generation and allocation of buffer object IDs)
1411 */
1412 mtx_lock(&ctx->Shared->Mutex);
1413
1414 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
1415
1416 /* Insert the ID and pointer into the hash table. If non-DSA, insert a
1417 * DummyBufferObject. Otherwise, create a new buffer object and insert
1418 * it.
1419 */
1420 for (i = 0; i < n; i++) {
1421 buffers[i] = first + i;
1422 if (dsa) {
1423 assert(ctx->Driver.NewBufferObject);
1424 buf = ctx->Driver.NewBufferObject(ctx, buffers[i]);
1425 if (!buf) {
1426 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1427 mtx_unlock(&ctx->Shared->Mutex);
1428 return;
1429 }
1430 }
1431 else
1432 buf = &DummyBufferObject;
1433
1434 _mesa_HashInsert(ctx->Shared->BufferObjects, buffers[i], buf);
1435 }
1436
1437 mtx_unlock(&ctx->Shared->Mutex);
1438 }
1439
1440 /**
1441 * Generate a set of unique buffer object IDs and store them in \c buffers.
1442 *
1443 * \param n Number of IDs to generate.
1444 * \param buffers Array of \c n locations to store the IDs.
1445 */
1446 void GLAPIENTRY
1447 _mesa_GenBuffers(GLsizei n, GLuint *buffers)
1448 {
1449 create_buffers(n, buffers, false);
1450 }
1451
1452 /**
1453 * Create a set of buffer objects and store their unique IDs in \c buffers.
1454 *
1455 * \param n Number of IDs to generate.
1456 * \param buffers Array of \c n locations to store the IDs.
1457 */
1458 void GLAPIENTRY
1459 _mesa_CreateBuffers(GLsizei n, GLuint *buffers)
1460 {
1461 create_buffers(n, buffers, true);
1462 }
1463
1464
1465 /**
1466 * Determine if ID is the name of a buffer object.
1467 *
1468 * \param id ID of the potential buffer object.
1469 * \return \c GL_TRUE if \c id is the name of a buffer object,
1470 * \c GL_FALSE otherwise.
1471 */
1472 GLboolean GLAPIENTRY
1473 _mesa_IsBuffer(GLuint id)
1474 {
1475 struct gl_buffer_object *bufObj;
1476 GET_CURRENT_CONTEXT(ctx);
1477 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1478
1479 mtx_lock(&ctx->Shared->Mutex);
1480 bufObj = _mesa_lookup_bufferobj(ctx, id);
1481 mtx_unlock(&ctx->Shared->Mutex);
1482
1483 return bufObj && bufObj != &DummyBufferObject;
1484 }
1485
1486
1487 void
1488 _mesa_buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj,
1489 GLenum target, GLsizeiptr size, const GLvoid *data,
1490 GLbitfield flags, const char *func)
1491 {
1492 if (size <= 0) {
1493 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size <= 0)", func);
1494 return;
1495 }
1496
1497 if (flags & ~(GL_MAP_READ_BIT |
1498 GL_MAP_WRITE_BIT |
1499 GL_MAP_PERSISTENT_BIT |
1500 GL_MAP_COHERENT_BIT |
1501 GL_DYNAMIC_STORAGE_BIT |
1502 GL_CLIENT_STORAGE_BIT)) {
1503 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid flag bits set)", func);
1504 return;
1505 }
1506
1507 if (flags & GL_MAP_PERSISTENT_BIT &&
1508 !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) {
1509 _mesa_error(ctx, GL_INVALID_VALUE,
1510 "%s(PERSISTENT and flags!=READ/WRITE)", func);
1511 return;
1512 }
1513
1514 if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) {
1515 _mesa_error(ctx, GL_INVALID_VALUE,
1516 "%s(COHERENT and flags!=PERSISTENT)", func);
1517 return;
1518 }
1519
1520 if (bufObj->Immutable) {
1521 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
1522 return;
1523 }
1524
1525 /* Unmap the existing buffer. We'll replace it now. Not an error. */
1526 _mesa_buffer_unmap_all_mappings(ctx, bufObj);
1527
1528 FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
1529
1530 bufObj->Written = GL_TRUE;
1531 bufObj->Immutable = GL_TRUE;
1532 bufObj->MinMaxCacheDirty = true;
1533
1534 assert(ctx->Driver.BufferData);
1535 if (!ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW,
1536 flags, bufObj)) {
1537 if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
1538 /* Even though the interaction between AMD_pinned_memory and
1539 * glBufferStorage is not described in the spec, Graham Sellers
1540 * said that it should behave the same as glBufferData.
1541 */
1542 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1543 }
1544 else {
1545 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1546 }
1547 }
1548 }
1549
1550 void GLAPIENTRY
1551 _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
1552 GLbitfield flags)
1553 {
1554 GET_CURRENT_CONTEXT(ctx);
1555 struct gl_buffer_object *bufObj;
1556
1557 bufObj = get_buffer(ctx, "glBufferStorage", target, GL_INVALID_OPERATION);
1558 if (!bufObj)
1559 return;
1560
1561 _mesa_buffer_storage(ctx, bufObj, target, size, data, flags,
1562 "glBufferStorage");
1563 }
1564
1565 void GLAPIENTRY
1566 _mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
1567 GLbitfield flags)
1568 {
1569 GET_CURRENT_CONTEXT(ctx);
1570 struct gl_buffer_object *bufObj;
1571
1572 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferStorage");
1573 if (!bufObj)
1574 return;
1575
1576 /*
1577 * In direct state access, buffer objects have an unspecified target since
1578 * they are not required to be bound.
1579 */
1580 _mesa_buffer_storage(ctx, bufObj, GL_NONE, size, data, flags,
1581 "glNamedBufferStorage");
1582 }
1583
1584
1585 void
1586 _mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
1587 GLenum target, GLsizeiptr size, const GLvoid *data,
1588 GLenum usage, const char *func)
1589 {
1590 bool valid_usage;
1591
1592 if (MESA_VERBOSE & VERBOSE_API) {
1593 _mesa_debug(ctx, "%s(%s, %ld, %p, %s)\n",
1594 func,
1595 _mesa_enum_to_string(target),
1596 (long int) size, data,
1597 _mesa_enum_to_string(usage));
1598 }
1599
1600 if (size < 0) {
1601 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", func);
1602 return;
1603 }
1604
1605 switch (usage) {
1606 case GL_STREAM_DRAW_ARB:
1607 valid_usage = (ctx->API != API_OPENGLES);
1608 break;
1609
1610 case GL_STATIC_DRAW_ARB:
1611 case GL_DYNAMIC_DRAW_ARB:
1612 valid_usage = true;
1613 break;
1614
1615 case GL_STREAM_READ_ARB:
1616 case GL_STREAM_COPY_ARB:
1617 case GL_STATIC_READ_ARB:
1618 case GL_STATIC_COPY_ARB:
1619 case GL_DYNAMIC_READ_ARB:
1620 case GL_DYNAMIC_COPY_ARB:
1621 valid_usage = _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx);
1622 break;
1623
1624 default:
1625 valid_usage = false;
1626 break;
1627 }
1628
1629 if (!valid_usage) {
1630 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid usage: %s)", func,
1631 _mesa_enum_to_string(usage));
1632 return;
1633 }
1634
1635 if (bufObj->Immutable) {
1636 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
1637 return;
1638 }
1639
1640 /* Unmap the existing buffer. We'll replace it now. Not an error. */
1641 _mesa_buffer_unmap_all_mappings(ctx, bufObj);
1642
1643 FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
1644
1645 bufObj->Written = GL_TRUE;
1646 bufObj->MinMaxCacheDirty = true;
1647
1648 #ifdef VBO_DEBUG
1649 printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
1650 bufObj->Name, size, data, usage);
1651 #endif
1652
1653 #ifdef BOUNDS_CHECK
1654 size += 100;
1655 #endif
1656
1657 assert(ctx->Driver.BufferData);
1658 if (!ctx->Driver.BufferData(ctx, target, size, data, usage,
1659 GL_MAP_READ_BIT |
1660 GL_MAP_WRITE_BIT |
1661 GL_DYNAMIC_STORAGE_BIT,
1662 bufObj)) {
1663 if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
1664 /* From GL_AMD_pinned_memory:
1665 *
1666 * INVALID_OPERATION is generated by BufferData if <target> is
1667 * EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be
1668 * mapped to the GPU address space.
1669 */
1670 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1671 }
1672 else {
1673 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1674 }
1675 }
1676 }
1677
1678 void GLAPIENTRY
1679 _mesa_BufferData(GLenum target, GLsizeiptr size,
1680 const GLvoid *data, GLenum usage)
1681 {
1682 GET_CURRENT_CONTEXT(ctx);
1683 struct gl_buffer_object *bufObj;
1684
1685 bufObj = get_buffer(ctx, "glBufferData", target, GL_INVALID_OPERATION);
1686 if (!bufObj)
1687 return;
1688
1689 _mesa_buffer_data(ctx, bufObj, target, size, data, usage,
1690 "glBufferData");
1691 }
1692
1693 void GLAPIENTRY
1694 _mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data,
1695 GLenum usage)
1696 {
1697 GET_CURRENT_CONTEXT(ctx);
1698 struct gl_buffer_object *bufObj;
1699
1700 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData");
1701 if (!bufObj)
1702 return;
1703
1704 /* In direct state access, buffer objects have an unspecified target since
1705 * they are not required to be bound.
1706 */
1707 _mesa_buffer_data(ctx, bufObj, GL_NONE, size, data, usage,
1708 "glNamedBufferData");
1709 }
1710
1711
1712 /**
1713 * Implementation for glBufferSubData and glNamedBufferSubData.
1714 *
1715 * \param ctx GL context.
1716 * \param bufObj The buffer object.
1717 * \param offset Offset of the first byte of the subdata range.
1718 * \param size Size, in bytes, of the subdata range.
1719 * \param data The data store.
1720 * \param func Name of calling function for recording errors.
1721 *
1722 */
1723 void
1724 _mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
1725 GLintptr offset, GLsizeiptr size, const GLvoid *data,
1726 const char *func)
1727 {
1728 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size,
1729 false, func)) {
1730 /* error already recorded */
1731 return;
1732 }
1733
1734 if (bufObj->Immutable &&
1735 !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) {
1736 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1737 return;
1738 }
1739
1740 if (size == 0)
1741 return;
1742
1743 bufObj->NumSubDataCalls++;
1744
1745 if ((bufObj->Usage == GL_STATIC_DRAW ||
1746 bufObj->Usage == GL_STATIC_COPY) &&
1747 bufObj->NumSubDataCalls >= BUFFER_WARNING_CALL_COUNT) {
1748 /* If the application declared the buffer as static draw/copy or stream
1749 * draw, it should not be frequently modified with glBufferSubData.
1750 */
1751 BUFFER_USAGE_WARNING(ctx,
1752 "using %s(buffer %u, offset %u, size %u) to "
1753 "update a %s buffer",
1754 func, bufObj->Name, offset, size,
1755 _mesa_enum_to_string(bufObj->Usage));
1756 }
1757
1758 bufObj->Written = GL_TRUE;
1759 bufObj->MinMaxCacheDirty = true;
1760
1761 assert(ctx->Driver.BufferSubData);
1762 ctx->Driver.BufferSubData(ctx, offset, size, data, bufObj);
1763 }
1764
1765 void GLAPIENTRY
1766 _mesa_BufferSubData(GLenum target, GLintptr offset,
1767 GLsizeiptr size, const GLvoid *data)
1768 {
1769 GET_CURRENT_CONTEXT(ctx);
1770 struct gl_buffer_object *bufObj;
1771
1772 bufObj = get_buffer(ctx, "glBufferSubData", target, GL_INVALID_OPERATION);
1773 if (!bufObj)
1774 return;
1775
1776 _mesa_buffer_sub_data(ctx, bufObj, offset, size, data, "glBufferSubData");
1777 }
1778
1779 void GLAPIENTRY
1780 _mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
1781 GLsizeiptr size, const GLvoid *data)
1782 {
1783 GET_CURRENT_CONTEXT(ctx);
1784 struct gl_buffer_object *bufObj;
1785
1786 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferSubData");
1787 if (!bufObj)
1788 return;
1789
1790 _mesa_buffer_sub_data(ctx, bufObj, offset, size, data,
1791 "glNamedBufferSubData");
1792 }
1793
1794
1795 void GLAPIENTRY
1796 _mesa_GetBufferSubData(GLenum target, GLintptr offset,
1797 GLsizeiptr size, GLvoid *data)
1798 {
1799 GET_CURRENT_CONTEXT(ctx);
1800 struct gl_buffer_object *bufObj;
1801
1802 bufObj = get_buffer(ctx, "glGetBufferSubData", target,
1803 GL_INVALID_OPERATION);
1804 if (!bufObj)
1805 return;
1806
1807 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
1808 "glGetBufferSubData")) {
1809 return;
1810 }
1811
1812 assert(ctx->Driver.GetBufferSubData);
1813 ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
1814 }
1815
1816 void GLAPIENTRY
1817 _mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset,
1818 GLsizeiptr size, GLvoid *data)
1819 {
1820 GET_CURRENT_CONTEXT(ctx);
1821 struct gl_buffer_object *bufObj;
1822
1823 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
1824 "glGetNamedBufferSubData");
1825 if (!bufObj)
1826 return;
1827
1828 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
1829 "glGetNamedBufferSubData")) {
1830 return;
1831 }
1832
1833 assert(ctx->Driver.GetBufferSubData);
1834 ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
1835 }
1836
1837
1838 /**
1839 * \param subdata true if caller is *SubData, false if *Data
1840 */
1841 void
1842 _mesa_clear_buffer_sub_data(struct gl_context *ctx,
1843 struct gl_buffer_object *bufObj,
1844 GLenum internalformat,
1845 GLintptr offset, GLsizeiptr size,
1846 GLenum format, GLenum type,
1847 const GLvoid *data,
1848 const char *func, bool subdata)
1849 {
1850 mesa_format mesaFormat;
1851 GLubyte clearValue[MAX_PIXEL_BYTES];
1852 GLsizeiptr clearValueSize;
1853
1854 /* This checks for disallowed mappings. */
1855 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size,
1856 subdata, func)) {
1857 return;
1858 }
1859
1860 mesaFormat = validate_clear_buffer_format(ctx, internalformat,
1861 format, type, func);
1862
1863 if (mesaFormat == MESA_FORMAT_NONE) {
1864 return;
1865 }
1866
1867 clearValueSize = _mesa_get_format_bytes(mesaFormat);
1868 if (offset % clearValueSize != 0 || size % clearValueSize != 0) {
1869 _mesa_error(ctx, GL_INVALID_VALUE,
1870 "%s(offset or size is not a multiple of "
1871 "internalformat size)", func);
1872 return;
1873 }
1874
1875 /* Bail early. Negative size has already been checked. */
1876 if (size == 0)
1877 return;
1878
1879 bufObj->MinMaxCacheDirty = true;
1880
1881 if (data == NULL) {
1882 /* clear to zeros, per the spec */
1883 ctx->Driver.ClearBufferSubData(ctx, offset, size,
1884 NULL, clearValueSize, bufObj);
1885 return;
1886 }
1887
1888 if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue,
1889 format, type, data, func)) {
1890 return;
1891 }
1892
1893 ctx->Driver.ClearBufferSubData(ctx, offset, size,
1894 clearValue, clearValueSize, bufObj);
1895 }
1896
1897 void GLAPIENTRY
1898 _mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format,
1899 GLenum type, const GLvoid *data)
1900 {
1901 GET_CURRENT_CONTEXT(ctx);
1902 struct gl_buffer_object *bufObj;
1903
1904 bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE);
1905 if (!bufObj)
1906 return;
1907
1908 _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
1909 format, type, data,
1910 "glClearBufferData", false);
1911 }
1912
1913 void GLAPIENTRY
1914 _mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat,
1915 GLenum format, GLenum type, const GLvoid *data)
1916 {
1917 GET_CURRENT_CONTEXT(ctx);
1918 struct gl_buffer_object *bufObj;
1919
1920 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData");
1921 if (!bufObj)
1922 return;
1923
1924 _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, 0, bufObj->Size,
1925 format, type, data,
1926 "glClearNamedBufferData", false);
1927 }
1928
1929
1930 void GLAPIENTRY
1931 _mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
1932 GLintptr offset, GLsizeiptr size,
1933 GLenum format, GLenum type,
1934 const GLvoid *data)
1935 {
1936 GET_CURRENT_CONTEXT(ctx);
1937 struct gl_buffer_object *bufObj;
1938
1939 bufObj = get_buffer(ctx, "glClearBufferSubData", target, GL_INVALID_VALUE);
1940 if (!bufObj)
1941 return;
1942
1943 _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size,
1944 format, type, data,
1945 "glClearBufferSubData", true);
1946 }
1947
1948 void GLAPIENTRY
1949 _mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat,
1950 GLintptr offset, GLsizeiptr size,
1951 GLenum format, GLenum type,
1952 const GLvoid *data)
1953 {
1954 GET_CURRENT_CONTEXT(ctx);
1955 struct gl_buffer_object *bufObj;
1956
1957 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
1958 "glClearNamedBufferSubData");
1959 if (!bufObj)
1960 return;
1961
1962 _mesa_clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size,
1963 format, type, data,
1964 "glClearNamedBufferSubData", true);
1965 }
1966
1967
1968 GLboolean
1969 _mesa_unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj,
1970 const char *func)
1971 {
1972 GLboolean status = GL_TRUE;
1973 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1974
1975 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
1976 _mesa_error(ctx, GL_INVALID_OPERATION,
1977 "%s(buffer is not mapped)", func);
1978 return GL_FALSE;
1979 }
1980
1981 #ifdef BOUNDS_CHECK
1982 if (bufObj->Access != GL_READ_ONLY_ARB) {
1983 GLubyte *buf = (GLubyte *) bufObj->Pointer;
1984 GLuint i;
1985 /* check that last 100 bytes are still = magic value */
1986 for (i = 0; i < 100; i++) {
1987 GLuint pos = bufObj->Size - i - 1;
1988 if (buf[pos] != 123) {
1989 _mesa_warning(ctx, "Out of bounds buffer object write detected"
1990 " at position %d (value = %u)\n",
1991 pos, buf[pos]);
1992 }
1993 }
1994 }
1995 #endif
1996
1997 #ifdef VBO_DEBUG
1998 if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
1999 GLuint i, unchanged = 0;
2000 GLubyte *b = (GLubyte *) bufObj->Pointer;
2001 GLint pos = -1;
2002 /* check which bytes changed */
2003 for (i = 0; i < bufObj->Size - 1; i++) {
2004 if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
2005 unchanged++;
2006 if (pos == -1)
2007 pos = i;
2008 }
2009 }
2010 if (unchanged) {
2011 printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
2012 bufObj->Name, unchanged, bufObj->Size, pos);
2013 }
2014 }
2015 #endif
2016
2017 status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER);
2018 bufObj->Mappings[MAP_USER].AccessFlags = 0;
2019 assert(bufObj->Mappings[MAP_USER].Pointer == NULL);
2020 assert(bufObj->Mappings[MAP_USER].Offset == 0);
2021 assert(bufObj->Mappings[MAP_USER].Length == 0);
2022
2023 return status;
2024 }
2025
2026 GLboolean GLAPIENTRY
2027 _mesa_UnmapBuffer(GLenum target)
2028 {
2029 GET_CURRENT_CONTEXT(ctx);
2030 struct gl_buffer_object *bufObj;
2031
2032 bufObj = get_buffer(ctx, "glUnmapBuffer", target, GL_INVALID_OPERATION);
2033 if (!bufObj)
2034 return GL_FALSE;
2035
2036 return _mesa_unmap_buffer(ctx, bufObj, "glUnmapBuffer");
2037 }
2038
2039 GLboolean GLAPIENTRY
2040 _mesa_UnmapNamedBuffer(GLuint buffer)
2041 {
2042 GET_CURRENT_CONTEXT(ctx);
2043 struct gl_buffer_object *bufObj;
2044
2045 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer");
2046 if (!bufObj)
2047 return GL_FALSE;
2048
2049 return _mesa_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer");
2050 }
2051
2052
2053 static bool
2054 get_buffer_parameter(struct gl_context *ctx,
2055 struct gl_buffer_object *bufObj, GLenum pname,
2056 GLint64 *params, const char *func)
2057 {
2058 switch (pname) {
2059 case GL_BUFFER_SIZE_ARB:
2060 *params = bufObj->Size;
2061 break;
2062 case GL_BUFFER_USAGE_ARB:
2063 *params = bufObj->Usage;
2064 break;
2065 case GL_BUFFER_ACCESS_ARB:
2066 *params = simplified_access_mode(ctx,
2067 bufObj->Mappings[MAP_USER].AccessFlags);
2068 break;
2069 case GL_BUFFER_MAPPED_ARB:
2070 *params = _mesa_bufferobj_mapped(bufObj, MAP_USER);
2071 break;
2072 case GL_BUFFER_ACCESS_FLAGS:
2073 if (!ctx->Extensions.ARB_map_buffer_range)
2074 goto invalid_pname;
2075 *params = bufObj->Mappings[MAP_USER].AccessFlags;
2076 break;
2077 case GL_BUFFER_MAP_OFFSET:
2078 if (!ctx->Extensions.ARB_map_buffer_range)
2079 goto invalid_pname;
2080 *params = bufObj->Mappings[MAP_USER].Offset;
2081 break;
2082 case GL_BUFFER_MAP_LENGTH:
2083 if (!ctx->Extensions.ARB_map_buffer_range)
2084 goto invalid_pname;
2085 *params = bufObj->Mappings[MAP_USER].Length;
2086 break;
2087 case GL_BUFFER_IMMUTABLE_STORAGE:
2088 if (!ctx->Extensions.ARB_buffer_storage)
2089 goto invalid_pname;
2090 *params = bufObj->Immutable;
2091 break;
2092 case GL_BUFFER_STORAGE_FLAGS:
2093 if (!ctx->Extensions.ARB_buffer_storage)
2094 goto invalid_pname;
2095 *params = bufObj->StorageFlags;
2096 break;
2097 default:
2098 goto invalid_pname;
2099 }
2100
2101 return true;
2102
2103 invalid_pname:
2104 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname: %s)", func,
2105 _mesa_enum_to_string(pname));
2106 return false;
2107 }
2108
2109 void GLAPIENTRY
2110 _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
2111 {
2112 GET_CURRENT_CONTEXT(ctx);
2113 struct gl_buffer_object *bufObj;
2114 GLint64 parameter;
2115
2116 bufObj = get_buffer(ctx, "glGetBufferParameteriv", target,
2117 GL_INVALID_OPERATION);
2118 if (!bufObj)
2119 return;
2120
2121 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2122 "glGetBufferParameteriv"))
2123 return; /* Error already recorded. */
2124
2125 *params = (GLint) parameter;
2126 }
2127
2128 void GLAPIENTRY
2129 _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
2130 {
2131 GET_CURRENT_CONTEXT(ctx);
2132 struct gl_buffer_object *bufObj;
2133 GLint64 parameter;
2134
2135 bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target,
2136 GL_INVALID_OPERATION);
2137 if (!bufObj)
2138 return;
2139
2140 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2141 "glGetBufferParameteri64v"))
2142 return; /* Error already recorded. */
2143
2144 *params = parameter;
2145 }
2146
2147 void GLAPIENTRY
2148 _mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params)
2149 {
2150 GET_CURRENT_CONTEXT(ctx);
2151 struct gl_buffer_object *bufObj;
2152 GLint64 parameter;
2153
2154 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2155 "glGetNamedBufferParameteriv");
2156 if (!bufObj)
2157 return;
2158
2159 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2160 "glGetNamedBufferParameteriv"))
2161 return; /* Error already recorded. */
2162
2163 *params = (GLint) parameter;
2164 }
2165
2166 void GLAPIENTRY
2167 _mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname,
2168 GLint64 *params)
2169 {
2170 GET_CURRENT_CONTEXT(ctx);
2171 struct gl_buffer_object *bufObj;
2172 GLint64 parameter;
2173
2174 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2175 "glGetNamedBufferParameteri64v");
2176 if (!bufObj)
2177 return;
2178
2179 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2180 "glGetNamedBufferParameteri64v"))
2181 return; /* Error already recorded. */
2182
2183 *params = parameter;
2184 }
2185
2186
2187 void GLAPIENTRY
2188 _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params)
2189 {
2190 GET_CURRENT_CONTEXT(ctx);
2191 struct gl_buffer_object *bufObj;
2192
2193 if (pname != GL_BUFFER_MAP_POINTER) {
2194 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointerv(pname != "
2195 "GL_BUFFER_MAP_POINTER)");
2196 return;
2197 }
2198
2199 bufObj = get_buffer(ctx, "glGetBufferPointerv", target,
2200 GL_INVALID_OPERATION);
2201 if (!bufObj)
2202 return;
2203
2204 *params = bufObj->Mappings[MAP_USER].Pointer;
2205 }
2206
2207 void GLAPIENTRY
2208 _mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params)
2209 {
2210 GET_CURRENT_CONTEXT(ctx);
2211 struct gl_buffer_object *bufObj;
2212
2213 if (pname != GL_BUFFER_MAP_POINTER) {
2214 _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != "
2215 "GL_BUFFER_MAP_POINTER)");
2216 return;
2217 }
2218
2219 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2220 "glGetNamedBufferPointerv");
2221 if (!bufObj)
2222 return;
2223
2224 *params = bufObj->Mappings[MAP_USER].Pointer;
2225 }
2226
2227
2228 void
2229 _mesa_copy_buffer_sub_data(struct gl_context *ctx,
2230 struct gl_buffer_object *src,
2231 struct gl_buffer_object *dst,
2232 GLintptr readOffset, GLintptr writeOffset,
2233 GLsizeiptr size, const char *func)
2234 {
2235 if (_mesa_check_disallowed_mapping(src)) {
2236 _mesa_error(ctx, GL_INVALID_OPERATION,
2237 "%s(readBuffer is mapped)", func);
2238 return;
2239 }
2240
2241 if (_mesa_check_disallowed_mapping(dst)) {
2242 _mesa_error(ctx, GL_INVALID_OPERATION,
2243 "%s(writeBuffer is mapped)", func);
2244 return;
2245 }
2246
2247 if (readOffset < 0) {
2248 _mesa_error(ctx, GL_INVALID_VALUE,
2249 "%s(readOffset %d < 0)", func, (int) readOffset);
2250 return;
2251 }
2252
2253 if (writeOffset < 0) {
2254 _mesa_error(ctx, GL_INVALID_VALUE,
2255 "%s(writeOffset %d < 0)", func, (int) writeOffset);
2256 return;
2257 }
2258
2259 if (size < 0) {
2260 _mesa_error(ctx, GL_INVALID_VALUE,
2261 "%s(size %d < 0)", func, (int) size);
2262 return;
2263 }
2264
2265 if (readOffset + size > src->Size) {
2266 _mesa_error(ctx, GL_INVALID_VALUE,
2267 "%s(readOffset %d + size %d > src_buffer_size %d)", func,
2268 (int) readOffset, (int) size, (int) src->Size);
2269 return;
2270 }
2271
2272 if (writeOffset + size > dst->Size) {
2273 _mesa_error(ctx, GL_INVALID_VALUE,
2274 "%s(writeOffset %d + size %d > dst_buffer_size %d)", func,
2275 (int) writeOffset, (int) size, (int) dst->Size);
2276 return;
2277 }
2278
2279 if (src == dst) {
2280 if (readOffset + size <= writeOffset) {
2281 /* OK */
2282 }
2283 else if (writeOffset + size <= readOffset) {
2284 /* OK */
2285 }
2286 else {
2287 /* overlapping src/dst is illegal */
2288 _mesa_error(ctx, GL_INVALID_VALUE,
2289 "%s(overlapping src/dst)", func);
2290 return;
2291 }
2292 }
2293
2294 dst->MinMaxCacheDirty = true;
2295
2296 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
2297 }
2298
2299 void GLAPIENTRY
2300 _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
2301 GLintptr readOffset, GLintptr writeOffset,
2302 GLsizeiptr size)
2303 {
2304 GET_CURRENT_CONTEXT(ctx);
2305 struct gl_buffer_object *src, *dst;
2306
2307 src = get_buffer(ctx, "glCopyBufferSubData", readTarget,
2308 GL_INVALID_OPERATION);
2309 if (!src)
2310 return;
2311
2312 dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget,
2313 GL_INVALID_OPERATION);
2314 if (!dst)
2315 return;
2316
2317 _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
2318 "glCopyBufferSubData");
2319 }
2320
2321 void GLAPIENTRY
2322 _mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
2323 GLintptr readOffset, GLintptr writeOffset,
2324 GLsizeiptr size)
2325 {
2326 GET_CURRENT_CONTEXT(ctx);
2327 struct gl_buffer_object *src, *dst;
2328
2329 src = _mesa_lookup_bufferobj_err(ctx, readBuffer,
2330 "glCopyNamedBufferSubData");
2331 if (!src)
2332 return;
2333
2334 dst = _mesa_lookup_bufferobj_err(ctx, writeBuffer,
2335 "glCopyNamedBufferSubData");
2336 if (!dst)
2337 return;
2338
2339 _mesa_copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
2340 "glCopyNamedBufferSubData");
2341 }
2342
2343
2344 void *
2345 _mesa_map_buffer_range(struct gl_context *ctx,
2346 struct gl_buffer_object *bufObj,
2347 GLintptr offset, GLsizeiptr length,
2348 GLbitfield access, const char *func)
2349 {
2350 void *map;
2351 GLbitfield allowed_access;
2352
2353 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
2354
2355 if (offset < 0) {
2356 _mesa_error(ctx, GL_INVALID_VALUE,
2357 "%s(offset %ld < 0)", func, (long) offset);
2358 return NULL;
2359 }
2360
2361 if (length < 0) {
2362 _mesa_error(ctx, GL_INVALID_VALUE,
2363 "%s(length %ld < 0)", func, (long) length);
2364 return NULL;
2365 }
2366
2367 /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
2368 *
2369 * "An INVALID_OPERATION error is generated for any of the following
2370 * conditions:
2371 *
2372 * * <length> is zero."
2373 *
2374 * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec
2375 * (30.10.2014) also says this, so it's no longer allowed for desktop GL,
2376 * either.
2377 */
2378 if (length == 0) {
2379 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func);
2380 return NULL;
2381 }
2382
2383 allowed_access = GL_MAP_READ_BIT |
2384 GL_MAP_WRITE_BIT |
2385 GL_MAP_INVALIDATE_RANGE_BIT |
2386 GL_MAP_INVALIDATE_BUFFER_BIT |
2387 GL_MAP_FLUSH_EXPLICIT_BIT |
2388 GL_MAP_UNSYNCHRONIZED_BIT;
2389
2390 if (ctx->Extensions.ARB_buffer_storage) {
2391 allowed_access |= GL_MAP_PERSISTENT_BIT |
2392 GL_MAP_COHERENT_BIT;
2393 }
2394
2395 if (access & ~allowed_access) {
2396 /* generate an error if any bits other than those allowed are set */
2397 _mesa_error(ctx, GL_INVALID_VALUE,
2398 "%s(access has undefined bits set)", func);
2399 return NULL;
2400 }
2401
2402 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
2403 _mesa_error(ctx, GL_INVALID_OPERATION,
2404 "%s(access indicates neither read or write)", func);
2405 return NULL;
2406 }
2407
2408 if ((access & GL_MAP_READ_BIT) &&
2409 (access & (GL_MAP_INVALIDATE_RANGE_BIT |
2410 GL_MAP_INVALIDATE_BUFFER_BIT |
2411 GL_MAP_UNSYNCHRONIZED_BIT))) {
2412 _mesa_error(ctx, GL_INVALID_OPERATION,
2413 "%s(read access with disallowed bits)", func);
2414 return NULL;
2415 }
2416
2417 if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
2418 ((access & GL_MAP_WRITE_BIT) == 0)) {
2419 _mesa_error(ctx, GL_INVALID_OPERATION,
2420 "%s(access has flush explicit without write)", func);
2421 return NULL;
2422 }
2423
2424 if (access & GL_MAP_READ_BIT &&
2425 !(bufObj->StorageFlags & GL_MAP_READ_BIT)) {
2426 _mesa_error(ctx, GL_INVALID_OPERATION,
2427 "%s(buffer does not allow read access)", func);
2428 return NULL;
2429 }
2430
2431 if (access & GL_MAP_WRITE_BIT &&
2432 !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) {
2433 _mesa_error(ctx, GL_INVALID_OPERATION,
2434 "%s(buffer does not allow write access)", func);
2435 return NULL;
2436 }
2437
2438 if (access & GL_MAP_COHERENT_BIT &&
2439 !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) {
2440 _mesa_error(ctx, GL_INVALID_OPERATION,
2441 "%s(buffer does not allow coherent access)", func);
2442 return NULL;
2443 }
2444
2445 if (access & GL_MAP_PERSISTENT_BIT &&
2446 !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) {
2447 _mesa_error(ctx, GL_INVALID_OPERATION,
2448 "%s(buffer does not allow persistent access)", func);
2449 return NULL;
2450 }
2451
2452 if (offset + length > bufObj->Size) {
2453 _mesa_error(ctx, GL_INVALID_VALUE,
2454 "%s(offset %td + length %td > buffer_size %td)", func,
2455 offset, length, bufObj->Size);
2456 return NULL;
2457 }
2458
2459 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
2460 _mesa_error(ctx, GL_INVALID_OPERATION,
2461 "%s(buffer already mapped)", func);
2462 return NULL;
2463 }
2464
2465 if (!bufObj->Size) {
2466 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
2467 return NULL;
2468 }
2469
2470 if (access & GL_MAP_WRITE_BIT) {
2471 bufObj->NumMapBufferWriteCalls++;
2472 if ((bufObj->Usage == GL_STATIC_DRAW ||
2473 bufObj->Usage == GL_STATIC_COPY) &&
2474 bufObj->NumMapBufferWriteCalls >= BUFFER_WARNING_CALL_COUNT) {
2475 BUFFER_USAGE_WARNING(ctx,
2476 "using %s(buffer %u, offset %u, length %u) to "
2477 "update a %s buffer",
2478 func, bufObj->Name, offset, length,
2479 _mesa_enum_to_string(bufObj->Usage));
2480 }
2481 }
2482
2483 assert(ctx->Driver.MapBufferRange);
2484 map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
2485 MAP_USER);
2486 if (!map) {
2487 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func);
2488 }
2489 else {
2490 /* The driver callback should have set all these fields.
2491 * This is important because other modules (like VBO) might call
2492 * the driver function directly.
2493 */
2494 assert(bufObj->Mappings[MAP_USER].Pointer == map);
2495 assert(bufObj->Mappings[MAP_USER].Length == length);
2496 assert(bufObj->Mappings[MAP_USER].Offset == offset);
2497 assert(bufObj->Mappings[MAP_USER].AccessFlags == access);
2498 }
2499
2500 if (access & GL_MAP_WRITE_BIT) {
2501 bufObj->Written = GL_TRUE;
2502 bufObj->MinMaxCacheDirty = true;
2503 }
2504
2505 #ifdef VBO_DEBUG
2506 if (strstr(func, "Range") == NULL) { /* If not MapRange */
2507 printf("glMapBuffer(%u, sz %ld, access 0x%x)\n",
2508 bufObj->Name, bufObj->Size, access);
2509 /* Access must be write only */
2510 if ((access & GL_MAP_WRITE_BIT) && (!(access & ~GL_MAP_WRITE_BIT))) {
2511 GLuint i;
2512 GLubyte *b = (GLubyte *) bufObj->Pointer;
2513 for (i = 0; i < bufObj->Size; i++)
2514 b[i] = i & 0xff;
2515 }
2516 }
2517 #endif
2518
2519 #ifdef BOUNDS_CHECK
2520 if (strstr(func, "Range") == NULL) { /* If not MapRange */
2521 GLubyte *buf = (GLubyte *) bufObj->Pointer;
2522 GLuint i;
2523 /* buffer is 100 bytes larger than requested, fill with magic value */
2524 for (i = 0; i < 100; i++) {
2525 buf[bufObj->Size - i - 1] = 123;
2526 }
2527 }
2528 #endif
2529
2530 return map;
2531 }
2532
2533 void * GLAPIENTRY
2534 _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
2535 GLbitfield access)
2536 {
2537 GET_CURRENT_CONTEXT(ctx);
2538 struct gl_buffer_object *bufObj;
2539
2540 if (!ctx->Extensions.ARB_map_buffer_range) {
2541 _mesa_error(ctx, GL_INVALID_OPERATION,
2542 "glMapBufferRange(ARB_map_buffer_range not supported)");
2543 return NULL;
2544 }
2545
2546 bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION);
2547 if (!bufObj)
2548 return NULL;
2549
2550 return _mesa_map_buffer_range(ctx, bufObj, offset, length, access,
2551 "glMapBufferRange");
2552 }
2553
2554 void * GLAPIENTRY
2555 _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
2556 GLbitfield access)
2557 {
2558 GET_CURRENT_CONTEXT(ctx);
2559 struct gl_buffer_object *bufObj;
2560
2561 if (!ctx->Extensions.ARB_map_buffer_range) {
2562 _mesa_error(ctx, GL_INVALID_OPERATION,
2563 "glMapNamedBufferRange("
2564 "ARB_map_buffer_range not supported)");
2565 return NULL;
2566 }
2567
2568 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBufferRange");
2569 if (!bufObj)
2570 return NULL;
2571
2572 return _mesa_map_buffer_range(ctx, bufObj, offset, length, access,
2573 "glMapNamedBufferRange");
2574 }
2575
2576 /**
2577 * Converts GLenum access from MapBuffer and MapNamedBuffer into
2578 * flags for input to _mesa_map_buffer_range.
2579 *
2580 * \return true if the type of requested access is permissible.
2581 */
2582 static bool
2583 get_map_buffer_access_flags(struct gl_context *ctx, GLenum access,
2584 GLbitfield *flags)
2585 {
2586 switch (access) {
2587 case GL_READ_ONLY_ARB:
2588 *flags = GL_MAP_READ_BIT;
2589 return _mesa_is_desktop_gl(ctx);
2590 case GL_WRITE_ONLY_ARB:
2591 *flags = GL_MAP_WRITE_BIT;
2592 return true;
2593 case GL_READ_WRITE_ARB:
2594 *flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
2595 return _mesa_is_desktop_gl(ctx);
2596 default:
2597 return false;
2598 }
2599 }
2600
2601 void * GLAPIENTRY
2602 _mesa_MapBuffer(GLenum target, GLenum access)
2603 {
2604 GET_CURRENT_CONTEXT(ctx);
2605 struct gl_buffer_object *bufObj;
2606 GLbitfield accessFlags;
2607
2608 if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
2609 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBuffer(invalid access)");
2610 return NULL;
2611 }
2612
2613 bufObj = get_buffer(ctx, "glMapBuffer", target, GL_INVALID_OPERATION);
2614 if (!bufObj)
2615 return NULL;
2616
2617 return _mesa_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
2618 "glMapBuffer");
2619 }
2620
2621 void * GLAPIENTRY
2622 _mesa_MapNamedBuffer(GLuint buffer, GLenum access)
2623 {
2624 GET_CURRENT_CONTEXT(ctx);
2625 struct gl_buffer_object *bufObj;
2626 GLbitfield accessFlags;
2627
2628 if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
2629 _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)");
2630 return NULL;
2631 }
2632
2633 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBuffer");
2634 if (!bufObj)
2635 return NULL;
2636
2637 return _mesa_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
2638 "glMapNamedBuffer");
2639 }
2640
2641
2642 void
2643 _mesa_flush_mapped_buffer_range(struct gl_context *ctx,
2644 struct gl_buffer_object *bufObj,
2645 GLintptr offset, GLsizeiptr length,
2646 const char *func)
2647 {
2648 if (!ctx->Extensions.ARB_map_buffer_range) {
2649 _mesa_error(ctx, GL_INVALID_OPERATION,
2650 "%s(ARB_map_buffer_range not supported)", func);
2651 return;
2652 }
2653
2654 if (offset < 0) {
2655 _mesa_error(ctx, GL_INVALID_VALUE,
2656 "%s(offset %ld < 0)", func, (long) offset);
2657 return;
2658 }
2659
2660 if (length < 0) {
2661 _mesa_error(ctx, GL_INVALID_VALUE,
2662 "%s(length %ld < 0)", func, (long) length);
2663 return;
2664 }
2665
2666 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
2667 /* buffer is not mapped */
2668 _mesa_error(ctx, GL_INVALID_OPERATION,
2669 "%s(buffer is not mapped)", func);
2670 return;
2671 }
2672
2673 if ((bufObj->Mappings[MAP_USER].AccessFlags &
2674 GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
2675 _mesa_error(ctx, GL_INVALID_OPERATION,
2676 "%s(GL_MAP_FLUSH_EXPLICIT_BIT not set)", func);
2677 return;
2678 }
2679
2680 if (offset + length > bufObj->Mappings[MAP_USER].Length) {
2681 _mesa_error(ctx, GL_INVALID_VALUE,
2682 "%s(offset %ld + length %ld > mapped length %ld)", func,
2683 (long) offset, (long) length,
2684 (long) bufObj->Mappings[MAP_USER].Length);
2685 return;
2686 }
2687
2688 assert(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT);
2689
2690 if (ctx->Driver.FlushMappedBufferRange)
2691 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
2692 MAP_USER);
2693 }
2694
2695 void GLAPIENTRY
2696 _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset,
2697 GLsizeiptr length)
2698 {
2699 GET_CURRENT_CONTEXT(ctx);
2700 struct gl_buffer_object *bufObj;
2701
2702 bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target,
2703 GL_INVALID_OPERATION);
2704 if (!bufObj)
2705 return;
2706
2707 _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length,
2708 "glFlushMappedBufferRange");
2709 }
2710
2711 void GLAPIENTRY
2712 _mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset,
2713 GLsizeiptr length)
2714 {
2715 GET_CURRENT_CONTEXT(ctx);
2716 struct gl_buffer_object *bufObj;
2717
2718 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2719 "glFlushMappedNamedBufferRange");
2720 if (!bufObj)
2721 return;
2722
2723 _mesa_flush_mapped_buffer_range(ctx, bufObj, offset, length,
2724 "glFlushMappedNamedBufferRange");
2725 }
2726
2727
2728 /**
2729 * Binds a buffer object to a uniform buffer binding point.
2730 *
2731 * The caller is responsible for flushing vertices and updating
2732 * NewDriverState.
2733 */
2734 static void
2735 set_ubo_binding(struct gl_context *ctx,
2736 struct gl_uniform_buffer_binding *binding,
2737 struct gl_buffer_object *bufObj,
2738 GLintptr offset,
2739 GLsizeiptr size,
2740 GLboolean autoSize)
2741 {
2742 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
2743
2744 binding->Offset = offset;
2745 binding->Size = size;
2746 binding->AutomaticSize = autoSize;
2747
2748 /* If this is a real buffer object, mark it has having been used
2749 * at some point as a UBO.
2750 */
2751 if (size >= 0)
2752 bufObj->UsageHistory |= USAGE_UNIFORM_BUFFER;
2753 }
2754
2755 /**
2756 * Binds a buffer object to a shader storage buffer binding point.
2757 *
2758 * The caller is responsible for flushing vertices and updating
2759 * NewDriverState.
2760 */
2761 static void
2762 set_ssbo_binding(struct gl_context *ctx,
2763 struct gl_shader_storage_buffer_binding *binding,
2764 struct gl_buffer_object *bufObj,
2765 GLintptr offset,
2766 GLsizeiptr size,
2767 GLboolean autoSize)
2768 {
2769 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
2770
2771 binding->Offset = offset;
2772 binding->Size = size;
2773 binding->AutomaticSize = autoSize;
2774
2775 /* If this is a real buffer object, mark it has having been used
2776 * at some point as a SSBO.
2777 */
2778 if (size >= 0)
2779 bufObj->UsageHistory |= USAGE_SHADER_STORAGE_BUFFER;
2780 }
2781
2782 /**
2783 * Binds a buffer object to a uniform buffer binding point.
2784 *
2785 * Unlike set_ubo_binding(), this function also flushes vertices
2786 * and updates NewDriverState. It also checks if the binding
2787 * has actually changed before updating it.
2788 */
2789 static void
2790 bind_uniform_buffer(struct gl_context *ctx,
2791 GLuint index,
2792 struct gl_buffer_object *bufObj,
2793 GLintptr offset,
2794 GLsizeiptr size,
2795 GLboolean autoSize)
2796 {
2797 struct gl_uniform_buffer_binding *binding =
2798 &ctx->UniformBufferBindings[index];
2799
2800 if (binding->BufferObject == bufObj &&
2801 binding->Offset == offset &&
2802 binding->Size == size &&
2803 binding->AutomaticSize == autoSize) {
2804 return;
2805 }
2806
2807 FLUSH_VERTICES(ctx, 0);
2808 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
2809
2810 set_ubo_binding(ctx, binding, bufObj, offset, size, autoSize);
2811 }
2812
2813 /**
2814 * Binds a buffer object to a shader storage buffer binding point.
2815 *
2816 * Unlike set_ssbo_binding(), this function also flushes vertices
2817 * and updates NewDriverState. It also checks if the binding
2818 * has actually changed before updating it.
2819 */
2820 static void
2821 bind_shader_storage_buffer(struct gl_context *ctx,
2822 GLuint index,
2823 struct gl_buffer_object *bufObj,
2824 GLintptr offset,
2825 GLsizeiptr size,
2826 GLboolean autoSize)
2827 {
2828 struct gl_shader_storage_buffer_binding *binding =
2829 &ctx->ShaderStorageBufferBindings[index];
2830
2831 if (binding->BufferObject == bufObj &&
2832 binding->Offset == offset &&
2833 binding->Size == size &&
2834 binding->AutomaticSize == autoSize) {
2835 return;
2836 }
2837
2838 FLUSH_VERTICES(ctx, 0);
2839 ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer;
2840
2841 set_ssbo_binding(ctx, binding, bufObj, offset, size, autoSize);
2842 }
2843
2844 /**
2845 * Bind a region of a buffer object to a uniform block binding point.
2846 * \param index the uniform buffer binding point index
2847 * \param bufObj the buffer object
2848 * \param offset offset to the start of buffer object region
2849 * \param size size of the buffer object region
2850 */
2851 static void
2852 bind_buffer_range_uniform_buffer(struct gl_context *ctx,
2853 GLuint index,
2854 struct gl_buffer_object *bufObj,
2855 GLintptr offset,
2856 GLsizeiptr size)
2857 {
2858 if (index >= ctx->Const.MaxUniformBufferBindings) {
2859 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
2860 return;
2861 }
2862
2863 if (offset & (ctx->Const.UniformBufferOffsetAlignment - 1)) {
2864 _mesa_error(ctx, GL_INVALID_VALUE,
2865 "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
2866 ctx->Const.UniformBufferOffsetAlignment);
2867 return;
2868 }
2869
2870 if (bufObj == ctx->Shared->NullBufferObj) {
2871 offset = -1;
2872 size = -1;
2873 }
2874
2875 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
2876 bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
2877 }
2878
2879 /**
2880 * Bind a region of a buffer object to a shader storage block binding point.
2881 * \param index the shader storage buffer binding point index
2882 * \param bufObj the buffer object
2883 * \param offset offset to the start of buffer object region
2884 * \param size size of the buffer object region
2885 */
2886 static void
2887 bind_buffer_range_shader_storage_buffer(struct gl_context *ctx,
2888 GLuint index,
2889 struct gl_buffer_object *bufObj,
2890 GLintptr offset,
2891 GLsizeiptr size)
2892 {
2893 if (index >= ctx->Const.MaxShaderStorageBufferBindings) {
2894 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
2895 return;
2896 }
2897
2898 if (offset & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) {
2899 _mesa_error(ctx, GL_INVALID_VALUE,
2900 "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
2901 ctx->Const.ShaderStorageBufferOffsetAlignment);
2902 return;
2903 }
2904
2905 if (bufObj == ctx->Shared->NullBufferObj) {
2906 offset = -1;
2907 size = -1;
2908 }
2909
2910 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
2911 bind_shader_storage_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
2912 }
2913
2914 /**
2915 * Bind a buffer object to a uniform block binding point.
2916 * As above, but offset = 0.
2917 */
2918 static void
2919 bind_buffer_base_uniform_buffer(struct gl_context *ctx,
2920 GLuint index,
2921 struct gl_buffer_object *bufObj)
2922 {
2923 if (index >= ctx->Const.MaxUniformBufferBindings) {
2924 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
2925 return;
2926 }
2927
2928 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
2929
2930 if (bufObj == ctx->Shared->NullBufferObj)
2931 bind_uniform_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
2932 else
2933 bind_uniform_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
2934 }
2935
2936 /**
2937 * Bind a buffer object to a shader storage block binding point.
2938 * As above, but offset = 0.
2939 */
2940 static void
2941 bind_buffer_base_shader_storage_buffer(struct gl_context *ctx,
2942 GLuint index,
2943 struct gl_buffer_object *bufObj)
2944 {
2945 if (index >= ctx->Const.MaxShaderStorageBufferBindings) {
2946 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
2947 return;
2948 }
2949
2950 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
2951
2952 if (bufObj == ctx->Shared->NullBufferObj)
2953 bind_shader_storage_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
2954 else
2955 bind_shader_storage_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
2956 }
2957
2958 /**
2959 * Binds a buffer object to an atomic buffer binding point.
2960 *
2961 * The caller is responsible for validating the offset,
2962 * flushing the vertices and updating NewDriverState.
2963 */
2964 static void
2965 set_atomic_buffer_binding(struct gl_context *ctx,
2966 struct gl_atomic_buffer_binding *binding,
2967 struct gl_buffer_object *bufObj,
2968 GLintptr offset,
2969 GLsizeiptr size)
2970 {
2971 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
2972
2973 if (bufObj == ctx->Shared->NullBufferObj) {
2974 binding->Offset = -1;
2975 binding->Size = -1;
2976 } else {
2977 binding->Offset = offset;
2978 binding->Size = size;
2979 bufObj->UsageHistory |= USAGE_ATOMIC_COUNTER_BUFFER;
2980 }
2981 }
2982
2983 /**
2984 * Binds a buffer object to an atomic buffer binding point.
2985 *
2986 * Unlike set_atomic_buffer_binding(), this function also validates the
2987 * index and offset, flushes vertices, and updates NewDriverState.
2988 * It also checks if the binding has actually changing before
2989 * updating it.
2990 */
2991 static void
2992 bind_atomic_buffer(struct gl_context *ctx,
2993 unsigned index,
2994 struct gl_buffer_object *bufObj,
2995 GLintptr offset,
2996 GLsizeiptr size,
2997 const char *name)
2998 {
2999 struct gl_atomic_buffer_binding *binding;
3000
3001 if (index >= ctx->Const.MaxAtomicBufferBindings) {
3002 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%d)", name, index);
3003 return;
3004 }
3005
3006 if (offset & (ATOMIC_COUNTER_SIZE - 1)) {
3007 _mesa_error(ctx, GL_INVALID_VALUE,
3008 "%s(offset misaligned %d/%d)", name, (int) offset,
3009 ATOMIC_COUNTER_SIZE);
3010 return;
3011 }
3012
3013 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
3014
3015 binding = &ctx->AtomicBufferBindings[index];
3016 if (binding->BufferObject == bufObj &&
3017 binding->Offset == offset &&
3018 binding->Size == size) {
3019 return;
3020 }
3021
3022 FLUSH_VERTICES(ctx, 0);
3023 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
3024
3025 set_atomic_buffer_binding(ctx, binding, bufObj, offset, size);
3026 }
3027
3028 static inline bool
3029 bind_buffers_check_offset_and_size(struct gl_context *ctx,
3030 GLuint index,
3031 const GLintptr *offsets,
3032 const GLsizeiptr *sizes)
3033 {
3034 if (offsets[index] < 0) {
3035 /* The ARB_multi_bind spec says:
3036 *
3037 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3038 * value in <offsets> is less than zero (per binding)."
3039 */
3040 _mesa_error(ctx, GL_INVALID_VALUE,
3041 "glBindBuffersRange(offsets[%u]=%" PRId64 " < 0)",
3042 index, (int64_t) offsets[index]);
3043 return false;
3044 }
3045
3046 if (sizes[index] <= 0) {
3047 /* The ARB_multi_bind spec says:
3048 *
3049 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3050 * value in <sizes> is less than or equal to zero (per binding)."
3051 */
3052 _mesa_error(ctx, GL_INVALID_VALUE,
3053 "glBindBuffersRange(sizes[%u]=%" PRId64 " <= 0)",
3054 index, (int64_t) sizes[index]);
3055 return false;
3056 }
3057
3058 return true;
3059 }
3060
3061 static bool
3062 error_check_bind_uniform_buffers(struct gl_context *ctx,
3063 GLuint first, GLsizei count,
3064 const char *caller)
3065 {
3066 if (!ctx->Extensions.ARB_uniform_buffer_object) {
3067 _mesa_error(ctx, GL_INVALID_ENUM,
3068 "%s(target=GL_UNIFORM_BUFFER)", caller);
3069 return false;
3070 }
3071
3072 /* The ARB_multi_bind_spec says:
3073 *
3074 * "An INVALID_OPERATION error is generated if <first> + <count> is
3075 * greater than the number of target-specific indexed binding points,
3076 * as described in section 6.7.1."
3077 */
3078 if (first + count > ctx->Const.MaxUniformBufferBindings) {
3079 _mesa_error(ctx, GL_INVALID_OPERATION,
3080 "%s(first=%u + count=%d > the value of "
3081 "GL_MAX_UNIFORM_BUFFER_BINDINGS=%u)",
3082 caller, first, count,
3083 ctx->Const.MaxUniformBufferBindings);
3084 return false;
3085 }
3086
3087 return true;
3088 }
3089
3090 static bool
3091 error_check_bind_shader_storage_buffers(struct gl_context *ctx,
3092 GLuint first, GLsizei count,
3093 const char *caller)
3094 {
3095 if (!ctx->Extensions.ARB_shader_storage_buffer_object) {
3096 _mesa_error(ctx, GL_INVALID_ENUM,
3097 "%s(target=GL_SHADER_STORAGE_BUFFER)", caller);
3098 return false;
3099 }
3100
3101 /* The ARB_multi_bind_spec says:
3102 *
3103 * "An INVALID_OPERATION error is generated if <first> + <count> is
3104 * greater than the number of target-specific indexed binding points,
3105 * as described in section 6.7.1."
3106 */
3107 if (first + count > ctx->Const.MaxShaderStorageBufferBindings) {
3108 _mesa_error(ctx, GL_INVALID_OPERATION,
3109 "%s(first=%u + count=%d > the value of "
3110 "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS=%u)",
3111 caller, first, count,
3112 ctx->Const.MaxShaderStorageBufferBindings);
3113 return false;
3114 }
3115
3116 return true;
3117 }
3118
3119 /**
3120 * Unbind all uniform buffers in the range
3121 * <first> through <first>+<count>-1
3122 */
3123 static void
3124 unbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
3125 {
3126 struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj;
3127 GLint i;
3128
3129 for (i = 0; i < count; i++)
3130 set_ubo_binding(ctx, &ctx->UniformBufferBindings[first + i],
3131 bufObj, -1, -1, GL_TRUE);
3132 }
3133
3134 /**
3135 * Unbind all shader storage buffers in the range
3136 * <first> through <first>+<count>-1
3137 */
3138 static void
3139 unbind_shader_storage_buffers(struct gl_context *ctx, GLuint first,
3140 GLsizei count)
3141 {
3142 struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj;
3143 GLint i;
3144
3145 for (i = 0; i < count; i++)
3146 set_ssbo_binding(ctx, &ctx->ShaderStorageBufferBindings[first + i],
3147 bufObj, -1, -1, GL_TRUE);
3148 }
3149
3150 static void
3151 bind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count,
3152 const GLuint *buffers,
3153 bool range,
3154 const GLintptr *offsets, const GLsizeiptr *sizes,
3155 const char *caller)
3156 {
3157 GLint i;
3158
3159 if (!error_check_bind_uniform_buffers(ctx, first, count, caller))
3160 return;
3161
3162 /* Assume that at least one binding will be changed */
3163 FLUSH_VERTICES(ctx, 0);
3164 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
3165
3166 if (!buffers) {
3167 /* The ARB_multi_bind spec says:
3168 *
3169 * "If <buffers> is NULL, all bindings from <first> through
3170 * <first>+<count>-1 are reset to their unbound (zero) state.
3171 * In this case, the offsets and sizes associated with the
3172 * binding points are set to default values, ignoring
3173 * <offsets> and <sizes>."
3174 */
3175 unbind_uniform_buffers(ctx, first, count);
3176 return;
3177 }
3178
3179 /* Note that the error semantics for multi-bind commands differ from
3180 * those of other GL commands.
3181 *
3182 * The Issues section in the ARB_multi_bind spec says:
3183 *
3184 * "(11) Typically, OpenGL specifies that if an error is generated by a
3185 * command, that command has no effect. This is somewhat
3186 * unfortunate for multi-bind commands, because it would require a
3187 * first pass to scan the entire list of bound objects for errors
3188 * and then a second pass to actually perform the bindings.
3189 * Should we have different error semantics?
3190 *
3191 * RESOLVED: Yes. In this specification, when the parameters for
3192 * one of the <count> binding points are invalid, that binding point
3193 * is not updated and an error will be generated. However, other
3194 * binding points in the same command will be updated if their
3195 * parameters are valid and no other error occurs."
3196 */
3197
3198 _mesa_begin_bufferobj_lookups(ctx);
3199
3200 for (i = 0; i < count; i++) {
3201 struct gl_uniform_buffer_binding *binding =
3202 &ctx->UniformBufferBindings[first + i];
3203 struct gl_buffer_object *bufObj;
3204 GLintptr offset = 0;
3205 GLsizeiptr size = 0;
3206
3207 if (range) {
3208 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
3209 continue;
3210
3211 /* The ARB_multi_bind spec says:
3212 *
3213 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3214 * pair of values in <offsets> and <sizes> does not respectively
3215 * satisfy the constraints described for those parameters for the
3216 * specified target, as described in section 6.7.1 (per binding)."
3217 *
3218 * Section 6.7.1 refers to table 6.5, which says:
3219 *
3220 * "┌───────────────────────────────────────────────────────────────┐
3221 * │ Uniform buffer array bindings (see sec. 7.6) │
3222 * ├─────────────────────┬─────────────────────────────────────────┤
3223 * │ ... │ ... │
3224 * │ offset restriction │ multiple of value of UNIFORM_BUFFER_- │
3225 * │ │ OFFSET_ALIGNMENT │
3226 * │ ... │ ... │
3227 * │ size restriction │ none │
3228 * └─────────────────────┴─────────────────────────────────────────┘"
3229 */
3230 if (offsets[i] & (ctx->Const.UniformBufferOffsetAlignment - 1)) {
3231 _mesa_error(ctx, GL_INVALID_VALUE,
3232 "glBindBuffersRange(offsets[%u]=%" PRId64
3233 " is misaligned; it must be a multiple of the value of "
3234 "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT=%u when "
3235 "target=GL_UNIFORM_BUFFER)",
3236 i, (int64_t) offsets[i],
3237 ctx->Const.UniformBufferOffsetAlignment);
3238 continue;
3239 }
3240
3241 offset = offsets[i];
3242 size = sizes[i];
3243 }
3244
3245 if (binding->BufferObject && binding->BufferObject->Name == buffers[i])
3246 bufObj = binding->BufferObject;
3247 else
3248 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller);
3249
3250 if (bufObj) {
3251 if (bufObj == ctx->Shared->NullBufferObj)
3252 set_ubo_binding(ctx, binding, bufObj, -1, -1, !range);
3253 else
3254 set_ubo_binding(ctx, binding, bufObj, offset, size, !range);
3255 }
3256 }
3257
3258 _mesa_end_bufferobj_lookups(ctx);
3259 }
3260
3261 static void
3262 bind_shader_storage_buffers(struct gl_context *ctx, GLuint first,
3263 GLsizei count, const GLuint *buffers,
3264 bool range,
3265 const GLintptr *offsets,
3266 const GLsizeiptr *sizes,
3267 const char *caller)
3268 {
3269 GLint i;
3270
3271 if (!error_check_bind_shader_storage_buffers(ctx, first, count, caller))
3272 return;
3273
3274 /* Assume that at least one binding will be changed */
3275 FLUSH_VERTICES(ctx, 0);
3276 ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer;
3277
3278 if (!buffers) {
3279 /* The ARB_multi_bind spec says:
3280 *
3281 * "If <buffers> is NULL, all bindings from <first> through
3282 * <first>+<count>-1 are reset to their unbound (zero) state.
3283 * In this case, the offsets and sizes associated with the
3284 * binding points are set to default values, ignoring
3285 * <offsets> and <sizes>."
3286 */
3287 unbind_shader_storage_buffers(ctx, first, count);
3288 return;
3289 }
3290
3291 /* Note that the error semantics for multi-bind commands differ from
3292 * those of other GL commands.
3293 *
3294 * The Issues section in the ARB_multi_bind spec says:
3295 *
3296 * "(11) Typically, OpenGL specifies that if an error is generated by a
3297 * command, that command has no effect. This is somewhat
3298 * unfortunate for multi-bind commands, because it would require a
3299 * first pass to scan the entire list of bound objects for errors
3300 * and then a second pass to actually perform the bindings.
3301 * Should we have different error semantics?
3302 *
3303 * RESOLVED: Yes. In this specification, when the parameters for
3304 * one of the <count> binding points are invalid, that binding point
3305 * is not updated and an error will be generated. However, other
3306 * binding points in the same command will be updated if their
3307 * parameters are valid and no other error occurs."
3308 */
3309
3310 _mesa_begin_bufferobj_lookups(ctx);
3311
3312 for (i = 0; i < count; i++) {
3313 struct gl_shader_storage_buffer_binding *binding =
3314 &ctx->ShaderStorageBufferBindings[first + i];
3315 struct gl_buffer_object *bufObj;
3316 GLintptr offset = 0;
3317 GLsizeiptr size = 0;
3318
3319 if (range) {
3320 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
3321 continue;
3322
3323 /* The ARB_multi_bind spec says:
3324 *
3325 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3326 * pair of values in <offsets> and <sizes> does not respectively
3327 * satisfy the constraints described for those parameters for the
3328 * specified target, as described in section 6.7.1 (per binding)."
3329 *
3330 * Section 6.7.1 refers to table 6.5, which says:
3331 *
3332 * "┌───────────────────────────────────────────────────────────────┐
3333 * │ Shader storage buffer array bindings (see sec. 7.8) │
3334 * ├─────────────────────┬─────────────────────────────────────────┤
3335 * │ ... │ ... │
3336 * │ offset restriction │ multiple of value of SHADER_STORAGE_- │
3337 * │ │ BUFFER_OFFSET_ALIGNMENT │
3338 * │ ... │ ... │
3339 * │ size restriction │ none │
3340 * └─────────────────────┴─────────────────────────────────────────┘"
3341 */
3342 if (offsets[i] & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) {
3343 _mesa_error(ctx, GL_INVALID_VALUE,
3344 "glBindBuffersRange(offsets[%u]=%" PRId64
3345 " is misaligned; it must be a multiple of the value of "
3346 "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT=%u when "
3347 "target=GL_SHADER_STORAGE_BUFFER)",
3348 i, (int64_t) offsets[i],
3349 ctx->Const.ShaderStorageBufferOffsetAlignment);
3350 continue;
3351 }
3352
3353 offset = offsets[i];
3354 size = sizes[i];
3355 }
3356
3357 if (binding->BufferObject && binding->BufferObject->Name == buffers[i])
3358 bufObj = binding->BufferObject;
3359 else
3360 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller);
3361
3362 if (bufObj) {
3363 if (bufObj == ctx->Shared->NullBufferObj)
3364 set_ssbo_binding(ctx, binding, bufObj, -1, -1, !range);
3365 else
3366 set_ssbo_binding(ctx, binding, bufObj, offset, size, !range);
3367 }
3368 }
3369
3370 _mesa_end_bufferobj_lookups(ctx);
3371 }
3372
3373 static bool
3374 error_check_bind_xfb_buffers(struct gl_context *ctx,
3375 struct gl_transform_feedback_object *tfObj,
3376 GLuint first, GLsizei count, const char *caller)
3377 {
3378 if (!ctx->Extensions.EXT_transform_feedback) {
3379 _mesa_error(ctx, GL_INVALID_ENUM,
3380 "%s(target=GL_TRANSFORM_FEEDBACK_BUFFER)", caller);
3381 return false;
3382 }
3383
3384 /* Page 398 of the PDF of the OpenGL 4.4 (Core Profile) spec says:
3385 *
3386 * "An INVALID_OPERATION error is generated :
3387 *
3388 * ...
3389 * • by BindBufferRange or BindBufferBase if target is TRANSFORM_-
3390 * FEEDBACK_BUFFER and transform feedback is currently active."
3391 *
3392 * We assume that this is also meant to apply to BindBuffersRange
3393 * and BindBuffersBase.
3394 */
3395 if (tfObj->Active) {
3396 _mesa_error(ctx, GL_INVALID_OPERATION,
3397 "%s(Changing transform feedback buffers while "
3398 "transform feedback is active)", caller);
3399 return false;
3400 }
3401
3402 /* The ARB_multi_bind_spec says:
3403 *
3404 * "An INVALID_OPERATION error is generated if <first> + <count> is
3405 * greater than the number of target-specific indexed binding points,
3406 * as described in section 6.7.1."
3407 */
3408 if (first + count > ctx->Const.MaxTransformFeedbackBuffers) {
3409 _mesa_error(ctx, GL_INVALID_OPERATION,
3410 "%s(first=%u + count=%d > the value of "
3411 "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS=%u)",
3412 caller, first, count,
3413 ctx->Const.MaxTransformFeedbackBuffers);
3414 return false;
3415 }
3416
3417 return true;
3418 }
3419
3420 /**
3421 * Unbind all transform feedback buffers in the range
3422 * <first> through <first>+<count>-1
3423 */
3424 static void
3425 unbind_xfb_buffers(struct gl_context *ctx,
3426 struct gl_transform_feedback_object *tfObj,
3427 GLuint first, GLsizei count)
3428 {
3429 struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj;
3430 GLint i;
3431
3432 for (i = 0; i < count; i++)
3433 _mesa_set_transform_feedback_binding(ctx, tfObj, first + i,
3434 bufObj, 0, 0);
3435 }
3436
3437 static void
3438 bind_xfb_buffers(struct gl_context *ctx,
3439 GLuint first, GLsizei count,
3440 const GLuint *buffers,
3441 bool range,
3442 const GLintptr *offsets,
3443 const GLsizeiptr *sizes,
3444 const char *caller)
3445 {
3446 struct gl_transform_feedback_object *tfObj =
3447 ctx->TransformFeedback.CurrentObject;
3448 GLint i;
3449
3450 if (!error_check_bind_xfb_buffers(ctx, tfObj, first, count, caller))
3451 return;
3452
3453 /* Assume that at least one binding will be changed */
3454 FLUSH_VERTICES(ctx, 0);
3455 ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback;
3456
3457 if (!buffers) {
3458 /* The ARB_multi_bind spec says:
3459 *
3460 * "If <buffers> is NULL, all bindings from <first> through
3461 * <first>+<count>-1 are reset to their unbound (zero) state.
3462 * In this case, the offsets and sizes associated with the
3463 * binding points are set to default values, ignoring
3464 * <offsets> and <sizes>."
3465 */
3466 unbind_xfb_buffers(ctx, tfObj, first, count);
3467 return;
3468 }
3469
3470 /* Note that the error semantics for multi-bind commands differ from
3471 * those of other GL commands.
3472 *
3473 * The Issues section in the ARB_multi_bind spec says:
3474 *
3475 * "(11) Typically, OpenGL specifies that if an error is generated by a
3476 * command, that command has no effect. This is somewhat
3477 * unfortunate for multi-bind commands, because it would require a
3478 * first pass to scan the entire list of bound objects for errors
3479 * and then a second pass to actually perform the bindings.
3480 * Should we have different error semantics?
3481 *
3482 * RESOLVED: Yes. In this specification, when the parameters for
3483 * one of the <count> binding points are invalid, that binding point
3484 * is not updated and an error will be generated. However, other
3485 * binding points in the same command will be updated if their
3486 * parameters are valid and no other error occurs."
3487 */
3488
3489 _mesa_begin_bufferobj_lookups(ctx);
3490
3491 for (i = 0; i < count; i++) {
3492 const GLuint index = first + i;
3493 struct gl_buffer_object * const boundBufObj = tfObj->Buffers[index];
3494 struct gl_buffer_object *bufObj;
3495 GLintptr offset = 0;
3496 GLsizeiptr size = 0;
3497
3498 if (range) {
3499 offset = offsets[i];
3500 size = sizes[i];
3501
3502 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
3503 continue;
3504
3505 /* The ARB_multi_bind spec says:
3506 *
3507 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3508 * pair of values in <offsets> and <sizes> does not respectively
3509 * satisfy the constraints described for those parameters for the
3510 * specified target, as described in section 6.7.1 (per binding)."
3511 *
3512 * Section 6.7.1 refers to table 6.5, which says:
3513 *
3514 * "┌───────────────────────────────────────────────────────────────┐
3515 * │ Transform feedback array bindings (see sec. 13.2.2) │
3516 * ├───────────────────────┬───────────────────────────────────────┤
3517 * │ ... │ ... │
3518 * │ offset restriction │ multiple of 4 │
3519 * │ ... │ ... │
3520 * │ size restriction │ multiple of 4 │
3521 * └───────────────────────┴───────────────────────────────────────┘"
3522 */
3523 if (offsets[i] & 0x3) {
3524 _mesa_error(ctx, GL_INVALID_VALUE,
3525 "glBindBuffersRange(offsets[%u]=%" PRId64
3526 " is misaligned; it must be a multiple of 4 when "
3527 "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
3528 i, (int64_t) offsets[i]);
3529 continue;
3530 }
3531
3532 if (sizes[i] & 0x3) {
3533 _mesa_error(ctx, GL_INVALID_VALUE,
3534 "glBindBuffersRange(sizes[%u]=%" PRId64
3535 " is misaligned; it must be a multiple of 4 when "
3536 "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
3537 i, (int64_t) sizes[i]);
3538 continue;
3539 }
3540
3541 offset = offsets[i];
3542 size = sizes[i];
3543 }
3544
3545 if (boundBufObj && boundBufObj->Name == buffers[i])
3546 bufObj = boundBufObj;
3547 else
3548 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller);
3549
3550 if (bufObj)
3551 _mesa_set_transform_feedback_binding(ctx, tfObj, index, bufObj,
3552 offset, size);
3553 }
3554
3555 _mesa_end_bufferobj_lookups(ctx);
3556 }
3557
3558 static bool
3559 error_check_bind_atomic_buffers(struct gl_context *ctx,
3560 GLuint first, GLsizei count,
3561 const char *caller)
3562 {
3563 if (!ctx->Extensions.ARB_shader_atomic_counters) {
3564 _mesa_error(ctx, GL_INVALID_ENUM,
3565 "%s(target=GL_ATOMIC_COUNTER_BUFFER)", caller);
3566 return false;
3567 }
3568
3569 /* The ARB_multi_bind_spec says:
3570 *
3571 * "An INVALID_OPERATION error is generated if <first> + <count> is
3572 * greater than the number of target-specific indexed binding points,
3573 * as described in section 6.7.1."
3574 */
3575 if (first + count > ctx->Const.MaxAtomicBufferBindings) {
3576 _mesa_error(ctx, GL_INVALID_OPERATION,
3577 "%s(first=%u + count=%d > the value of "
3578 "GL_MAX_ATOMIC_BUFFER_BINDINGS=%u)",
3579 caller, first, count, ctx->Const.MaxAtomicBufferBindings);
3580 return false;
3581 }
3582
3583 return true;
3584 }
3585
3586 /**
3587 * Unbind all atomic counter buffers in the range
3588 * <first> through <first>+<count>-1
3589 */
3590 static void
3591 unbind_atomic_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
3592 {
3593 struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj;
3594 GLint i;
3595
3596 for (i = 0; i < count; i++)
3597 set_atomic_buffer_binding(ctx, &ctx->AtomicBufferBindings[first + i],
3598 bufObj, -1, -1);
3599 }
3600
3601 static void
3602 bind_atomic_buffers(struct gl_context *ctx,
3603 GLuint first,
3604 GLsizei count,
3605 const GLuint *buffers,
3606 bool range,
3607 const GLintptr *offsets,
3608 const GLsizeiptr *sizes,
3609 const char *caller)
3610 {
3611 GLint i;
3612
3613 if (!error_check_bind_atomic_buffers(ctx, first, count, caller))
3614 return;
3615
3616 /* Assume that at least one binding will be changed */
3617 FLUSH_VERTICES(ctx, 0);
3618 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
3619
3620 if (!buffers) {
3621 /* The ARB_multi_bind spec says:
3622 *
3623 * "If <buffers> is NULL, all bindings from <first> through
3624 * <first>+<count>-1 are reset to their unbound (zero) state.
3625 * In this case, the offsets and sizes associated with the
3626 * binding points are set to default values, ignoring
3627 * <offsets> and <sizes>."
3628 */
3629 unbind_atomic_buffers(ctx, first, count);
3630 return;
3631 }
3632
3633 /* Note that the error semantics for multi-bind commands differ from
3634 * those of other GL commands.
3635 *
3636 * The Issues section in the ARB_multi_bind spec says:
3637 *
3638 * "(11) Typically, OpenGL specifies that if an error is generated by a
3639 * command, that command has no effect. This is somewhat
3640 * unfortunate for multi-bind commands, because it would require a
3641 * first pass to scan the entire list of bound objects for errors
3642 * and then a second pass to actually perform the bindings.
3643 * Should we have different error semantics?
3644 *
3645 * RESOLVED: Yes. In this specification, when the parameters for
3646 * one of the <count> binding points are invalid, that binding point
3647 * is not updated and an error will be generated. However, other
3648 * binding points in the same command will be updated if their
3649 * parameters are valid and no other error occurs."
3650 */
3651
3652 _mesa_begin_bufferobj_lookups(ctx);
3653
3654 for (i = 0; i < count; i++) {
3655 struct gl_atomic_buffer_binding *binding =
3656 &ctx->AtomicBufferBindings[first + i];
3657 struct gl_buffer_object *bufObj;
3658 GLintptr offset = 0;
3659 GLsizeiptr size = 0;
3660
3661 if (range) {
3662 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
3663 continue;
3664
3665 /* The ARB_multi_bind spec says:
3666 *
3667 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3668 * pair of values in <offsets> and <sizes> does not respectively
3669 * satisfy the constraints described for those parameters for the
3670 * specified target, as described in section 6.7.1 (per binding)."
3671 *
3672 * Section 6.7.1 refers to table 6.5, which says:
3673 *
3674 * "┌───────────────────────────────────────────────────────────────┐
3675 * │ Atomic counter array bindings (see sec. 7.7.2) │
3676 * ├───────────────────────┬───────────────────────────────────────┤
3677 * │ ... │ ... │
3678 * │ offset restriction │ multiple of 4 │
3679 * │ ... │ ... │
3680 * │ size restriction │ none │
3681 * └───────────────────────┴───────────────────────────────────────┘"
3682 */
3683 if (offsets[i] & (ATOMIC_COUNTER_SIZE - 1)) {
3684 _mesa_error(ctx, GL_INVALID_VALUE,
3685 "glBindBuffersRange(offsets[%u]=%" PRId64
3686 " is misaligned; it must be a multiple of %d when "
3687 "target=GL_ATOMIC_COUNTER_BUFFER)",
3688 i, (int64_t) offsets[i], ATOMIC_COUNTER_SIZE);
3689 continue;
3690 }
3691
3692 offset = offsets[i];
3693 size = sizes[i];
3694 }
3695
3696 if (binding->BufferObject && binding->BufferObject->Name == buffers[i])
3697 bufObj = binding->BufferObject;
3698 else
3699 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller);
3700
3701 if (bufObj)
3702 set_atomic_buffer_binding(ctx, binding, bufObj, offset, size);
3703 }
3704
3705 _mesa_end_bufferobj_lookups(ctx);
3706 }
3707
3708 void GLAPIENTRY
3709 _mesa_BindBufferRange(GLenum target, GLuint index,
3710 GLuint buffer, GLintptr offset, GLsizeiptr size)
3711 {
3712 GET_CURRENT_CONTEXT(ctx);
3713 struct gl_buffer_object *bufObj;
3714
3715 if (MESA_VERBOSE & VERBOSE_API) {
3716 _mesa_debug(ctx, "glBindBufferRange(%s, %u, %u, %ld, %ld)\n",
3717 _mesa_enum_to_string(target), index, buffer, offset, size);
3718 }
3719
3720 if (buffer == 0) {
3721 bufObj = ctx->Shared->NullBufferObj;
3722 } else {
3723 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3724 }
3725 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
3726 &bufObj, "glBindBufferRange"))
3727 return;
3728
3729 if (!bufObj) {
3730 _mesa_error(ctx, GL_INVALID_OPERATION,
3731 "glBindBufferRange(invalid buffer=%u)", buffer);
3732 return;
3733 }
3734
3735 if (buffer != 0) {
3736 if (size <= 0) {
3737 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)",
3738 (int) size);
3739 return;
3740 }
3741 }
3742
3743 switch (target) {
3744 case GL_TRANSFORM_FEEDBACK_BUFFER:
3745 _mesa_bind_buffer_range_transform_feedback(ctx,
3746 ctx->TransformFeedback.CurrentObject,
3747 index, bufObj, offset, size,
3748 false);
3749 return;
3750 case GL_UNIFORM_BUFFER:
3751 bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
3752 return;
3753 case GL_SHADER_STORAGE_BUFFER:
3754 bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size);
3755 return;
3756 case GL_ATOMIC_COUNTER_BUFFER:
3757 bind_atomic_buffer(ctx, index, bufObj, offset, size,
3758 "glBindBufferRange");
3759 return;
3760 default:
3761 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
3762 return;
3763 }
3764 }
3765
3766 void GLAPIENTRY
3767 _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
3768 {
3769 GET_CURRENT_CONTEXT(ctx);
3770 struct gl_buffer_object *bufObj;
3771
3772 if (MESA_VERBOSE & VERBOSE_API) {
3773 _mesa_debug(ctx, "glBindBufferBase(%s, %u, %u)\n",
3774 _mesa_enum_to_string(target), index, buffer);
3775 }
3776
3777 if (buffer == 0) {
3778 bufObj = ctx->Shared->NullBufferObj;
3779 } else {
3780 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3781 }
3782 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
3783 &bufObj, "glBindBufferBase"))
3784 return;
3785
3786 if (!bufObj) {
3787 _mesa_error(ctx, GL_INVALID_OPERATION,
3788 "glBindBufferBase(invalid buffer=%u)", buffer);
3789 return;
3790 }
3791
3792 /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with
3793 * regards to BindBufferBase. It says (GL 3.1 core spec, page 63):
3794 *
3795 * "BindBufferBase is equivalent to calling BindBufferRange with offset
3796 * zero and size equal to the size of buffer."
3797 *
3798 * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230):
3799 *
3800 * "If the parameter (starting offset or size) was not specified when the
3801 * buffer object was bound, zero is returned."
3802 *
3803 * What happens if the size of the buffer changes? Does the size of the
3804 * buffer at the moment glBindBufferBase was called still play a role, like
3805 * the first quote would imply, or is the size meaningless in the
3806 * glBindBufferBase case like the second quote would suggest? The GL 4.1
3807 * core spec page 45 says:
3808 *
3809 * "It is equivalent to calling BindBufferRange with offset zero, while
3810 * size is determined by the size of the bound buffer at the time the
3811 * binding is used."
3812 *
3813 * My interpretation is that the GL 4.1 spec was a clarification of the
3814 * behavior, not a change. In particular, this choice will only make
3815 * rendering work in cases where it would have had undefined results.
3816 */
3817
3818 switch (target) {
3819 case GL_TRANSFORM_FEEDBACK_BUFFER:
3820 _mesa_bind_buffer_base_transform_feedback(ctx,
3821 ctx->TransformFeedback.CurrentObject,
3822 index, bufObj, false);
3823 return;
3824 case GL_UNIFORM_BUFFER:
3825 bind_buffer_base_uniform_buffer(ctx, index, bufObj);
3826 return;
3827 case GL_SHADER_STORAGE_BUFFER:
3828 bind_buffer_base_shader_storage_buffer(ctx, index, bufObj);
3829 return;
3830 case GL_ATOMIC_COUNTER_BUFFER:
3831 bind_atomic_buffer(ctx, index, bufObj, 0, 0,
3832 "glBindBufferBase");
3833 return;
3834 default:
3835 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
3836 return;
3837 }
3838 }
3839
3840 void GLAPIENTRY
3841 _mesa_BindBuffersRange(GLenum target, GLuint first, GLsizei count,
3842 const GLuint *buffers,
3843 const GLintptr *offsets, const GLsizeiptr *sizes)
3844 {
3845 GET_CURRENT_CONTEXT(ctx);
3846
3847 if (MESA_VERBOSE & VERBOSE_API) {
3848 _mesa_debug(ctx, "glBindBuffersRange(%s, %u, %d, %p, %p, %p)\n",
3849 _mesa_enum_to_string(target), first, count,
3850 buffers, offsets, sizes);
3851 }
3852
3853 switch (target) {
3854 case GL_TRANSFORM_FEEDBACK_BUFFER:
3855 bind_xfb_buffers(ctx, first, count, buffers, true, offsets, sizes,
3856 "glBindBuffersRange");
3857 return;
3858 case GL_UNIFORM_BUFFER:
3859 bind_uniform_buffers(ctx, first, count, buffers, true, offsets, sizes,
3860 "glBindBuffersRange");
3861 return;
3862 case GL_SHADER_STORAGE_BUFFER:
3863 bind_shader_storage_buffers(ctx, first, count, buffers, true, offsets, sizes,
3864 "glBindBuffersRange");
3865 return;
3866 case GL_ATOMIC_COUNTER_BUFFER:
3867 bind_atomic_buffers(ctx, first, count, buffers, true, offsets, sizes,
3868 "glBindBuffersRange");
3869 return;
3870 default:
3871 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersRange(target=%s)",
3872 _mesa_enum_to_string(target));
3873 break;
3874 }
3875 }
3876
3877 void GLAPIENTRY
3878 _mesa_BindBuffersBase(GLenum target, GLuint first, GLsizei count,
3879 const GLuint *buffers)
3880 {
3881 GET_CURRENT_CONTEXT(ctx);
3882
3883 if (MESA_VERBOSE & VERBOSE_API) {
3884 _mesa_debug(ctx, "glBindBuffersBase(%s, %u, %d, %p)\n",
3885 _mesa_enum_to_string(target), first, count, buffers);
3886 }
3887
3888 switch (target) {
3889 case GL_TRANSFORM_FEEDBACK_BUFFER:
3890 bind_xfb_buffers(ctx, first, count, buffers, false, NULL, NULL,
3891 "glBindBuffersBase");
3892 return;
3893 case GL_UNIFORM_BUFFER:
3894 bind_uniform_buffers(ctx, first, count, buffers, false, NULL, NULL,
3895 "glBindBuffersBase");
3896 return;
3897 case GL_SHADER_STORAGE_BUFFER:
3898 bind_shader_storage_buffers(ctx, first, count, buffers, false, NULL, NULL,
3899 "glBindBuffersBase");
3900 return;
3901 case GL_ATOMIC_COUNTER_BUFFER:
3902 bind_atomic_buffers(ctx, first, count, buffers, false, NULL, NULL,
3903 "glBindBuffersBase");
3904 return;
3905 default:
3906 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersBase(target=%s)",
3907 _mesa_enum_to_string(target));
3908 break;
3909 }
3910 }
3911
3912 void GLAPIENTRY
3913 _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset,
3914 GLsizeiptr length)
3915 {
3916 GET_CURRENT_CONTEXT(ctx);
3917 struct gl_buffer_object *bufObj;
3918 const GLintptr end = offset + length;
3919
3920 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
3921 * Profile) spec says:
3922 *
3923 * "An INVALID_VALUE error is generated if buffer is zero or is not the
3924 * name of an existing buffer object."
3925 */
3926 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3927 if (!bufObj || bufObj == &DummyBufferObject) {
3928 _mesa_error(ctx, GL_INVALID_VALUE,
3929 "glInvalidateBufferSubData(name = 0x%x) invalid object",
3930 buffer);
3931 return;
3932 }
3933
3934 /* The GL_ARB_invalidate_subdata spec says:
3935 *
3936 * "An INVALID_VALUE error is generated if <offset> or <length> is
3937 * negative, or if <offset> + <length> is greater than the value of
3938 * BUFFER_SIZE."
3939 */
3940 if (offset < 0 || length < 0 || end > bufObj->Size) {
3941 _mesa_error(ctx, GL_INVALID_VALUE,
3942 "glInvalidateBufferSubData(invalid offset or length)");
3943 return;
3944 }
3945
3946 /* The OpenGL 4.4 (Core Profile) spec says:
3947 *
3948 * "An INVALID_OPERATION error is generated if buffer is currently
3949 * mapped by MapBuffer or if the invalidate range intersects the range
3950 * currently mapped by MapBufferRange, unless it was mapped
3951 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
3952 */
3953 if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) &&
3954 bufferobj_range_mapped(bufObj, offset, length)) {
3955 _mesa_error(ctx, GL_INVALID_OPERATION,
3956 "glInvalidateBufferSubData(intersection with mapped "
3957 "range)");
3958 return;
3959 }
3960
3961 if (ctx->Driver.InvalidateBufferSubData)
3962 ctx->Driver.InvalidateBufferSubData(ctx, bufObj, offset, length);
3963 }
3964
3965 void GLAPIENTRY
3966 _mesa_InvalidateBufferData(GLuint buffer)
3967 {
3968 GET_CURRENT_CONTEXT(ctx);
3969 struct gl_buffer_object *bufObj;
3970
3971 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
3972 * Profile) spec says:
3973 *
3974 * "An INVALID_VALUE error is generated if buffer is zero or is not the
3975 * name of an existing buffer object."
3976 */
3977 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3978 if (!bufObj || bufObj == &DummyBufferObject) {
3979 _mesa_error(ctx, GL_INVALID_VALUE,
3980 "glInvalidateBufferData(name = 0x%x) invalid object",
3981 buffer);
3982 return;
3983 }
3984
3985 /* The OpenGL 4.4 (Core Profile) spec says:
3986 *
3987 * "An INVALID_OPERATION error is generated if buffer is currently
3988 * mapped by MapBuffer or if the invalidate range intersects the range
3989 * currently mapped by MapBufferRange, unless it was mapped
3990 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
3991 */
3992 if (_mesa_check_disallowed_mapping(bufObj)) {
3993 _mesa_error(ctx, GL_INVALID_OPERATION,
3994 "glInvalidateBufferData(intersection with mapped "
3995 "range)");
3996 return;
3997 }
3998
3999 if (ctx->Driver.InvalidateBufferSubData)
4000 ctx->Driver.InvalidateBufferSubData(ctx, bufObj, 0, bufObj->Size);
4001 }