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