glthread: track instance divisor changes
[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 "context.h"
40 #include "bufferobj.h"
41 #include "externalobjects.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 #include "util/u_atomic.h"
49 #include "util/u_memory.h"
50
51
52 /* Debug flags */
53 /*#define VBO_DEBUG*/
54 /*#define BOUNDS_CHECK*/
55
56
57 /**
58 * We count the number of buffer modification calls to check for
59 * inefficient buffer use. This is the number of such calls before we
60 * issue a warning.
61 */
62 #define BUFFER_WARNING_CALL_COUNT 4
63
64
65 /**
66 * Helper to warn of possible performance issues, such as frequently
67 * updating a buffer created with GL_STATIC_DRAW. Called via the macro
68 * below.
69 */
70 static void
71 buffer_usage_warning(struct gl_context *ctx, GLuint *id, const char *fmt, ...)
72 {
73 va_list args;
74
75 va_start(args, fmt);
76 _mesa_gl_vdebugf(ctx, id,
77 MESA_DEBUG_SOURCE_API,
78 MESA_DEBUG_TYPE_PERFORMANCE,
79 MESA_DEBUG_SEVERITY_MEDIUM,
80 fmt, args);
81 va_end(args);
82 }
83
84 #define BUFFER_USAGE_WARNING(CTX, FMT, ...) \
85 do { \
86 static GLuint id = 0; \
87 buffer_usage_warning(CTX, &id, FMT, ##__VA_ARGS__); \
88 } while (0)
89
90
91 /**
92 * Used as a placeholder for buffer objects between glGenBuffers() and
93 * glBindBuffer() so that glIsBuffer() can work correctly.
94 */
95 static struct gl_buffer_object DummyBufferObject;
96
97
98 /**
99 * Return pointer to address of a buffer object target.
100 * \param ctx the GL context
101 * \param target the buffer object target to be retrieved.
102 * \return pointer to pointer to the buffer object bound to \c target in the
103 * specified context or \c NULL if \c target is invalid.
104 */
105 static inline struct gl_buffer_object **
106 get_buffer_target(struct gl_context *ctx, GLenum target)
107 {
108 /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0. */
109 if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) {
110 switch (target) {
111 case GL_ARRAY_BUFFER:
112 case GL_ELEMENT_ARRAY_BUFFER:
113 break;
114 case GL_PIXEL_PACK_BUFFER:
115 case GL_PIXEL_UNPACK_BUFFER:
116 if (!ctx->Extensions.EXT_pixel_buffer_object)
117 return NULL;
118 break;
119 default:
120 return NULL;
121 }
122 }
123
124 switch (target) {
125 case GL_ARRAY_BUFFER_ARB:
126 if (ctx->Array.ArrayBufferObj)
127 ctx->Array.ArrayBufferObj->UsageHistory |= USAGE_ARRAY_BUFFER;
128 return &ctx->Array.ArrayBufferObj;
129 case GL_ELEMENT_ARRAY_BUFFER_ARB:
130 if (ctx->Array.VAO->IndexBufferObj)
131 ctx->Array.VAO->IndexBufferObj->UsageHistory
132 |= USAGE_ELEMENT_ARRAY_BUFFER;
133 return &ctx->Array.VAO->IndexBufferObj;
134 case GL_PIXEL_PACK_BUFFER_EXT:
135 return &ctx->Pack.BufferObj;
136 case GL_PIXEL_UNPACK_BUFFER_EXT:
137 return &ctx->Unpack.BufferObj;
138 case GL_COPY_READ_BUFFER:
139 return &ctx->CopyReadBuffer;
140 case GL_COPY_WRITE_BUFFER:
141 return &ctx->CopyWriteBuffer;
142 case GL_QUERY_BUFFER:
143 if (_mesa_has_ARB_query_buffer_object(ctx))
144 return &ctx->QueryBuffer;
145 break;
146 case GL_DRAW_INDIRECT_BUFFER:
147 if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_draw_indirect) ||
148 _mesa_is_gles31(ctx)) {
149 return &ctx->DrawIndirectBuffer;
150 }
151 break;
152 case GL_PARAMETER_BUFFER_ARB:
153 if (_mesa_has_ARB_indirect_parameters(ctx)) {
154 return &ctx->ParameterBuffer;
155 }
156 break;
157 case GL_DISPATCH_INDIRECT_BUFFER:
158 if (_mesa_has_compute_shaders(ctx)) {
159 return &ctx->DispatchIndirectBuffer;
160 }
161 break;
162 case GL_TRANSFORM_FEEDBACK_BUFFER:
163 if (ctx->Extensions.EXT_transform_feedback) {
164 return &ctx->TransformFeedback.CurrentBuffer;
165 }
166 break;
167 case GL_TEXTURE_BUFFER:
168 if (_mesa_has_ARB_texture_buffer_object(ctx) ||
169 _mesa_has_OES_texture_buffer(ctx)) {
170 return &ctx->Texture.BufferObject;
171 }
172 break;
173 case GL_UNIFORM_BUFFER:
174 if (ctx->Extensions.ARB_uniform_buffer_object) {
175 return &ctx->UniformBuffer;
176 }
177 break;
178 case GL_SHADER_STORAGE_BUFFER:
179 if (ctx->Extensions.ARB_shader_storage_buffer_object) {
180 return &ctx->ShaderStorageBuffer;
181 }
182 break;
183 case GL_ATOMIC_COUNTER_BUFFER:
184 if (ctx->Extensions.ARB_shader_atomic_counters) {
185 return &ctx->AtomicBuffer;
186 }
187 break;
188 case GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD:
189 if (ctx->Extensions.AMD_pinned_memory) {
190 return &ctx->ExternalVirtualMemoryBuffer;
191 }
192 break;
193 default:
194 return NULL;
195 }
196 return NULL;
197 }
198
199
200 /**
201 * Get the buffer object bound to the specified target in a GL context.
202 * \param ctx the GL context
203 * \param target the buffer object target to be retrieved.
204 * \param error the GL error to record if target is illegal.
205 * \return pointer to the buffer object bound to \c target in the
206 * specified context or \c NULL if \c target is invalid.
207 */
208 static inline struct gl_buffer_object *
209 get_buffer(struct gl_context *ctx, const char *func, GLenum target,
210 GLenum error)
211 {
212 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
213
214 if (!bufObj) {
215 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
216 return NULL;
217 }
218
219 if (!*bufObj) {
220 _mesa_error(ctx, error, "%s(no buffer bound)", func);
221 return NULL;
222 }
223
224 return *bufObj;
225 }
226
227
228 /**
229 * Convert a GLbitfield describing the mapped buffer access flags
230 * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
231 */
232 static GLenum
233 simplified_access_mode(struct gl_context *ctx, GLbitfield access)
234 {
235 const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
236 if ((access & rwFlags) == rwFlags)
237 return GL_READ_WRITE;
238 if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
239 return GL_READ_ONLY;
240 if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
241 return GL_WRITE_ONLY;
242
243 /* Otherwise, AccessFlags is zero (the default state).
244 *
245 * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says:
246 *
247 * Name Type Initial Value Legal Values
248 * ... ... ... ...
249 * BUFFER_ACCESS enum READ_WRITE READ_ONLY, WRITE_ONLY
250 * READ_WRITE
251 *
252 * However, table 6.8 in the GL_OES_mapbuffer extension says:
253 *
254 * Get Value Type Get Command Value Description
255 * --------- ---- ----------- ----- -----------
256 * BUFFER_ACCESS_OES Z1 GetBufferParameteriv WRITE_ONLY_OES buffer map flag
257 *
258 * The difference is because GL_OES_mapbuffer only supports mapping buffers
259 * write-only.
260 */
261 assert(access == 0);
262
263 return _mesa_is_gles(ctx) ? GL_WRITE_ONLY : GL_READ_WRITE;
264 }
265
266
267 /**
268 * Test if the buffer is mapped, and if so, if the mapped range overlaps the
269 * given range.
270 * The regions do not overlap if and only if the end of the given
271 * region is before the mapped region or the start of the given region
272 * is after the mapped region.
273 *
274 * \param obj Buffer object target on which to operate.
275 * \param offset Offset of the first byte of the subdata range.
276 * \param size Size, in bytes, of the subdata range.
277 * \return true if ranges overlap, false otherwise
278 *
279 */
280 static bool
281 bufferobj_range_mapped(const struct gl_buffer_object *obj,
282 GLintptr offset, GLsizeiptr size)
283 {
284 if (_mesa_bufferobj_mapped(obj, MAP_USER)) {
285 const GLintptr end = offset + size;
286 const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset +
287 obj->Mappings[MAP_USER].Length;
288
289 if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) {
290 return true;
291 }
292 }
293 return false;
294 }
295
296
297 /**
298 * Tests the subdata range parameters and sets the GL error code for
299 * \c glBufferSubDataARB, \c glGetBufferSubDataARB and
300 * \c glClearBufferSubData.
301 *
302 * \param ctx GL context.
303 * \param bufObj The buffer object.
304 * \param offset Offset of the first byte of the subdata range.
305 * \param size Size, in bytes, of the subdata range.
306 * \param mappedRange If true, checks if an overlapping range is mapped.
307 * If false, checks if buffer is mapped.
308 * \param caller Name of calling function for recording errors.
309 * \return false if error, true otherwise
310 *
311 * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData
312 */
313 static bool
314 buffer_object_subdata_range_good(struct gl_context *ctx,
315 const struct gl_buffer_object *bufObj,
316 GLintptr offset, GLsizeiptr size,
317 bool mappedRange, const char *caller)
318 {
319 if (size < 0) {
320 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
321 return false;
322 }
323
324 if (offset < 0) {
325 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
326 return false;
327 }
328
329 if (offset + size > bufObj->Size) {
330 _mesa_error(ctx, GL_INVALID_VALUE,
331 "%s(offset %lu + size %lu > buffer size %lu)", caller,
332 (unsigned long) offset,
333 (unsigned long) size,
334 (unsigned long) bufObj->Size);
335 return false;
336 }
337
338 if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT)
339 return true;
340
341 if (mappedRange) {
342 if (bufferobj_range_mapped(bufObj, offset, size)) {
343 _mesa_error(ctx, GL_INVALID_OPERATION,
344 "%s(range is mapped without persistent bit)",
345 caller);
346 return false;
347 }
348 }
349 else {
350 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
351 _mesa_error(ctx, GL_INVALID_OPERATION,
352 "%s(buffer is mapped without persistent bit)",
353 caller);
354 return false;
355 }
356 }
357
358 return true;
359 }
360
361
362 /**
363 * Test the format and type parameters and set the GL error code for
364 * \c glClearBufferData, \c glClearNamedBufferData, \c glClearBufferSubData
365 * and \c glClearNamedBufferSubData.
366 *
367 * \param ctx GL context.
368 * \param internalformat Format to which the data is to be converted.
369 * \param format Format of the supplied data.
370 * \param type Type of the supplied data.
371 * \param caller Name of calling function for recording errors.
372 * \return If internalformat, format and type are legal the mesa_format
373 * corresponding to internalformat, otherwise MESA_FORMAT_NONE.
374 *
375 * \sa glClearBufferData, glClearNamedBufferData, glClearBufferSubData and
376 * glClearNamedBufferSubData.
377 */
378 static mesa_format
379 validate_clear_buffer_format(struct gl_context *ctx,
380 GLenum internalformat,
381 GLenum format, GLenum type,
382 const char *caller)
383 {
384 mesa_format mesaFormat;
385 GLenum errorFormatType;
386
387 mesaFormat = _mesa_validate_texbuffer_format(ctx, internalformat);
388 if (mesaFormat == MESA_FORMAT_NONE) {
389 _mesa_error(ctx, GL_INVALID_ENUM,
390 "%s(invalid internalformat)", caller);
391 return MESA_FORMAT_NONE;
392 }
393
394 /* NOTE: not mentioned in ARB_clear_buffer_object but according to
395 * EXT_texture_integer there is no conversion between integer and
396 * non-integer formats
397 */
398 if (_mesa_is_enum_format_signed_int(format) !=
399 _mesa_is_format_integer_color(mesaFormat)) {
400 _mesa_error(ctx, GL_INVALID_OPERATION,
401 "%s(integer vs non-integer)", caller);
402 return MESA_FORMAT_NONE;
403 }
404
405 if (!_mesa_is_color_format(format)) {
406 _mesa_error(ctx, GL_INVALID_VALUE,
407 "%s(format is not a color format)", caller);
408 return MESA_FORMAT_NONE;
409 }
410
411 errorFormatType = _mesa_error_check_format_and_type(ctx, format, type);
412 if (errorFormatType != GL_NO_ERROR) {
413 _mesa_error(ctx, GL_INVALID_VALUE,
414 "%s(invalid format or type)", caller);
415 return MESA_FORMAT_NONE;
416 }
417
418 return mesaFormat;
419 }
420
421
422 /**
423 * Convert user-specified clear value to the specified internal format.
424 *
425 * \param ctx GL context.
426 * \param internalformat Format to which the data is converted.
427 * \param clearValue Points to the converted clear value.
428 * \param format Format of the supplied data.
429 * \param type Type of the supplied data.
430 * \param data Data which is to be converted to internalformat.
431 * \param caller Name of calling function for recording errors.
432 * \return true if data could be converted, false otherwise.
433 *
434 * \sa glClearBufferData, glClearBufferSubData
435 */
436 static bool
437 convert_clear_buffer_data(struct gl_context *ctx,
438 mesa_format internalformat,
439 GLubyte *clearValue, GLenum format, GLenum type,
440 const GLvoid *data, const char *caller)
441 {
442 GLenum internalformatBase = _mesa_get_format_base_format(internalformat);
443
444 if (_mesa_texstore(ctx, 1, internalformatBase, internalformat,
445 0, &clearValue, 1, 1, 1,
446 format, type, data, &ctx->Unpack)) {
447 return true;
448 }
449 else {
450 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
451 return false;
452 }
453 }
454
455
456 /**
457 * Allocate and initialize a new buffer object.
458 *
459 * Default callback for the \c dd_function_table::NewBufferObject() hook.
460 */
461 static struct gl_buffer_object *
462 _mesa_new_buffer_object(struct gl_context *ctx, GLuint name)
463 {
464 struct gl_buffer_object *obj = MALLOC_STRUCT(gl_buffer_object);
465 if (!obj)
466 return NULL;
467
468 _mesa_initialize_buffer_object(ctx, obj, name);
469 return obj;
470 }
471
472
473 /**
474 * Delete a buffer object.
475 *
476 * Default callback for the \c dd_function_table::DeleteBuffer() hook.
477 */
478 void
479 _mesa_delete_buffer_object(struct gl_context *ctx,
480 struct gl_buffer_object *bufObj)
481 {
482 (void) ctx;
483
484 vbo_delete_minmax_cache(bufObj);
485 align_free(bufObj->Data);
486
487 /* assign strange values here to help w/ debugging */
488 bufObj->RefCount = -1000;
489 bufObj->Name = ~0;
490
491 simple_mtx_destroy(&bufObj->MinMaxCacheMutex);
492 free(bufObj->Label);
493 free(bufObj);
494 }
495
496
497
498 /**
499 * Set ptr to bufObj w/ reference counting.
500 * This is normally only called from the _mesa_reference_buffer_object() macro
501 * when there's a real pointer change.
502 */
503 void
504 _mesa_reference_buffer_object_(struct gl_context *ctx,
505 struct gl_buffer_object **ptr,
506 struct gl_buffer_object *bufObj)
507 {
508 if (*ptr) {
509 /* Unreference the old buffer */
510 struct gl_buffer_object *oldObj = *ptr;
511
512 if (p_atomic_dec_zero(&oldObj->RefCount)) {
513 assert(ctx->Driver.DeleteBuffer);
514 ctx->Driver.DeleteBuffer(ctx, oldObj);
515 }
516
517 *ptr = NULL;
518 }
519 assert(!*ptr);
520
521 if (bufObj) {
522 /* reference new buffer */
523 p_atomic_inc(&bufObj->RefCount);
524 *ptr = bufObj;
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 obj->RefCount = 1;
557 obj->Name = name;
558 obj->Usage = GL_STATIC_DRAW_ARB;
559
560 simple_mtx_init(&obj->MinMaxCacheMutex, mtx_plain);
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, GLsizeiptrARB 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 align_free( bufObj->Data );
626
627 new_data = 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, GLintptrARB offset,
664 GLsizeiptrARB 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 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 simple_mtx_init(&DummyBufferObject.MinMaxCacheMutex, mtx_plain);
880 DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */
881
882 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
883 _mesa_reference_buffer_object(ctx,
884 &ctx->UniformBufferBindings[i].BufferObject,
885 NULL);
886 ctx->UniformBufferBindings[i].Offset = -1;
887 ctx->UniformBufferBindings[i].Size = -1;
888 }
889
890 for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) {
891 _mesa_reference_buffer_object(ctx,
892 &ctx->ShaderStorageBufferBindings[i].BufferObject,
893 NULL);
894 ctx->ShaderStorageBufferBindings[i].Offset = -1;
895 ctx->ShaderStorageBufferBindings[i].Size = -1;
896 }
897
898 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) {
899 _mesa_reference_buffer_object(ctx,
900 &ctx->AtomicBufferBindings[i].BufferObject,
901 NULL);
902 ctx->AtomicBufferBindings[i].Offset = 0;
903 ctx->AtomicBufferBindings[i].Size = 0;
904 }
905 }
906
907
908 void
909 _mesa_free_buffer_objects( struct gl_context *ctx )
910 {
911 GLuint i;
912
913 _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
914
915 _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL);
916 _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL);
917
918 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL);
919
920 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, NULL);
921
922 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, NULL);
923
924 _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, NULL);
925
926 _mesa_reference_buffer_object(ctx, &ctx->ParameterBuffer, NULL);
927
928 _mesa_reference_buffer_object(ctx, &ctx->DispatchIndirectBuffer, NULL);
929
930 _mesa_reference_buffer_object(ctx, &ctx->QueryBuffer, NULL);
931
932 for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
933 _mesa_reference_buffer_object(ctx,
934 &ctx->UniformBufferBindings[i].BufferObject,
935 NULL);
936 }
937
938 for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) {
939 _mesa_reference_buffer_object(ctx,
940 &ctx->ShaderStorageBufferBindings[i].BufferObject,
941 NULL);
942 }
943
944 for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) {
945 _mesa_reference_buffer_object(ctx,
946 &ctx->AtomicBufferBindings[i].BufferObject,
947 NULL);
948 }
949
950 }
951
952 bool
953 _mesa_handle_bind_buffer_gen(struct gl_context *ctx,
954 GLuint buffer,
955 struct gl_buffer_object **buf_handle,
956 const char *caller)
957 {
958 struct gl_buffer_object *buf = *buf_handle;
959
960 if (!buf && (ctx->API == API_OPENGL_CORE)) {
961 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller);
962 return false;
963 }
964
965 if (!buf || buf == &DummyBufferObject) {
966 /* If this is a new buffer object id, or one which was generated but
967 * never used before, allocate a buffer object now.
968 */
969 buf = ctx->Driver.NewBufferObject(ctx, buffer);
970 if (!buf) {
971 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
972 return false;
973 }
974 _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf);
975 *buf_handle = buf;
976 }
977
978 return true;
979 }
980
981 /**
982 * Bind the specified target to buffer for the specified context.
983 * Called by glBindBuffer() and other functions.
984 */
985 static void
986 bind_buffer_object(struct gl_context *ctx,
987 struct gl_buffer_object **bindTarget, GLuint buffer)
988 {
989 struct gl_buffer_object *oldBufObj;
990 struct gl_buffer_object *newBufObj = NULL;
991
992 assert(bindTarget);
993
994 /* Get pointer to old buffer object (to be unbound) */
995 oldBufObj = *bindTarget;
996 if ((oldBufObj && oldBufObj->Name == buffer && !oldBufObj->DeletePending) ||
997 (!oldBufObj && buffer == 0))
998 return; /* rebinding the same buffer object- no change */
999
1000 /*
1001 * Get pointer to new buffer object (newBufObj)
1002 */
1003 if (buffer != 0) {
1004 /* non-default buffer object */
1005 newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
1006 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
1007 &newBufObj, "glBindBuffer"))
1008 return;
1009
1010 /* record usage history */
1011 if (bindTarget == &ctx->Pack.BufferObj)
1012 newBufObj->UsageHistory |= USAGE_PIXEL_PACK_BUFFER;
1013 }
1014
1015 /* bind new buffer */
1016 _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
1017 }
1018
1019
1020 /**
1021 * Update the default buffer objects in the given context to reference those
1022 * specified in the shared state and release those referencing the old
1023 * shared state.
1024 */
1025 void
1026 _mesa_update_default_objects_buffer_objects(struct gl_context *ctx)
1027 {
1028 /* Bind 0 to remove references to those in the shared context hash table. */
1029 bind_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 0);
1030 bind_buffer_object(ctx, &ctx->Array.VAO->IndexBufferObj, 0);
1031 bind_buffer_object(ctx, &ctx->Pack.BufferObj, 0);
1032 bind_buffer_object(ctx, &ctx->Unpack.BufferObj, 0);
1033 }
1034
1035
1036
1037 /**
1038 * Return the gl_buffer_object for the given ID.
1039 * Always return NULL for ID 0.
1040 */
1041 struct gl_buffer_object *
1042 _mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer)
1043 {
1044 if (buffer == 0)
1045 return NULL;
1046 else
1047 return (struct gl_buffer_object *)
1048 _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
1049 }
1050
1051
1052 struct gl_buffer_object *
1053 _mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer)
1054 {
1055 if (buffer == 0)
1056 return NULL;
1057 else
1058 return (struct gl_buffer_object *)
1059 _mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer);
1060 }
1061
1062 /**
1063 * A convenience function for direct state access functions that throws
1064 * GL_INVALID_OPERATION if buffer is not the name of an existing
1065 * buffer object.
1066 */
1067 struct gl_buffer_object *
1068 _mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer,
1069 const char *caller)
1070 {
1071 struct gl_buffer_object *bufObj;
1072
1073 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1074 if (!bufObj || bufObj == &DummyBufferObject) {
1075 _mesa_error(ctx, GL_INVALID_OPERATION,
1076 "%s(non-existent buffer object %u)", caller, buffer);
1077 return NULL;
1078 }
1079
1080 return bufObj;
1081 }
1082
1083
1084 /**
1085 * Look up a buffer object for a multi-bind function.
1086 *
1087 * Unlike _mesa_lookup_bufferobj(), this function also takes care
1088 * of generating an error if the buffer ID is not zero or the name
1089 * of an existing buffer object.
1090 *
1091 * If the buffer ID refers to an existing buffer object, a pointer
1092 * to the buffer object is returned. If the ID is zero, NULL is returned.
1093 * If the ID is not zero and does not refer to a valid buffer object, this
1094 * function returns NULL.
1095 *
1096 * This function assumes that the caller has already locked the
1097 * hash table mutex by calling
1098 * _mesa_HashLockMutex(ctx->Shared->BufferObjects).
1099 */
1100 struct gl_buffer_object *
1101 _mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx,
1102 const GLuint *buffers,
1103 GLuint index, const char *caller,
1104 bool *error)
1105 {
1106 struct gl_buffer_object *bufObj = NULL;
1107
1108 *error = false;
1109
1110 if (buffers[index] != 0) {
1111 bufObj = _mesa_lookup_bufferobj_locked(ctx, buffers[index]);
1112
1113 /* The multi-bind functions don't create the buffer objects
1114 when they don't exist. */
1115 if (bufObj == &DummyBufferObject)
1116 bufObj = NULL;
1117
1118 if (!bufObj) {
1119 /* The ARB_multi_bind spec says:
1120 *
1121 * "An INVALID_OPERATION error is generated if any value
1122 * in <buffers> is not zero or the name of an existing
1123 * buffer object (per binding)."
1124 */
1125 _mesa_error(ctx, GL_INVALID_OPERATION,
1126 "%s(buffers[%u]=%u is not zero or the name "
1127 "of an existing buffer object)",
1128 caller, index, buffers[index]);
1129 *error = true;
1130 }
1131 }
1132
1133 return bufObj;
1134 }
1135
1136
1137 /**
1138 * If *ptr points to obj, set ptr = the Null/default buffer object.
1139 * This is a helper for buffer object deletion.
1140 * The GL spec says that deleting a buffer object causes it to get
1141 * unbound from all arrays in the current context.
1142 */
1143 static void
1144 unbind(struct gl_context *ctx,
1145 struct gl_vertex_array_object *vao, unsigned index,
1146 struct gl_buffer_object *obj)
1147 {
1148 if (vao->BufferBinding[index].BufferObj == obj) {
1149 _mesa_bind_vertex_buffer(ctx, vao, index, NULL,
1150 vao->BufferBinding[index].Offset,
1151 vao->BufferBinding[index].Stride, true, false);
1152 }
1153 }
1154
1155
1156 /**
1157 * Plug default/fallback buffer object functions into the device
1158 * driver hooks.
1159 */
1160 void
1161 _mesa_init_buffer_object_functions(struct dd_function_table *driver)
1162 {
1163 /* GL_ARB_vertex/pixel_buffer_object */
1164 driver->NewBufferObject = _mesa_new_buffer_object;
1165 driver->DeleteBuffer = _mesa_delete_buffer_object;
1166 driver->BufferData = buffer_data_fallback;
1167 driver->BufferSubData = buffer_sub_data_fallback;
1168 driver->GetBufferSubData = buffer_get_subdata;
1169 driver->UnmapBuffer = unmap_buffer_fallback;
1170
1171 /* GL_ARB_clear_buffer_object */
1172 driver->ClearBufferSubData = _mesa_ClearBufferSubData_sw;
1173
1174 /* GL_ARB_map_buffer_range */
1175 driver->MapBufferRange = map_buffer_range_fallback;
1176 driver->FlushMappedBufferRange = flush_mapped_buffer_range_fallback;
1177
1178 /* GL_ARB_copy_buffer */
1179 driver->CopyBufferSubData = copy_buffer_sub_data_fallback;
1180 }
1181
1182
1183 void
1184 _mesa_buffer_unmap_all_mappings(struct gl_context *ctx,
1185 struct gl_buffer_object *bufObj)
1186 {
1187 for (int i = 0; i < MAP_COUNT; i++) {
1188 if (_mesa_bufferobj_mapped(bufObj, i)) {
1189 ctx->Driver.UnmapBuffer(ctx, bufObj, i);
1190 assert(bufObj->Mappings[i].Pointer == NULL);
1191 bufObj->Mappings[i].AccessFlags = 0;
1192 }
1193 }
1194 }
1195
1196
1197 /**********************************************************************/
1198 /* API Functions */
1199 /**********************************************************************/
1200
1201 void GLAPIENTRY
1202 _mesa_BindBuffer_no_error(GLenum target, GLuint buffer)
1203 {
1204 GET_CURRENT_CONTEXT(ctx);
1205
1206 struct gl_buffer_object **bindTarget = get_buffer_target(ctx, target);
1207 bind_buffer_object(ctx, bindTarget, buffer);
1208 }
1209
1210
1211 void GLAPIENTRY
1212 _mesa_BindBuffer(GLenum target, GLuint buffer)
1213 {
1214 GET_CURRENT_CONTEXT(ctx);
1215
1216 if (MESA_VERBOSE & VERBOSE_API) {
1217 _mesa_debug(ctx, "glBindBuffer(%s, %u)\n",
1218 _mesa_enum_to_string(target), buffer);
1219 }
1220
1221 struct gl_buffer_object **bindTarget = get_buffer_target(ctx, target);
1222 if (!bindTarget) {
1223 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target %s)",
1224 _mesa_enum_to_string(target));
1225 return;
1226 }
1227
1228 bind_buffer_object(ctx, bindTarget, buffer);
1229 }
1230
1231 void
1232 _mesa_InternalBindElementBuffer(struct gl_context *ctx,
1233 struct gl_buffer_object *buf)
1234 {
1235 struct gl_buffer_object **bindTarget =
1236 get_buffer_target(ctx, GL_ELEMENT_ARRAY_BUFFER);
1237
1238 /* Move the buffer reference from the parameter to the bind point. */
1239 _mesa_reference_buffer_object(ctx, bindTarget, NULL);
1240 if (buf)
1241 *bindTarget = buf;
1242 }
1243
1244 /**
1245 * Binds a buffer object to a binding point.
1246 *
1247 * The caller is responsible for validating the offset,
1248 * flushing the vertices and updating NewDriverState.
1249 */
1250 static void
1251 set_buffer_binding(struct gl_context *ctx,
1252 struct gl_buffer_binding *binding,
1253 struct gl_buffer_object *bufObj,
1254 GLintptr offset,
1255 GLsizeiptr size,
1256 bool autoSize, gl_buffer_usage usage)
1257 {
1258 _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
1259
1260 binding->Offset = offset;
1261 binding->Size = size;
1262 binding->AutomaticSize = autoSize;
1263
1264 /* If this is a real buffer object, mark it has having been used
1265 * at some point as an atomic counter buffer.
1266 */
1267 if (size >= 0)
1268 bufObj->UsageHistory |= usage;
1269 }
1270
1271 static void
1272 set_buffer_multi_binding(struct gl_context *ctx,
1273 const GLuint *buffers,
1274 int idx,
1275 const char *caller,
1276 struct gl_buffer_binding *binding,
1277 GLintptr offset,
1278 GLsizeiptr size,
1279 bool range,
1280 gl_buffer_usage usage)
1281 {
1282 struct gl_buffer_object *bufObj;
1283
1284 if (binding->BufferObject && binding->BufferObject->Name == buffers[idx])
1285 bufObj = binding->BufferObject;
1286 else {
1287 bool error;
1288 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, idx, caller,
1289 &error);
1290 if (error)
1291 return;
1292 }
1293
1294 if (!bufObj)
1295 set_buffer_binding(ctx, binding, bufObj, -1, -1, !range, usage);
1296 else
1297 set_buffer_binding(ctx, binding, bufObj, offset, size, !range, usage);
1298 }
1299
1300 static void
1301 bind_buffer(struct gl_context *ctx,
1302 struct gl_buffer_binding *binding,
1303 struct gl_buffer_object *bufObj,
1304 GLintptr offset,
1305 GLsizeiptr size,
1306 GLboolean autoSize,
1307 uint64_t driver_state,
1308 gl_buffer_usage usage)
1309 {
1310 if (binding->BufferObject == bufObj &&
1311 binding->Offset == offset &&
1312 binding->Size == size &&
1313 binding->AutomaticSize == autoSize) {
1314 return;
1315 }
1316
1317 FLUSH_VERTICES(ctx, 0);
1318 ctx->NewDriverState |= driver_state;
1319
1320 set_buffer_binding(ctx, binding, bufObj, offset, size, autoSize, usage);
1321 }
1322
1323 /**
1324 * Binds a buffer object to a uniform buffer binding point.
1325 *
1326 * Unlike set_buffer_binding(), this function also flushes vertices
1327 * and updates NewDriverState. It also checks if the binding
1328 * has actually changed before updating it.
1329 */
1330 static void
1331 bind_uniform_buffer(struct gl_context *ctx,
1332 GLuint index,
1333 struct gl_buffer_object *bufObj,
1334 GLintptr offset,
1335 GLsizeiptr size,
1336 GLboolean autoSize)
1337 {
1338 bind_buffer(ctx, &ctx->UniformBufferBindings[index],
1339 bufObj, offset, size, autoSize,
1340 ctx->DriverFlags.NewUniformBuffer,
1341 USAGE_UNIFORM_BUFFER);
1342 }
1343
1344 /**
1345 * Binds a buffer object to a shader storage buffer binding point.
1346 *
1347 * Unlike set_ssbo_binding(), this function also flushes vertices
1348 * and updates NewDriverState. It also checks if the binding
1349 * has actually changed before updating it.
1350 */
1351 static void
1352 bind_shader_storage_buffer(struct gl_context *ctx,
1353 GLuint index,
1354 struct gl_buffer_object *bufObj,
1355 GLintptr offset,
1356 GLsizeiptr size,
1357 GLboolean autoSize)
1358 {
1359 bind_buffer(ctx, &ctx->ShaderStorageBufferBindings[index],
1360 bufObj, offset, size, autoSize,
1361 ctx->DriverFlags.NewShaderStorageBuffer,
1362 USAGE_SHADER_STORAGE_BUFFER);
1363 }
1364
1365 /**
1366 * Binds a buffer object to an atomic buffer binding point.
1367 *
1368 * Unlike set_atomic_binding(), this function also flushes vertices
1369 * and updates NewDriverState. It also checks if the binding
1370 * has actually changed before updating it.
1371 */
1372 static void
1373 bind_atomic_buffer(struct gl_context *ctx, unsigned index,
1374 struct gl_buffer_object *bufObj, GLintptr offset,
1375 GLsizeiptr size, GLboolean autoSize)
1376 {
1377 bind_buffer(ctx, &ctx->AtomicBufferBindings[index],
1378 bufObj, offset, size, autoSize,
1379 ctx->DriverFlags.NewAtomicBuffer,
1380 USAGE_ATOMIC_COUNTER_BUFFER);
1381 }
1382
1383 /**
1384 * Bind a buffer object to a uniform block binding point.
1385 * As above, but offset = 0.
1386 */
1387 static void
1388 bind_buffer_base_uniform_buffer(struct gl_context *ctx,
1389 GLuint index,
1390 struct gl_buffer_object *bufObj)
1391 {
1392 if (index >= ctx->Const.MaxUniformBufferBindings) {
1393 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
1394 return;
1395 }
1396
1397 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
1398
1399 if (!bufObj)
1400 bind_uniform_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
1401 else
1402 bind_uniform_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
1403 }
1404
1405 /**
1406 * Bind a buffer object to a shader storage block binding point.
1407 * As above, but offset = 0.
1408 */
1409 static void
1410 bind_buffer_base_shader_storage_buffer(struct gl_context *ctx,
1411 GLuint index,
1412 struct gl_buffer_object *bufObj)
1413 {
1414 if (index >= ctx->Const.MaxShaderStorageBufferBindings) {
1415 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
1416 return;
1417 }
1418
1419 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
1420
1421 if (!bufObj)
1422 bind_shader_storage_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
1423 else
1424 bind_shader_storage_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
1425 }
1426
1427 /**
1428 * Bind a buffer object to a shader storage block binding point.
1429 * As above, but offset = 0.
1430 */
1431 static void
1432 bind_buffer_base_atomic_buffer(struct gl_context *ctx,
1433 GLuint index,
1434 struct gl_buffer_object *bufObj)
1435 {
1436 if (index >= ctx->Const.MaxAtomicBufferBindings) {
1437 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
1438 return;
1439 }
1440
1441 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
1442
1443 if (!bufObj)
1444 bind_atomic_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
1445 else
1446 bind_atomic_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
1447 }
1448
1449 /**
1450 * Delete a set of buffer objects.
1451 *
1452 * \param n Number of buffer objects to delete.
1453 * \param ids Array of \c n buffer object IDs.
1454 */
1455 static void
1456 delete_buffers(struct gl_context *ctx, GLsizei n, const GLuint *ids)
1457 {
1458 FLUSH_VERTICES(ctx, 0);
1459
1460 _mesa_HashLockMutex(ctx->Shared->BufferObjects);
1461
1462 for (GLsizei i = 0; i < n; i++) {
1463 struct gl_buffer_object *bufObj =
1464 _mesa_lookup_bufferobj_locked(ctx, ids[i]);
1465 if (bufObj) {
1466 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1467 GLuint j;
1468
1469 assert(bufObj->Name == ids[i] || bufObj == &DummyBufferObject);
1470
1471 _mesa_buffer_unmap_all_mappings(ctx, bufObj);
1472
1473 /* unbind any vertex pointers bound to this buffer */
1474 for (j = 0; j < ARRAY_SIZE(vao->BufferBinding); j++) {
1475 unbind(ctx, vao, j, bufObj);
1476 }
1477
1478 if (ctx->Array.ArrayBufferObj == bufObj) {
1479 bind_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 0);
1480 }
1481 if (vao->IndexBufferObj == bufObj) {
1482 bind_buffer_object(ctx, &vao->IndexBufferObj, 0);
1483 }
1484
1485 /* unbind ARB_draw_indirect binding point */
1486 if (ctx->DrawIndirectBuffer == bufObj) {
1487 bind_buffer_object(ctx, &ctx->DrawIndirectBuffer, 0);
1488 }
1489
1490 /* unbind ARB_indirect_parameters binding point */
1491 if (ctx->ParameterBuffer == bufObj) {
1492 bind_buffer_object(ctx, &ctx->ParameterBuffer, 0);
1493 }
1494
1495 /* unbind ARB_compute_shader binding point */
1496 if (ctx->DispatchIndirectBuffer == bufObj) {
1497 bind_buffer_object(ctx, &ctx->DispatchIndirectBuffer, 0);
1498 }
1499
1500 /* unbind ARB_copy_buffer binding points */
1501 if (ctx->CopyReadBuffer == bufObj) {
1502 bind_buffer_object(ctx, &ctx->CopyReadBuffer, 0);
1503 }
1504 if (ctx->CopyWriteBuffer == bufObj) {
1505 bind_buffer_object(ctx, &ctx->CopyWriteBuffer, 0);
1506 }
1507
1508 /* unbind transform feedback binding points */
1509 if (ctx->TransformFeedback.CurrentBuffer == bufObj) {
1510 bind_buffer_object(ctx, &ctx->TransformFeedback.CurrentBuffer, 0);
1511 }
1512 for (j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
1513 if (ctx->TransformFeedback.CurrentObject->Buffers[j] == bufObj) {
1514 _mesa_bind_buffer_base_transform_feedback(ctx,
1515 ctx->TransformFeedback.CurrentObject,
1516 j, NULL, false);
1517 }
1518 }
1519
1520 /* unbind UBO binding points */
1521 for (j = 0; j < ctx->Const.MaxUniformBufferBindings; j++) {
1522 if (ctx->UniformBufferBindings[j].BufferObject == bufObj) {
1523 bind_buffer_base_uniform_buffer(ctx, j, NULL);
1524 }
1525 }
1526
1527 if (ctx->UniformBuffer == bufObj) {
1528 bind_buffer_object(ctx, &ctx->UniformBuffer, 0);
1529 }
1530
1531 /* unbind SSBO binding points */
1532 for (j = 0; j < ctx->Const.MaxShaderStorageBufferBindings; j++) {
1533 if (ctx->ShaderStorageBufferBindings[j].BufferObject == bufObj) {
1534 bind_buffer_base_shader_storage_buffer(ctx, j, NULL);
1535 }
1536 }
1537
1538 if (ctx->ShaderStorageBuffer == bufObj) {
1539 bind_buffer_object(ctx, &ctx->ShaderStorageBuffer, 0);
1540 }
1541
1542 /* unbind Atomci Buffer binding points */
1543 for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) {
1544 if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) {
1545 bind_buffer_base_atomic_buffer(ctx, j, NULL);
1546 }
1547 }
1548
1549 if (ctx->AtomicBuffer == bufObj) {
1550 bind_buffer_object(ctx, &ctx->AtomicBuffer, 0);
1551 }
1552
1553 /* unbind any pixel pack/unpack pointers bound to this buffer */
1554 if (ctx->Pack.BufferObj == bufObj) {
1555 bind_buffer_object(ctx, &ctx->Pack.BufferObj, 0);
1556 }
1557 if (ctx->Unpack.BufferObj == bufObj) {
1558 bind_buffer_object(ctx, &ctx->Unpack.BufferObj, 0);
1559 }
1560
1561 if (ctx->Texture.BufferObject == bufObj) {
1562 bind_buffer_object(ctx, &ctx->Texture.BufferObject, 0);
1563 }
1564
1565 if (ctx->ExternalVirtualMemoryBuffer == bufObj) {
1566 bind_buffer_object(ctx, &ctx->ExternalVirtualMemoryBuffer, 0);
1567 }
1568
1569 /* unbind query buffer binding point */
1570 if (ctx->QueryBuffer == bufObj) {
1571 bind_buffer_object(ctx, &ctx->QueryBuffer, 0);
1572 }
1573
1574 /* The ID is immediately freed for re-use */
1575 _mesa_HashRemoveLocked(ctx->Shared->BufferObjects, ids[i]);
1576 /* Make sure we do not run into the classic ABA problem on bind.
1577 * We don't want to allow re-binding a buffer object that's been
1578 * "deleted" by glDeleteBuffers().
1579 *
1580 * The explicit rebinding to the default object in the current context
1581 * prevents the above in the current context, but another context
1582 * sharing the same objects might suffer from this problem.
1583 * The alternative would be to do the hash lookup in any case on bind
1584 * which would introduce more runtime overhead than this.
1585 */
1586 bufObj->DeletePending = GL_TRUE;
1587 _mesa_reference_buffer_object(ctx, &bufObj, NULL);
1588 }
1589 }
1590
1591 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
1592 }
1593
1594
1595 void GLAPIENTRY
1596 _mesa_DeleteBuffers_no_error(GLsizei n, const GLuint *ids)
1597 {
1598 GET_CURRENT_CONTEXT(ctx);
1599 delete_buffers(ctx, n, ids);
1600 }
1601
1602
1603 void GLAPIENTRY
1604 _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
1605 {
1606 GET_CURRENT_CONTEXT(ctx);
1607
1608 if (n < 0) {
1609 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
1610 return;
1611 }
1612
1613 delete_buffers(ctx, n, ids);
1614 }
1615
1616
1617 /**
1618 * This is the implementation for glGenBuffers and glCreateBuffers. It is not
1619 * exposed to the rest of Mesa to encourage the use of nameless buffers in
1620 * driver internals.
1621 */
1622 static void
1623 create_buffers(struct gl_context *ctx, GLsizei n, GLuint *buffers, bool dsa)
1624 {
1625 GLuint first;
1626 struct gl_buffer_object *buf;
1627
1628 if (!buffers)
1629 return;
1630
1631 /*
1632 * This must be atomic (generation and allocation of buffer object IDs)
1633 */
1634 _mesa_HashLockMutex(ctx->Shared->BufferObjects);
1635
1636 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
1637
1638 /* Insert the ID and pointer into the hash table. If non-DSA, insert a
1639 * DummyBufferObject. Otherwise, create a new buffer object and insert
1640 * it.
1641 */
1642 for (int i = 0; i < n; i++) {
1643 buffers[i] = first + i;
1644 if (dsa) {
1645 assert(ctx->Driver.NewBufferObject);
1646 buf = ctx->Driver.NewBufferObject(ctx, buffers[i]);
1647 if (!buf) {
1648 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCreateBuffers");
1649 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
1650 return;
1651 }
1652 }
1653 else
1654 buf = &DummyBufferObject;
1655
1656 _mesa_HashInsertLocked(ctx->Shared->BufferObjects, buffers[i], buf);
1657 }
1658
1659 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
1660 }
1661
1662
1663 static void
1664 create_buffers_err(struct gl_context *ctx, GLsizei n, GLuint *buffers, bool dsa)
1665 {
1666 const char *func = dsa ? "glCreateBuffers" : "glGenBuffers";
1667
1668 if (MESA_VERBOSE & VERBOSE_API)
1669 _mesa_debug(ctx, "%s(%d)\n", func, n);
1670
1671 if (n < 0) {
1672 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n %d < 0)", func, n);
1673 return;
1674 }
1675
1676 create_buffers(ctx, n, buffers, dsa);
1677 }
1678
1679 /**
1680 * Generate a set of unique buffer object IDs and store them in \c buffers.
1681 *
1682 * \param n Number of IDs to generate.
1683 * \param buffers Array of \c n locations to store the IDs.
1684 */
1685 void GLAPIENTRY
1686 _mesa_GenBuffers_no_error(GLsizei n, GLuint *buffers)
1687 {
1688 GET_CURRENT_CONTEXT(ctx);
1689 create_buffers(ctx, n, buffers, false);
1690 }
1691
1692
1693 void GLAPIENTRY
1694 _mesa_GenBuffers(GLsizei n, GLuint *buffers)
1695 {
1696 GET_CURRENT_CONTEXT(ctx);
1697 create_buffers_err(ctx, n, buffers, false);
1698 }
1699
1700 /**
1701 * Create a set of buffer objects and store their unique IDs in \c buffers.
1702 *
1703 * \param n Number of IDs to generate.
1704 * \param buffers Array of \c n locations to store the IDs.
1705 */
1706 void GLAPIENTRY
1707 _mesa_CreateBuffers_no_error(GLsizei n, GLuint *buffers)
1708 {
1709 GET_CURRENT_CONTEXT(ctx);
1710 create_buffers(ctx, n, buffers, true);
1711 }
1712
1713
1714 void GLAPIENTRY
1715 _mesa_CreateBuffers(GLsizei n, GLuint *buffers)
1716 {
1717 GET_CURRENT_CONTEXT(ctx);
1718 create_buffers_err(ctx, n, buffers, true);
1719 }
1720
1721
1722 /**
1723 * Determine if ID is the name of a buffer object.
1724 *
1725 * \param id ID of the potential buffer object.
1726 * \return \c GL_TRUE if \c id is the name of a buffer object,
1727 * \c GL_FALSE otherwise.
1728 */
1729 GLboolean GLAPIENTRY
1730 _mesa_IsBuffer(GLuint id)
1731 {
1732 struct gl_buffer_object *bufObj;
1733 GET_CURRENT_CONTEXT(ctx);
1734 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1735
1736 bufObj = _mesa_lookup_bufferobj(ctx, id);
1737
1738 return bufObj && bufObj != &DummyBufferObject;
1739 }
1740
1741
1742 static bool
1743 validate_buffer_storage(struct gl_context *ctx,
1744 struct gl_buffer_object *bufObj, GLsizeiptr size,
1745 GLbitfield flags, const char *func)
1746 {
1747 if (size <= 0) {
1748 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size <= 0)", func);
1749 return false;
1750 }
1751
1752 GLbitfield valid_flags = GL_MAP_READ_BIT |
1753 GL_MAP_WRITE_BIT |
1754 GL_MAP_PERSISTENT_BIT |
1755 GL_MAP_COHERENT_BIT |
1756 GL_DYNAMIC_STORAGE_BIT |
1757 GL_CLIENT_STORAGE_BIT;
1758
1759 if (ctx->Extensions.ARB_sparse_buffer)
1760 valid_flags |= GL_SPARSE_STORAGE_BIT_ARB;
1761
1762 if (flags & ~valid_flags) {
1763 _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid flag bits set)", func);
1764 return false;
1765 }
1766
1767 /* The Errors section of the GL_ARB_sparse_buffer spec says:
1768 *
1769 * "INVALID_VALUE is generated by BufferStorage if <flags> contains
1770 * SPARSE_STORAGE_BIT_ARB and <flags> also contains any combination of
1771 * MAP_READ_BIT or MAP_WRITE_BIT."
1772 */
1773 if (flags & GL_SPARSE_STORAGE_BIT_ARB &&
1774 flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) {
1775 _mesa_error(ctx, GL_INVALID_VALUE, "%s(SPARSE_STORAGE and READ/WRITE)", func);
1776 return false;
1777 }
1778
1779 if (flags & GL_MAP_PERSISTENT_BIT &&
1780 !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) {
1781 _mesa_error(ctx, GL_INVALID_VALUE,
1782 "%s(PERSISTENT and flags!=READ/WRITE)", func);
1783 return false;
1784 }
1785
1786 if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) {
1787 _mesa_error(ctx, GL_INVALID_VALUE,
1788 "%s(COHERENT and flags!=PERSISTENT)", func);
1789 return false;
1790 }
1791
1792 if (bufObj->Immutable || bufObj->HandleAllocated) {
1793 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
1794 return false;
1795 }
1796
1797 return true;
1798 }
1799
1800
1801 static void
1802 buffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj,
1803 struct gl_memory_object *memObj, GLenum target,
1804 GLsizeiptr size, const GLvoid *data, GLbitfield flags,
1805 GLuint64 offset, const char *func)
1806 {
1807 GLboolean res;
1808
1809 /* Unmap the existing buffer. We'll replace it now. Not an error. */
1810 _mesa_buffer_unmap_all_mappings(ctx, bufObj);
1811
1812 FLUSH_VERTICES(ctx, 0);
1813
1814 bufObj->Written = GL_TRUE;
1815 bufObj->Immutable = GL_TRUE;
1816 bufObj->MinMaxCacheDirty = true;
1817
1818 if (memObj) {
1819 assert(ctx->Driver.BufferDataMem);
1820 res = ctx->Driver.BufferDataMem(ctx, target, size, memObj, offset,
1821 GL_DYNAMIC_DRAW, bufObj);
1822 }
1823 else {
1824 assert(ctx->Driver.BufferData);
1825 res = ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW,
1826 flags, bufObj);
1827 }
1828
1829 if (!res) {
1830 if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
1831 /* Even though the interaction between AMD_pinned_memory and
1832 * glBufferStorage is not described in the spec, Graham Sellers
1833 * said that it should behave the same as glBufferData.
1834 */
1835 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1836 }
1837 else {
1838 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1839 }
1840 }
1841 }
1842
1843
1844 static ALWAYS_INLINE void
1845 inlined_buffer_storage(GLenum target, GLuint buffer, GLsizeiptr size,
1846 const GLvoid *data, GLbitfield flags,
1847 GLuint memory, GLuint64 offset,
1848 bool dsa, bool mem, bool no_error, const char *func)
1849 {
1850 GET_CURRENT_CONTEXT(ctx);
1851 struct gl_buffer_object *bufObj;
1852 struct gl_memory_object *memObj = NULL;
1853
1854 if (mem) {
1855 if (!no_error) {
1856 if (!ctx->Extensions.EXT_memory_object) {
1857 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1858 return;
1859 }
1860
1861 /* From the EXT_external_objects spec:
1862 *
1863 * "An INVALID_VALUE error is generated by BufferStorageMemEXT and
1864 * NamedBufferStorageMemEXT if <memory> is 0, or ..."
1865 */
1866 if (memory == 0) {
1867 _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory == 0)", func);
1868 }
1869 }
1870
1871 memObj = _mesa_lookup_memory_object(ctx, memory);
1872 if (!memObj)
1873 return;
1874
1875 /* From the EXT_external_objects spec:
1876 *
1877 * "An INVALID_OPERATION error is generated if <memory> names a
1878 * valid memory object which has no associated memory."
1879 */
1880 if (!no_error && !memObj->Immutable) {
1881 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)",
1882 func);
1883 return;
1884 }
1885 }
1886
1887 if (dsa) {
1888 if (no_error) {
1889 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1890 } else {
1891 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func);
1892 if (!bufObj)
1893 return;
1894 }
1895 } else {
1896 if (no_error) {
1897 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
1898 bufObj = *bufObjPtr;
1899 } else {
1900 bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION);
1901 if (!bufObj)
1902 return;
1903 }
1904 }
1905
1906 if (no_error || validate_buffer_storage(ctx, bufObj, size, flags, func))
1907 buffer_storage(ctx, bufObj, memObj, target, size, data, flags, offset, func);
1908 }
1909
1910
1911 void GLAPIENTRY
1912 _mesa_BufferStorage_no_error(GLenum target, GLsizeiptr size,
1913 const GLvoid *data, GLbitfield flags)
1914 {
1915 inlined_buffer_storage(target, 0, size, data, flags, GL_NONE, 0,
1916 false, false, true, "glBufferStorage");
1917 }
1918
1919
1920 void GLAPIENTRY
1921 _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
1922 GLbitfield flags)
1923 {
1924 inlined_buffer_storage(target, 0, size, data, flags, GL_NONE, 0,
1925 false, false, false, "glBufferStorage");
1926 }
1927
1928 void GLAPIENTRY
1929 _mesa_NamedBufferStorageEXT(GLuint buffer, GLsizeiptr size,
1930 const GLvoid *data, GLbitfield flags)
1931 {
1932 GET_CURRENT_CONTEXT(ctx);
1933
1934 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1935 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
1936 &bufObj, "glNamedBufferStorageEXT"))
1937 return;
1938
1939 inlined_buffer_storage(GL_NONE, buffer, size, data, flags, GL_NONE, 0,
1940 true, false, false, "glNamedBufferStorageEXT");
1941 }
1942
1943
1944 void GLAPIENTRY
1945 _mesa_BufferStorageMemEXT(GLenum target, GLsizeiptr size,
1946 GLuint memory, GLuint64 offset)
1947 {
1948 inlined_buffer_storage(target, 0, size, NULL, 0, memory, offset,
1949 false, true, false, "glBufferStorageMemEXT");
1950 }
1951
1952
1953 void GLAPIENTRY
1954 _mesa_BufferStorageMemEXT_no_error(GLenum target, GLsizeiptr size,
1955 GLuint memory, GLuint64 offset)
1956 {
1957 inlined_buffer_storage(target, 0, size, NULL, 0, memory, offset,
1958 false, true, true, "glBufferStorageMemEXT");
1959 }
1960
1961
1962 void GLAPIENTRY
1963 _mesa_NamedBufferStorage_no_error(GLuint buffer, GLsizeiptr size,
1964 const GLvoid *data, GLbitfield flags)
1965 {
1966 /* In direct state access, buffer objects have an unspecified target
1967 * since they are not required to be bound.
1968 */
1969 inlined_buffer_storage(GL_NONE, buffer, size, data, flags, GL_NONE, 0,
1970 true, false, true, "glNamedBufferStorage");
1971 }
1972
1973
1974 void GLAPIENTRY
1975 _mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
1976 GLbitfield flags)
1977 {
1978 /* In direct state access, buffer objects have an unspecified target
1979 * since they are not required to be bound.
1980 */
1981 inlined_buffer_storage(GL_NONE, buffer, size, data, flags, GL_NONE, 0,
1982 true, false, false, "glNamedBufferStorage");
1983 }
1984
1985 void GLAPIENTRY
1986 _mesa_NamedBufferStorageMemEXT(GLuint buffer, GLsizeiptr size,
1987 GLuint memory, GLuint64 offset)
1988 {
1989 inlined_buffer_storage(GL_NONE, buffer, size, GL_NONE, 0, memory, offset,
1990 true, true, false, "glNamedBufferStorageMemEXT");
1991 }
1992
1993
1994 void GLAPIENTRY
1995 _mesa_NamedBufferStorageMemEXT_no_error(GLuint buffer, GLsizeiptr size,
1996 GLuint memory, GLuint64 offset)
1997 {
1998 inlined_buffer_storage(GL_NONE, buffer, size, GL_NONE, 0, memory, offset,
1999 true, true, true, "glNamedBufferStorageMemEXT");
2000 }
2001
2002
2003 static ALWAYS_INLINE void
2004 buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2005 GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage,
2006 const char *func, bool no_error)
2007 {
2008 bool valid_usage;
2009
2010 if (MESA_VERBOSE & VERBOSE_API) {
2011 _mesa_debug(ctx, "%s(%s, %ld, %p, %s)\n",
2012 func,
2013 _mesa_enum_to_string(target),
2014 (long int) size, data,
2015 _mesa_enum_to_string(usage));
2016 }
2017
2018 if (!no_error) {
2019 if (size < 0) {
2020 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", func);
2021 return;
2022 }
2023
2024 switch (usage) {
2025 case GL_STREAM_DRAW_ARB:
2026 valid_usage = (ctx->API != API_OPENGLES);
2027 break;
2028 case GL_STATIC_DRAW_ARB:
2029 case GL_DYNAMIC_DRAW_ARB:
2030 valid_usage = true;
2031 break;
2032 case GL_STREAM_READ_ARB:
2033 case GL_STREAM_COPY_ARB:
2034 case GL_STATIC_READ_ARB:
2035 case GL_STATIC_COPY_ARB:
2036 case GL_DYNAMIC_READ_ARB:
2037 case GL_DYNAMIC_COPY_ARB:
2038 valid_usage = _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx);
2039 break;
2040 default:
2041 valid_usage = false;
2042 break;
2043 }
2044
2045 if (!valid_usage) {
2046 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid usage: %s)", func,
2047 _mesa_enum_to_string(usage));
2048 return;
2049 }
2050
2051 if (bufObj->Immutable || bufObj->HandleAllocated) {
2052 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
2053 return;
2054 }
2055 }
2056
2057 /* Unmap the existing buffer. We'll replace it now. Not an error. */
2058 _mesa_buffer_unmap_all_mappings(ctx, bufObj);
2059
2060 FLUSH_VERTICES(ctx, 0);
2061
2062 bufObj->Written = GL_TRUE;
2063 bufObj->MinMaxCacheDirty = true;
2064
2065 #ifdef VBO_DEBUG
2066 printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
2067 bufObj->Name, size, data, usage);
2068 #endif
2069
2070 #ifdef BOUNDS_CHECK
2071 size += 100;
2072 #endif
2073
2074 assert(ctx->Driver.BufferData);
2075 if (!ctx->Driver.BufferData(ctx, target, size, data, usage,
2076 GL_MAP_READ_BIT |
2077 GL_MAP_WRITE_BIT |
2078 GL_DYNAMIC_STORAGE_BIT,
2079 bufObj)) {
2080 if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
2081 if (!no_error) {
2082 /* From GL_AMD_pinned_memory:
2083 *
2084 * INVALID_OPERATION is generated by BufferData if <target> is
2085 * EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be
2086 * mapped to the GPU address space.
2087 */
2088 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
2089 }
2090 } else {
2091 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
2092 }
2093 }
2094 }
2095
2096 static void
2097 buffer_data_error(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2098 GLenum target, GLsizeiptr size, const GLvoid *data,
2099 GLenum usage, const char *func)
2100 {
2101 buffer_data(ctx, bufObj, target, size, data, usage, func, false);
2102 }
2103
2104 static void
2105 buffer_data_no_error(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2106 GLenum target, GLsizeiptr size, const GLvoid *data,
2107 GLenum usage, const char *func)
2108 {
2109 buffer_data(ctx, bufObj, target, size, data, usage, func, true);
2110 }
2111
2112 void
2113 _mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2114 GLenum target, GLsizeiptr size, const GLvoid *data,
2115 GLenum usage, const char *func)
2116 {
2117 buffer_data_error(ctx, bufObj, target, size, data, usage, func);
2118 }
2119
2120 void GLAPIENTRY
2121 _mesa_BufferData_no_error(GLenum target, GLsizeiptr size, const GLvoid *data,
2122 GLenum usage)
2123 {
2124 GET_CURRENT_CONTEXT(ctx);
2125
2126 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
2127 buffer_data_no_error(ctx, *bufObj, target, size, data, usage,
2128 "glBufferData");
2129 }
2130
2131 void GLAPIENTRY
2132 _mesa_BufferData(GLenum target, GLsizeiptr size,
2133 const GLvoid *data, GLenum usage)
2134 {
2135 GET_CURRENT_CONTEXT(ctx);
2136 struct gl_buffer_object *bufObj;
2137
2138 bufObj = get_buffer(ctx, "glBufferData", target, GL_INVALID_OPERATION);
2139 if (!bufObj)
2140 return;
2141
2142 _mesa_buffer_data(ctx, bufObj, target, size, data, usage,
2143 "glBufferData");
2144 }
2145
2146 void GLAPIENTRY
2147 _mesa_NamedBufferData_no_error(GLuint buffer, GLsizeiptr size,
2148 const GLvoid *data, GLenum usage)
2149 {
2150 GET_CURRENT_CONTEXT(ctx);
2151
2152 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2153 buffer_data_no_error(ctx, bufObj, GL_NONE, size, data, usage,
2154 "glNamedBufferData");
2155 }
2156
2157 void GLAPIENTRY
2158 _mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data,
2159 GLenum usage)
2160 {
2161 GET_CURRENT_CONTEXT(ctx);
2162 struct gl_buffer_object *bufObj;
2163
2164 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData");
2165 if (!bufObj)
2166 return;
2167
2168 /* In direct state access, buffer objects have an unspecified target since
2169 * they are not required to be bound.
2170 */
2171 _mesa_buffer_data(ctx, bufObj, GL_NONE, size, data, usage,
2172 "glNamedBufferData");
2173 }
2174
2175 void GLAPIENTRY
2176 _mesa_NamedBufferDataEXT(GLuint buffer, GLsizeiptr size, const GLvoid *data,
2177 GLenum usage)
2178 {
2179 GET_CURRENT_CONTEXT(ctx);
2180 struct gl_buffer_object *bufObj;
2181
2182 if (!buffer) {
2183 _mesa_error(ctx, GL_INVALID_OPERATION,
2184 "glNamedBufferDataEXT(buffer=0)");
2185 return;
2186 }
2187
2188 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2189 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
2190 &bufObj, "glNamedBufferDataEXT"))
2191 return;
2192
2193 _mesa_buffer_data(ctx, bufObj, GL_NONE, size, data, usage,
2194 "glNamedBufferDataEXT");
2195 }
2196
2197 static bool
2198 validate_buffer_sub_data(struct gl_context *ctx,
2199 struct gl_buffer_object *bufObj,
2200 GLintptr offset, GLsizeiptr size,
2201 const char *func)
2202 {
2203 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size,
2204 true, func)) {
2205 /* error already recorded */
2206 return false;
2207 }
2208
2209 if (bufObj->Immutable &&
2210 !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) {
2211 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
2212 return false;
2213 }
2214
2215 if ((bufObj->Usage == GL_STATIC_DRAW ||
2216 bufObj->Usage == GL_STATIC_COPY) &&
2217 bufObj->NumSubDataCalls >= BUFFER_WARNING_CALL_COUNT - 1) {
2218 /* If the application declared the buffer as static draw/copy or stream
2219 * draw, it should not be frequently modified with glBufferSubData.
2220 */
2221 BUFFER_USAGE_WARNING(ctx,
2222 "using %s(buffer %u, offset %u, size %u) to "
2223 "update a %s buffer",
2224 func, bufObj->Name, offset, size,
2225 _mesa_enum_to_string(bufObj->Usage));
2226 }
2227
2228 return true;
2229 }
2230
2231
2232 /**
2233 * Implementation for glBufferSubData and glNamedBufferSubData.
2234 *
2235 * \param ctx GL context.
2236 * \param bufObj The buffer object.
2237 * \param offset Offset of the first byte of the subdata range.
2238 * \param size Size, in bytes, of the subdata range.
2239 * \param data The data store.
2240 * \param func Name of calling function for recording errors.
2241 *
2242 */
2243 void
2244 _mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2245 GLintptr offset, GLsizeiptr size, const GLvoid *data)
2246 {
2247 if (size == 0)
2248 return;
2249
2250 bufObj->NumSubDataCalls++;
2251 bufObj->Written = GL_TRUE;
2252 bufObj->MinMaxCacheDirty = true;
2253
2254 assert(ctx->Driver.BufferSubData);
2255 ctx->Driver.BufferSubData(ctx, offset, size, data, bufObj);
2256 }
2257
2258
2259 static ALWAYS_INLINE void
2260 buffer_sub_data(GLenum target, GLuint buffer, GLintptr offset,
2261 GLsizeiptr size, const GLvoid *data,
2262 bool dsa, bool no_error, const char *func)
2263 {
2264 GET_CURRENT_CONTEXT(ctx);
2265 struct gl_buffer_object *bufObj;
2266
2267 if (dsa) {
2268 if (no_error) {
2269 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2270 } else {
2271 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func);
2272 if (!bufObj)
2273 return;
2274 }
2275 } else {
2276 if (no_error) {
2277 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
2278 bufObj = *bufObjPtr;
2279 } else {
2280 bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION);
2281 if (!bufObj)
2282 return;
2283 }
2284 }
2285
2286 if (no_error || validate_buffer_sub_data(ctx, bufObj, offset, size, func))
2287 _mesa_buffer_sub_data(ctx, bufObj, offset, size, data);
2288 }
2289
2290
2291 void GLAPIENTRY
2292 _mesa_BufferSubData_no_error(GLenum target, GLintptr offset,
2293 GLsizeiptr size, const GLvoid *data)
2294 {
2295 buffer_sub_data(target, 0, offset, size, data, false, true,
2296 "glBufferSubData");
2297 }
2298
2299
2300 void GLAPIENTRY
2301 _mesa_BufferSubData(GLenum target, GLintptr offset,
2302 GLsizeiptr size, const GLvoid *data)
2303 {
2304 buffer_sub_data(target, 0, offset, size, data, false, false,
2305 "glBufferSubData");
2306 }
2307
2308 void GLAPIENTRY
2309 _mesa_NamedBufferSubData_no_error(GLuint buffer, GLintptr offset,
2310 GLsizeiptr size, const GLvoid *data)
2311 {
2312 buffer_sub_data(0, buffer, offset, size, data, true, true,
2313 "glNamedBufferSubData");
2314 }
2315
2316 void GLAPIENTRY
2317 _mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
2318 GLsizeiptr size, const GLvoid *data)
2319 {
2320 buffer_sub_data(0, buffer, offset, size, data, true, false,
2321 "glNamedBufferSubData");
2322 }
2323
2324 void GLAPIENTRY
2325 _mesa_NamedBufferSubDataEXT(GLuint buffer, GLintptr offset,
2326 GLsizeiptr size, const GLvoid *data)
2327 {
2328 GET_CURRENT_CONTEXT(ctx);
2329 struct gl_buffer_object *bufObj;
2330
2331 if (!buffer) {
2332 _mesa_error(ctx, GL_INVALID_OPERATION,
2333 "glNamedBufferSubDataEXT(buffer=0)");
2334 return;
2335 }
2336
2337 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2338 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
2339 &bufObj, "glNamedBufferSubDataEXT"))
2340 return;
2341
2342 if (validate_buffer_sub_data(ctx, bufObj, offset, size,
2343 "glNamedBufferSubDataEXT")) {
2344 _mesa_buffer_sub_data(ctx, bufObj, offset, size, data);
2345 }
2346 }
2347
2348
2349 void GLAPIENTRY
2350 _mesa_GetBufferSubData(GLenum target, GLintptr offset,
2351 GLsizeiptr size, GLvoid *data)
2352 {
2353 GET_CURRENT_CONTEXT(ctx);
2354 struct gl_buffer_object *bufObj;
2355
2356 bufObj = get_buffer(ctx, "glGetBufferSubData", target,
2357 GL_INVALID_OPERATION);
2358 if (!bufObj)
2359 return;
2360
2361 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
2362 "glGetBufferSubData")) {
2363 return;
2364 }
2365
2366 assert(ctx->Driver.GetBufferSubData);
2367 ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
2368 }
2369
2370 void GLAPIENTRY
2371 _mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset,
2372 GLsizeiptr size, GLvoid *data)
2373 {
2374 GET_CURRENT_CONTEXT(ctx);
2375 struct gl_buffer_object *bufObj;
2376
2377 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2378 "glGetNamedBufferSubData");
2379 if (!bufObj)
2380 return;
2381
2382 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
2383 "glGetNamedBufferSubData")) {
2384 return;
2385 }
2386
2387 assert(ctx->Driver.GetBufferSubData);
2388 ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
2389 }
2390
2391
2392 void GLAPIENTRY
2393 _mesa_GetNamedBufferSubDataEXT(GLuint buffer, GLintptr offset,
2394 GLsizeiptr size, GLvoid *data)
2395 {
2396 GET_CURRENT_CONTEXT(ctx);
2397 struct gl_buffer_object *bufObj;
2398
2399 if (!buffer) {
2400 _mesa_error(ctx, GL_INVALID_OPERATION,
2401 "glGetNamedBufferSubDataEXT(buffer=0)");
2402 return;
2403 }
2404
2405 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2406 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
2407 &bufObj, "glGetNamedBufferSubDataEXT"))
2408 return;
2409
2410 if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
2411 "glGetNamedBufferSubDataEXT")) {
2412 return;
2413 }
2414
2415 assert(ctx->Driver.GetBufferSubData);
2416 ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
2417 }
2418
2419 /**
2420 * \param subdata true if caller is *SubData, false if *Data
2421 */
2422 static ALWAYS_INLINE void
2423 clear_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2424 GLenum internalformat, GLintptr offset, GLsizeiptr size,
2425 GLenum format, GLenum type, const GLvoid *data,
2426 const char *func, bool subdata, bool no_error)
2427 {
2428 mesa_format mesaFormat;
2429 GLubyte clearValue[MAX_PIXEL_BYTES];
2430 GLsizeiptr clearValueSize;
2431
2432 /* This checks for disallowed mappings. */
2433 if (!no_error && !buffer_object_subdata_range_good(ctx, bufObj, offset, size,
2434 subdata, func)) {
2435 return;
2436 }
2437
2438 if (no_error) {
2439 mesaFormat = _mesa_get_texbuffer_format(ctx, internalformat);
2440 } else {
2441 mesaFormat = validate_clear_buffer_format(ctx, internalformat,
2442 format, type, func);
2443 }
2444
2445 if (mesaFormat == MESA_FORMAT_NONE)
2446 return;
2447
2448 clearValueSize = _mesa_get_format_bytes(mesaFormat);
2449 if (!no_error &&
2450 (offset % clearValueSize != 0 || size % clearValueSize != 0)) {
2451 _mesa_error(ctx, GL_INVALID_VALUE,
2452 "%s(offset or size is not a multiple of "
2453 "internalformat size)", func);
2454 return;
2455 }
2456
2457 /* Bail early. Negative size has already been checked. */
2458 if (size == 0)
2459 return;
2460
2461 bufObj->MinMaxCacheDirty = true;
2462
2463 if (data == NULL) {
2464 /* clear to zeros, per the spec */
2465 ctx->Driver.ClearBufferSubData(ctx, offset, size,
2466 NULL, clearValueSize, bufObj);
2467 return;
2468 }
2469
2470 if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue,
2471 format, type, data, func)) {
2472 return;
2473 }
2474
2475 ctx->Driver.ClearBufferSubData(ctx, offset, size,
2476 clearValue, clearValueSize, bufObj);
2477 }
2478
2479 static void
2480 clear_buffer_sub_data_error(struct gl_context *ctx,
2481 struct gl_buffer_object *bufObj,
2482 GLenum internalformat, GLintptr offset,
2483 GLsizeiptr size, GLenum format, GLenum type,
2484 const GLvoid *data, const char *func, bool subdata)
2485 {
2486 clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, format,
2487 type, data, func, subdata, false);
2488 }
2489
2490
2491 static void
2492 clear_buffer_sub_data_no_error(struct gl_context *ctx,
2493 struct gl_buffer_object *bufObj,
2494 GLenum internalformat, GLintptr offset,
2495 GLsizeiptr size, GLenum format, GLenum type,
2496 const GLvoid *data, const char *func,
2497 bool subdata)
2498 {
2499 clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, format,
2500 type, data, func, subdata, true);
2501 }
2502
2503
2504 void GLAPIENTRY
2505 _mesa_ClearBufferData_no_error(GLenum target, GLenum internalformat,
2506 GLenum format, GLenum type, const GLvoid *data)
2507 {
2508 GET_CURRENT_CONTEXT(ctx);
2509
2510 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
2511 clear_buffer_sub_data_no_error(ctx, *bufObj, internalformat, 0,
2512 (*bufObj)->Size, format, type, data,
2513 "glClearBufferData", false);
2514 }
2515
2516
2517 void GLAPIENTRY
2518 _mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format,
2519 GLenum type, const GLvoid *data)
2520 {
2521 GET_CURRENT_CONTEXT(ctx);
2522 struct gl_buffer_object *bufObj;
2523
2524 bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE);
2525 if (!bufObj)
2526 return;
2527
2528 clear_buffer_sub_data_error(ctx, bufObj, internalformat, 0, bufObj->Size,
2529 format, type, data, "glClearBufferData", false);
2530 }
2531
2532
2533 void GLAPIENTRY
2534 _mesa_ClearNamedBufferData_no_error(GLuint buffer, GLenum internalformat,
2535 GLenum format, GLenum type,
2536 const GLvoid *data)
2537 {
2538 GET_CURRENT_CONTEXT(ctx);
2539
2540 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2541 clear_buffer_sub_data_no_error(ctx, bufObj, internalformat, 0, bufObj->Size,
2542 format, type, data, "glClearNamedBufferData",
2543 false);
2544 }
2545
2546
2547 void GLAPIENTRY
2548 _mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat,
2549 GLenum format, GLenum type, const GLvoid *data)
2550 {
2551 GET_CURRENT_CONTEXT(ctx);
2552 struct gl_buffer_object *bufObj;
2553
2554 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData");
2555 if (!bufObj)
2556 return;
2557
2558 clear_buffer_sub_data_error(ctx, bufObj, internalformat, 0, bufObj->Size,
2559 format, type, data, "glClearNamedBufferData",
2560 false);
2561 }
2562
2563
2564 void GLAPIENTRY
2565 _mesa_ClearNamedBufferDataEXT(GLuint buffer, GLenum internalformat,
2566 GLenum format, GLenum type, const GLvoid *data)
2567 {
2568 GET_CURRENT_CONTEXT(ctx);
2569 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2570 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
2571 &bufObj, "glClearNamedBufferDataEXT"))
2572 return;
2573
2574 clear_buffer_sub_data_error(ctx, bufObj, internalformat, 0, bufObj->Size,
2575 format, type, data, "glClearNamedBufferDataEXT",
2576 false);
2577 }
2578
2579
2580 void GLAPIENTRY
2581 _mesa_ClearBufferSubData_no_error(GLenum target, GLenum internalformat,
2582 GLintptr offset, GLsizeiptr size,
2583 GLenum format, GLenum type,
2584 const GLvoid *data)
2585 {
2586 GET_CURRENT_CONTEXT(ctx);
2587
2588 struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
2589 clear_buffer_sub_data_no_error(ctx, *bufObj, internalformat, offset, size,
2590 format, type, data, "glClearBufferSubData",
2591 true);
2592 }
2593
2594
2595 void GLAPIENTRY
2596 _mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
2597 GLintptr offset, GLsizeiptr size,
2598 GLenum format, GLenum type,
2599 const GLvoid *data)
2600 {
2601 GET_CURRENT_CONTEXT(ctx);
2602 struct gl_buffer_object *bufObj;
2603
2604 bufObj = get_buffer(ctx, "glClearBufferSubData", target, GL_INVALID_VALUE);
2605 if (!bufObj)
2606 return;
2607
2608 clear_buffer_sub_data_error(ctx, bufObj, internalformat, offset, size,
2609 format, type, data, "glClearBufferSubData",
2610 true);
2611 }
2612
2613
2614 void GLAPIENTRY
2615 _mesa_ClearNamedBufferSubData_no_error(GLuint buffer, GLenum internalformat,
2616 GLintptr offset, GLsizeiptr size,
2617 GLenum format, GLenum type,
2618 const GLvoid *data)
2619 {
2620 GET_CURRENT_CONTEXT(ctx);
2621
2622 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2623 clear_buffer_sub_data_no_error(ctx, bufObj, internalformat, offset, size,
2624 format, type, data,
2625 "glClearNamedBufferSubData", true);
2626 }
2627
2628
2629 void GLAPIENTRY
2630 _mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat,
2631 GLintptr offset, GLsizeiptr size,
2632 GLenum format, GLenum type,
2633 const GLvoid *data)
2634 {
2635 GET_CURRENT_CONTEXT(ctx);
2636 struct gl_buffer_object *bufObj;
2637
2638 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2639 "glClearNamedBufferSubData");
2640 if (!bufObj)
2641 return;
2642
2643 clear_buffer_sub_data_error(ctx, bufObj, internalformat, offset, size,
2644 format, type, data, "glClearNamedBufferSubData",
2645 true);
2646 }
2647
2648 void GLAPIENTRY
2649 _mesa_ClearNamedBufferSubDataEXT(GLuint buffer, GLenum internalformat,
2650 GLintptr offset, GLsizeiptr size,
2651 GLenum format, GLenum type,
2652 const GLvoid *data)
2653 {
2654 GET_CURRENT_CONTEXT(ctx);
2655 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2656 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
2657 &bufObj, "glClearNamedBufferSubDataEXT"))
2658 return;
2659
2660 clear_buffer_sub_data_error(ctx, bufObj, internalformat, offset, size,
2661 format, type, data, "glClearNamedBufferSubDataEXT",
2662 true);
2663 }
2664
2665 static GLboolean
2666 unmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj)
2667 {
2668 GLboolean status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER);
2669 bufObj->Mappings[MAP_USER].AccessFlags = 0;
2670 assert(bufObj->Mappings[MAP_USER].Pointer == NULL);
2671 assert(bufObj->Mappings[MAP_USER].Offset == 0);
2672 assert(bufObj->Mappings[MAP_USER].Length == 0);
2673
2674 return status;
2675 }
2676
2677 static GLboolean
2678 validate_and_unmap_buffer(struct gl_context *ctx,
2679 struct gl_buffer_object *bufObj,
2680 const char *func)
2681 {
2682 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2683
2684 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
2685 _mesa_error(ctx, GL_INVALID_OPERATION,
2686 "%s(buffer is not mapped)", func);
2687 return GL_FALSE;
2688 }
2689
2690 #ifdef BOUNDS_CHECK
2691 if (bufObj->Access != GL_READ_ONLY_ARB) {
2692 GLubyte *buf = (GLubyte *) bufObj->Pointer;
2693 GLuint i;
2694 /* check that last 100 bytes are still = magic value */
2695 for (i = 0; i < 100; i++) {
2696 GLuint pos = bufObj->Size - i - 1;
2697 if (buf[pos] != 123) {
2698 _mesa_warning(ctx, "Out of bounds buffer object write detected"
2699 " at position %d (value = %u)\n",
2700 pos, buf[pos]);
2701 }
2702 }
2703 }
2704 #endif
2705
2706 #ifdef VBO_DEBUG
2707 if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
2708 GLuint i, unchanged = 0;
2709 GLubyte *b = (GLubyte *) bufObj->Pointer;
2710 GLint pos = -1;
2711 /* check which bytes changed */
2712 for (i = 0; i < bufObj->Size - 1; i++) {
2713 if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
2714 unchanged++;
2715 if (pos == -1)
2716 pos = i;
2717 }
2718 }
2719 if (unchanged) {
2720 printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
2721 bufObj->Name, unchanged, bufObj->Size, pos);
2722 }
2723 }
2724 #endif
2725
2726 return unmap_buffer(ctx, bufObj);
2727 }
2728
2729 GLboolean GLAPIENTRY
2730 _mesa_UnmapBuffer_no_error(GLenum target)
2731 {
2732 GET_CURRENT_CONTEXT(ctx);
2733 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
2734 struct gl_buffer_object *bufObj = *bufObjPtr;
2735
2736 return unmap_buffer(ctx, bufObj);
2737 }
2738
2739 GLboolean GLAPIENTRY
2740 _mesa_UnmapBuffer(GLenum target)
2741 {
2742 GET_CURRENT_CONTEXT(ctx);
2743 struct gl_buffer_object *bufObj;
2744
2745 bufObj = get_buffer(ctx, "glUnmapBuffer", target, GL_INVALID_OPERATION);
2746 if (!bufObj)
2747 return GL_FALSE;
2748
2749 return validate_and_unmap_buffer(ctx, bufObj, "glUnmapBuffer");
2750 }
2751
2752 GLboolean GLAPIENTRY
2753 _mesa_UnmapNamedBufferEXT_no_error(GLuint buffer)
2754 {
2755 GET_CURRENT_CONTEXT(ctx);
2756 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2757
2758 return unmap_buffer(ctx, bufObj);
2759 }
2760
2761 GLboolean GLAPIENTRY
2762 _mesa_UnmapNamedBufferEXT(GLuint buffer)
2763 {
2764 GET_CURRENT_CONTEXT(ctx);
2765 struct gl_buffer_object *bufObj;
2766
2767 if (!buffer) {
2768 _mesa_error(ctx, GL_INVALID_OPERATION,
2769 "glUnmapNamedBufferEXT(buffer=0)");
2770 return GL_FALSE;
2771 }
2772
2773 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer");
2774 if (!bufObj)
2775 return GL_FALSE;
2776
2777 return validate_and_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer");
2778 }
2779
2780
2781 static bool
2782 get_buffer_parameter(struct gl_context *ctx,
2783 struct gl_buffer_object *bufObj, GLenum pname,
2784 GLint64 *params, const char *func)
2785 {
2786 switch (pname) {
2787 case GL_BUFFER_SIZE_ARB:
2788 *params = bufObj->Size;
2789 break;
2790 case GL_BUFFER_USAGE_ARB:
2791 *params = bufObj->Usage;
2792 break;
2793 case GL_BUFFER_ACCESS_ARB:
2794 *params = simplified_access_mode(ctx,
2795 bufObj->Mappings[MAP_USER].AccessFlags);
2796 break;
2797 case GL_BUFFER_MAPPED_ARB:
2798 *params = _mesa_bufferobj_mapped(bufObj, MAP_USER);
2799 break;
2800 case GL_BUFFER_ACCESS_FLAGS:
2801 if (!ctx->Extensions.ARB_map_buffer_range)
2802 goto invalid_pname;
2803 *params = bufObj->Mappings[MAP_USER].AccessFlags;
2804 break;
2805 case GL_BUFFER_MAP_OFFSET:
2806 if (!ctx->Extensions.ARB_map_buffer_range)
2807 goto invalid_pname;
2808 *params = bufObj->Mappings[MAP_USER].Offset;
2809 break;
2810 case GL_BUFFER_MAP_LENGTH:
2811 if (!ctx->Extensions.ARB_map_buffer_range)
2812 goto invalid_pname;
2813 *params = bufObj->Mappings[MAP_USER].Length;
2814 break;
2815 case GL_BUFFER_IMMUTABLE_STORAGE:
2816 if (!ctx->Extensions.ARB_buffer_storage)
2817 goto invalid_pname;
2818 *params = bufObj->Immutable;
2819 break;
2820 case GL_BUFFER_STORAGE_FLAGS:
2821 if (!ctx->Extensions.ARB_buffer_storage)
2822 goto invalid_pname;
2823 *params = bufObj->StorageFlags;
2824 break;
2825 default:
2826 goto invalid_pname;
2827 }
2828
2829 return true;
2830
2831 invalid_pname:
2832 _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname: %s)", func,
2833 _mesa_enum_to_string(pname));
2834 return false;
2835 }
2836
2837 void GLAPIENTRY
2838 _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
2839 {
2840 GET_CURRENT_CONTEXT(ctx);
2841 struct gl_buffer_object *bufObj;
2842 GLint64 parameter;
2843
2844 bufObj = get_buffer(ctx, "glGetBufferParameteriv", target,
2845 GL_INVALID_OPERATION);
2846 if (!bufObj)
2847 return;
2848
2849 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2850 "glGetBufferParameteriv"))
2851 return; /* Error already recorded. */
2852
2853 *params = (GLint) parameter;
2854 }
2855
2856 void GLAPIENTRY
2857 _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
2858 {
2859 GET_CURRENT_CONTEXT(ctx);
2860 struct gl_buffer_object *bufObj;
2861 GLint64 parameter;
2862
2863 bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target,
2864 GL_INVALID_OPERATION);
2865 if (!bufObj)
2866 return;
2867
2868 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2869 "glGetBufferParameteri64v"))
2870 return; /* Error already recorded. */
2871
2872 *params = parameter;
2873 }
2874
2875 void GLAPIENTRY
2876 _mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params)
2877 {
2878 GET_CURRENT_CONTEXT(ctx);
2879 struct gl_buffer_object *bufObj;
2880 GLint64 parameter;
2881
2882 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2883 "glGetNamedBufferParameteriv");
2884 if (!bufObj)
2885 return;
2886
2887 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2888 "glGetNamedBufferParameteriv"))
2889 return; /* Error already recorded. */
2890
2891 *params = (GLint) parameter;
2892 }
2893
2894 void GLAPIENTRY
2895 _mesa_GetNamedBufferParameterivEXT(GLuint buffer, GLenum pname, GLint *params)
2896 {
2897 GET_CURRENT_CONTEXT(ctx);
2898 struct gl_buffer_object *bufObj;
2899 GLint64 parameter;
2900
2901 if (!buffer) {
2902 _mesa_error(ctx, GL_INVALID_OPERATION,
2903 "glGetNamedBufferParameterivEXT: buffer=0");
2904 return;
2905 }
2906
2907 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2908 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
2909 &bufObj, "glGetNamedBufferParameterivEXT"))
2910 return;
2911
2912 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2913 "glGetNamedBufferParameterivEXT"))
2914 return; /* Error already recorded. */
2915
2916 *params = (GLint) parameter;
2917 }
2918
2919 void GLAPIENTRY
2920 _mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname,
2921 GLint64 *params)
2922 {
2923 GET_CURRENT_CONTEXT(ctx);
2924 struct gl_buffer_object *bufObj;
2925 GLint64 parameter;
2926
2927 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2928 "glGetNamedBufferParameteri64v");
2929 if (!bufObj)
2930 return;
2931
2932 if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2933 "glGetNamedBufferParameteri64v"))
2934 return; /* Error already recorded. */
2935
2936 *params = parameter;
2937 }
2938
2939
2940 void GLAPIENTRY
2941 _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params)
2942 {
2943 GET_CURRENT_CONTEXT(ctx);
2944 struct gl_buffer_object *bufObj;
2945
2946 if (pname != GL_BUFFER_MAP_POINTER) {
2947 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointerv(pname != "
2948 "GL_BUFFER_MAP_POINTER)");
2949 return;
2950 }
2951
2952 bufObj = get_buffer(ctx, "glGetBufferPointerv", target,
2953 GL_INVALID_OPERATION);
2954 if (!bufObj)
2955 return;
2956
2957 *params = bufObj->Mappings[MAP_USER].Pointer;
2958 }
2959
2960 void GLAPIENTRY
2961 _mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params)
2962 {
2963 GET_CURRENT_CONTEXT(ctx);
2964 struct gl_buffer_object *bufObj;
2965
2966 if (pname != GL_BUFFER_MAP_POINTER) {
2967 _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != "
2968 "GL_BUFFER_MAP_POINTER)");
2969 return;
2970 }
2971
2972 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2973 "glGetNamedBufferPointerv");
2974 if (!bufObj)
2975 return;
2976
2977 *params = bufObj->Mappings[MAP_USER].Pointer;
2978 }
2979
2980 void GLAPIENTRY
2981 _mesa_GetNamedBufferPointervEXT(GLuint buffer, GLenum pname, GLvoid **params)
2982 {
2983 GET_CURRENT_CONTEXT(ctx);
2984 struct gl_buffer_object *bufObj;
2985
2986 if (!buffer) {
2987 _mesa_error(ctx, GL_INVALID_OPERATION,
2988 "glGetNamedBufferPointervEXT(buffer=0)");
2989 return;
2990 }
2991 if (pname != GL_BUFFER_MAP_POINTER) {
2992 _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointervEXT(pname != "
2993 "GL_BUFFER_MAP_POINTER)");
2994 return;
2995 }
2996
2997 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2998 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
2999 &bufObj, "glGetNamedBufferPointervEXT"))
3000 return;
3001
3002 *params = bufObj->Mappings[MAP_USER].Pointer;
3003 }
3004
3005 static void
3006 copy_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *src,
3007 struct gl_buffer_object *dst, GLintptr readOffset,
3008 GLintptr writeOffset, GLsizeiptr size, const char *func)
3009 {
3010 if (_mesa_check_disallowed_mapping(src)) {
3011 _mesa_error(ctx, GL_INVALID_OPERATION,
3012 "%s(readBuffer is mapped)", func);
3013 return;
3014 }
3015
3016 if (_mesa_check_disallowed_mapping(dst)) {
3017 _mesa_error(ctx, GL_INVALID_OPERATION,
3018 "%s(writeBuffer is mapped)", func);
3019 return;
3020 }
3021
3022 if (readOffset < 0) {
3023 _mesa_error(ctx, GL_INVALID_VALUE,
3024 "%s(readOffset %d < 0)", func, (int) readOffset);
3025 return;
3026 }
3027
3028 if (writeOffset < 0) {
3029 _mesa_error(ctx, GL_INVALID_VALUE,
3030 "%s(writeOffset %d < 0)", func, (int) writeOffset);
3031 return;
3032 }
3033
3034 if (size < 0) {
3035 _mesa_error(ctx, GL_INVALID_VALUE,
3036 "%s(size %d < 0)", func, (int) size);
3037 return;
3038 }
3039
3040 if (readOffset + size > src->Size) {
3041 _mesa_error(ctx, GL_INVALID_VALUE,
3042 "%s(readOffset %d + size %d > src_buffer_size %d)", func,
3043 (int) readOffset, (int) size, (int) src->Size);
3044 return;
3045 }
3046
3047 if (writeOffset + size > dst->Size) {
3048 _mesa_error(ctx, GL_INVALID_VALUE,
3049 "%s(writeOffset %d + size %d > dst_buffer_size %d)", func,
3050 (int) writeOffset, (int) size, (int) dst->Size);
3051 return;
3052 }
3053
3054 if (src == dst) {
3055 if (readOffset + size <= writeOffset) {
3056 /* OK */
3057 }
3058 else if (writeOffset + size <= readOffset) {
3059 /* OK */
3060 }
3061 else {
3062 /* overlapping src/dst is illegal */
3063 _mesa_error(ctx, GL_INVALID_VALUE,
3064 "%s(overlapping src/dst)", func);
3065 return;
3066 }
3067 }
3068
3069 dst->MinMaxCacheDirty = true;
3070
3071 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
3072 }
3073
3074 void GLAPIENTRY
3075 _mesa_CopyBufferSubData_no_error(GLenum readTarget, GLenum writeTarget,
3076 GLintptr readOffset, GLintptr writeOffset,
3077 GLsizeiptr size)
3078 {
3079 GET_CURRENT_CONTEXT(ctx);
3080
3081 struct gl_buffer_object **src_ptr = get_buffer_target(ctx, readTarget);
3082 struct gl_buffer_object *src = *src_ptr;
3083
3084 struct gl_buffer_object **dst_ptr = get_buffer_target(ctx, writeTarget);
3085 struct gl_buffer_object *dst = *dst_ptr;
3086
3087 dst->MinMaxCacheDirty = true;
3088 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset,
3089 size);
3090 }
3091
3092 void GLAPIENTRY
3093 _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
3094 GLintptr readOffset, GLintptr writeOffset,
3095 GLsizeiptr size)
3096 {
3097 GET_CURRENT_CONTEXT(ctx);
3098 struct gl_buffer_object *src, *dst;
3099
3100 src = get_buffer(ctx, "glCopyBufferSubData", readTarget,
3101 GL_INVALID_OPERATION);
3102 if (!src)
3103 return;
3104
3105 dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget,
3106 GL_INVALID_OPERATION);
3107 if (!dst)
3108 return;
3109
3110 copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
3111 "glCopyBufferSubData");
3112 }
3113
3114 void GLAPIENTRY
3115 _mesa_NamedCopyBufferSubDataEXT(GLuint readBuffer, GLuint writeBuffer,
3116 GLintptr readOffset, GLintptr writeOffset,
3117 GLsizeiptr size)
3118 {
3119 GET_CURRENT_CONTEXT(ctx);
3120 struct gl_buffer_object *src, *dst;
3121
3122 src = _mesa_lookup_bufferobj(ctx, readBuffer);
3123 if (!_mesa_handle_bind_buffer_gen(ctx, readBuffer,
3124 &src,
3125 "glNamedCopyBufferSubDataEXT"))
3126 return;
3127
3128 dst = _mesa_lookup_bufferobj(ctx, writeBuffer);
3129 if (!_mesa_handle_bind_buffer_gen(ctx, writeBuffer,
3130 &dst,
3131 "glNamedCopyBufferSubDataEXT"))
3132 return;
3133
3134 copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
3135 "glNamedCopyBufferSubDataEXT");
3136 }
3137
3138 void GLAPIENTRY
3139 _mesa_CopyNamedBufferSubData_no_error(GLuint readBuffer, GLuint writeBuffer,
3140 GLintptr readOffset,
3141 GLintptr writeOffset, GLsizeiptr size)
3142 {
3143 GET_CURRENT_CONTEXT(ctx);
3144
3145 struct gl_buffer_object *src = _mesa_lookup_bufferobj(ctx, readBuffer);
3146 struct gl_buffer_object *dst = _mesa_lookup_bufferobj(ctx, writeBuffer);
3147
3148 dst->MinMaxCacheDirty = true;
3149 ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset,
3150 size);
3151 }
3152
3153 void GLAPIENTRY
3154 _mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
3155 GLintptr readOffset, GLintptr writeOffset,
3156 GLsizeiptr size)
3157 {
3158 GET_CURRENT_CONTEXT(ctx);
3159 struct gl_buffer_object *src, *dst;
3160
3161 src = _mesa_lookup_bufferobj_err(ctx, readBuffer,
3162 "glCopyNamedBufferSubData");
3163 if (!src)
3164 return;
3165
3166 dst = _mesa_lookup_bufferobj_err(ctx, writeBuffer,
3167 "glCopyNamedBufferSubData");
3168 if (!dst)
3169 return;
3170
3171 copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
3172 "glCopyNamedBufferSubData");
3173 }
3174
3175 void GLAPIENTRY
3176 _mesa_InternalBufferSubDataCopyMESA(GLintptr srcBuffer, GLuint srcOffset,
3177 GLuint dstTargetOrName, GLintptr dstOffset,
3178 GLsizeiptr size, GLboolean named,
3179 GLboolean ext_dsa)
3180 {
3181 GET_CURRENT_CONTEXT(ctx);
3182 struct gl_buffer_object *src = (struct gl_buffer_object *)srcBuffer;
3183 struct gl_buffer_object *dst;
3184 const char *func;
3185
3186 /* Handle behavior for all 3 variants. */
3187 if (named && ext_dsa) {
3188 func = "glNamedBufferSubDataEXT";
3189 dst = _mesa_lookup_bufferobj(ctx, dstTargetOrName);
3190 if (!_mesa_handle_bind_buffer_gen(ctx, dstTargetOrName, &dst, func))
3191 goto done;
3192 } else if (named) {
3193 func = "glNamedBufferSubData";
3194 dst = _mesa_lookup_bufferobj_err(ctx, dstTargetOrName, func);
3195 if (!dst)
3196 goto done;
3197 } else {
3198 assert(!ext_dsa);
3199 func = "glBufferSubData";
3200 dst = get_buffer(ctx, func, dstTargetOrName, GL_INVALID_OPERATION);
3201 if (!dst)
3202 goto done;
3203 }
3204
3205 if (!validate_buffer_sub_data(ctx, dst, dstOffset, size, func))
3206 goto done; /* the error is already set */
3207
3208 dst->MinMaxCacheDirty = true;
3209 ctx->Driver.CopyBufferSubData(ctx, src, dst, srcOffset, dstOffset, size);
3210
3211 done:
3212 /* The caller passes the reference to this function, so unreference it. */
3213 _mesa_reference_buffer_object(ctx, &src, NULL);
3214 }
3215
3216 static bool
3217 validate_map_buffer_range(struct gl_context *ctx,
3218 struct gl_buffer_object *bufObj, GLintptr offset,
3219 GLsizeiptr length, GLbitfield access,
3220 const char *func)
3221 {
3222 GLbitfield allowed_access;
3223
3224 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, false);
3225
3226 if (offset < 0) {
3227 _mesa_error(ctx, GL_INVALID_VALUE,
3228 "%s(offset %ld < 0)", func, (long) offset);
3229 return false;
3230 }
3231
3232 if (length < 0) {
3233 _mesa_error(ctx, GL_INVALID_VALUE,
3234 "%s(length %ld < 0)", func, (long) length);
3235 return false;
3236 }
3237
3238 /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
3239 *
3240 * "An INVALID_OPERATION error is generated for any of the following
3241 * conditions:
3242 *
3243 * * <length> is zero."
3244 *
3245 * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec
3246 * (30.10.2014) also says this, so it's no longer allowed for desktop GL,
3247 * either.
3248 */
3249 if (length == 0) {
3250 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func);
3251 return false;
3252 }
3253
3254 allowed_access = GL_MAP_READ_BIT |
3255 GL_MAP_WRITE_BIT |
3256 GL_MAP_INVALIDATE_RANGE_BIT |
3257 GL_MAP_INVALIDATE_BUFFER_BIT |
3258 GL_MAP_FLUSH_EXPLICIT_BIT |
3259 GL_MAP_UNSYNCHRONIZED_BIT;
3260
3261 if (ctx->Extensions.ARB_buffer_storage) {
3262 allowed_access |= GL_MAP_PERSISTENT_BIT |
3263 GL_MAP_COHERENT_BIT;
3264 }
3265
3266 if (access & ~allowed_access) {
3267 /* generate an error if any bits other than those allowed are set */
3268 _mesa_error(ctx, GL_INVALID_VALUE,
3269 "%s(access has undefined bits set)", func);
3270 return false;
3271 }
3272
3273 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
3274 _mesa_error(ctx, GL_INVALID_OPERATION,
3275 "%s(access indicates neither read or write)", func);
3276 return false;
3277 }
3278
3279 if ((access & GL_MAP_READ_BIT) &&
3280 (access & (GL_MAP_INVALIDATE_RANGE_BIT |
3281 GL_MAP_INVALIDATE_BUFFER_BIT |
3282 GL_MAP_UNSYNCHRONIZED_BIT))) {
3283 _mesa_error(ctx, GL_INVALID_OPERATION,
3284 "%s(read access with disallowed bits)", func);
3285 return false;
3286 }
3287
3288 if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
3289 ((access & GL_MAP_WRITE_BIT) == 0)) {
3290 _mesa_error(ctx, GL_INVALID_OPERATION,
3291 "%s(access has flush explicit without write)", func);
3292 return false;
3293 }
3294
3295 if (access & GL_MAP_READ_BIT &&
3296 !(bufObj->StorageFlags & GL_MAP_READ_BIT)) {
3297 _mesa_error(ctx, GL_INVALID_OPERATION,
3298 "%s(buffer does not allow read access)", func);
3299 return false;
3300 }
3301
3302 if (access & GL_MAP_WRITE_BIT &&
3303 !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) {
3304 _mesa_error(ctx, GL_INVALID_OPERATION,
3305 "%s(buffer does not allow write access)", func);
3306 return false;
3307 }
3308
3309 if (access & GL_MAP_COHERENT_BIT &&
3310 !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) {
3311 _mesa_error(ctx, GL_INVALID_OPERATION,
3312 "%s(buffer does not allow coherent access)", func);
3313 return false;
3314 }
3315
3316 if (access & GL_MAP_PERSISTENT_BIT &&
3317 !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) {
3318 _mesa_error(ctx, GL_INVALID_OPERATION,
3319 "%s(buffer does not allow persistent access)", func);
3320 return false;
3321 }
3322
3323 if (offset + length > bufObj->Size) {
3324 _mesa_error(ctx, GL_INVALID_VALUE,
3325 "%s(offset %lu + length %lu > buffer_size %lu)", func,
3326 (unsigned long) offset, (unsigned long) length,
3327 (unsigned long) bufObj->Size);
3328 return false;
3329 }
3330
3331 if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
3332 _mesa_error(ctx, GL_INVALID_OPERATION,
3333 "%s(buffer already mapped)", func);
3334 return false;
3335 }
3336
3337 if (access & GL_MAP_WRITE_BIT) {
3338 bufObj->NumMapBufferWriteCalls++;
3339 if ((bufObj->Usage == GL_STATIC_DRAW ||
3340 bufObj->Usage == GL_STATIC_COPY) &&
3341 bufObj->NumMapBufferWriteCalls >= BUFFER_WARNING_CALL_COUNT) {
3342 BUFFER_USAGE_WARNING(ctx,
3343 "using %s(buffer %u, offset %u, length %u) to "
3344 "update a %s buffer",
3345 func, bufObj->Name, offset, length,
3346 _mesa_enum_to_string(bufObj->Usage));
3347 }
3348 }
3349
3350 return true;
3351 }
3352
3353 static void *
3354 map_buffer_range(struct gl_context *ctx, struct gl_buffer_object *bufObj,
3355 GLintptr offset, GLsizeiptr length, GLbitfield access,
3356 const char *func)
3357 {
3358 if (!bufObj->Size) {
3359 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
3360 return NULL;
3361 }
3362
3363 assert(ctx->Driver.MapBufferRange);
3364 void *map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
3365 MAP_USER);
3366 if (!map) {
3367 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func);
3368 }
3369 else {
3370 /* The driver callback should have set all these fields.
3371 * This is important because other modules (like VBO) might call
3372 * the driver function directly.
3373 */
3374 assert(bufObj->Mappings[MAP_USER].Pointer == map);
3375 assert(bufObj->Mappings[MAP_USER].Length == length);
3376 assert(bufObj->Mappings[MAP_USER].Offset == offset);
3377 assert(bufObj->Mappings[MAP_USER].AccessFlags == access);
3378 }
3379
3380 if (access & GL_MAP_WRITE_BIT) {
3381 bufObj->Written = GL_TRUE;
3382 bufObj->MinMaxCacheDirty = true;
3383 }
3384
3385 #ifdef VBO_DEBUG
3386 if (strstr(func, "Range") == NULL) { /* If not MapRange */
3387 printf("glMapBuffer(%u, sz %ld, access 0x%x)\n",
3388 bufObj->Name, bufObj->Size, access);
3389 /* Access must be write only */
3390 if ((access & GL_MAP_WRITE_BIT) && (!(access & ~GL_MAP_WRITE_BIT))) {
3391 GLuint i;
3392 GLubyte *b = (GLubyte *) bufObj->Pointer;
3393 for (i = 0; i < bufObj->Size; i++)
3394 b[i] = i & 0xff;
3395 }
3396 }
3397 #endif
3398
3399 #ifdef BOUNDS_CHECK
3400 if (strstr(func, "Range") == NULL) { /* If not MapRange */
3401 GLubyte *buf = (GLubyte *) bufObj->Pointer;
3402 GLuint i;
3403 /* buffer is 100 bytes larger than requested, fill with magic value */
3404 for (i = 0; i < 100; i++) {
3405 buf[bufObj->Size - i - 1] = 123;
3406 }
3407 }
3408 #endif
3409
3410 return map;
3411 }
3412
3413 void * GLAPIENTRY
3414 _mesa_MapBufferRange_no_error(GLenum target, GLintptr offset,
3415 GLsizeiptr length, GLbitfield access)
3416 {
3417 GET_CURRENT_CONTEXT(ctx);
3418
3419 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
3420 struct gl_buffer_object *bufObj = *bufObjPtr;
3421
3422 return map_buffer_range(ctx, bufObj, offset, length, access,
3423 "glMapBufferRange");
3424 }
3425
3426 void * GLAPIENTRY
3427 _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
3428 GLbitfield access)
3429 {
3430 GET_CURRENT_CONTEXT(ctx);
3431 struct gl_buffer_object *bufObj;
3432
3433 if (!ctx->Extensions.ARB_map_buffer_range) {
3434 _mesa_error(ctx, GL_INVALID_OPERATION,
3435 "glMapBufferRange(ARB_map_buffer_range not supported)");
3436 return NULL;
3437 }
3438
3439 bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION);
3440 if (!bufObj)
3441 return NULL;
3442
3443 if (!validate_map_buffer_range(ctx, bufObj, offset, length, access,
3444 "glMapBufferRange"))
3445 return NULL;
3446
3447 return map_buffer_range(ctx, bufObj, offset, length, access,
3448 "glMapBufferRange");
3449 }
3450
3451 void * GLAPIENTRY
3452 _mesa_MapNamedBufferRange_no_error(GLuint buffer, GLintptr offset,
3453 GLsizeiptr length, GLbitfield access)
3454 {
3455 GET_CURRENT_CONTEXT(ctx);
3456 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3457
3458 return map_buffer_range(ctx, bufObj, offset, length, access,
3459 "glMapNamedBufferRange");
3460 }
3461
3462 static void *
3463 map_named_buffer_range(GLuint buffer, GLintptr offset, GLsizeiptr length,
3464 GLbitfield access, bool dsa_ext, const char *func)
3465 {
3466 GET_CURRENT_CONTEXT(ctx);
3467 struct gl_buffer_object *bufObj = NULL;
3468
3469 if (!ctx->Extensions.ARB_map_buffer_range) {
3470 _mesa_error(ctx, GL_INVALID_OPERATION,
3471 "%s(ARB_map_buffer_range not supported)", func);
3472 return NULL;
3473 }
3474
3475 if (dsa_ext) {
3476 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3477 if (!_mesa_handle_bind_buffer_gen(ctx, buffer, &bufObj, func))
3478 return NULL;
3479 } else {
3480 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func);
3481 if (!bufObj)
3482 return NULL;
3483 }
3484
3485 if (!validate_map_buffer_range(ctx, bufObj, offset, length, access, func))
3486 return NULL;
3487
3488 return map_buffer_range(ctx, bufObj, offset, length, access, func);
3489 }
3490
3491 void * GLAPIENTRY
3492 _mesa_MapNamedBufferRangeEXT(GLuint buffer, GLintptr offset, GLsizeiptr length,
3493 GLbitfield access)
3494 {
3495 GET_CURRENT_CONTEXT(ctx);
3496 if (!buffer) {
3497 _mesa_error(ctx, GL_INVALID_OPERATION,
3498 "glMapNamedBufferRangeEXT(buffer=0)");
3499 return NULL;
3500 }
3501 return map_named_buffer_range(buffer, offset, length, access, true,
3502 "glMapNamedBufferRangeEXT");
3503 }
3504
3505 void * GLAPIENTRY
3506 _mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
3507 GLbitfield access)
3508 {
3509 return map_named_buffer_range(buffer, offset, length, access, false,
3510 "glMapNamedBufferRange");
3511 }
3512
3513 /**
3514 * Converts GLenum access from MapBuffer and MapNamedBuffer into
3515 * flags for input to map_buffer_range.
3516 *
3517 * \return true if the type of requested access is permissible.
3518 */
3519 static bool
3520 get_map_buffer_access_flags(struct gl_context *ctx, GLenum access,
3521 GLbitfield *flags)
3522 {
3523 switch (access) {
3524 case GL_READ_ONLY_ARB:
3525 *flags = GL_MAP_READ_BIT;
3526 return _mesa_is_desktop_gl(ctx);
3527 case GL_WRITE_ONLY_ARB:
3528 *flags = GL_MAP_WRITE_BIT;
3529 return true;
3530 case GL_READ_WRITE_ARB:
3531 *flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
3532 return _mesa_is_desktop_gl(ctx);
3533 default:
3534 *flags = 0;
3535 return false;
3536 }
3537 }
3538
3539 void * GLAPIENTRY
3540 _mesa_MapBuffer_no_error(GLenum target, GLenum access)
3541 {
3542 GET_CURRENT_CONTEXT(ctx);
3543
3544 GLbitfield accessFlags;
3545 get_map_buffer_access_flags(ctx, access, &accessFlags);
3546
3547 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
3548 struct gl_buffer_object *bufObj = *bufObjPtr;
3549
3550 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3551 "glMapBuffer");
3552 }
3553
3554 void * GLAPIENTRY
3555 _mesa_MapBuffer(GLenum target, GLenum access)
3556 {
3557 GET_CURRENT_CONTEXT(ctx);
3558 struct gl_buffer_object *bufObj;
3559 GLbitfield accessFlags;
3560
3561 if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
3562 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBuffer(invalid access)");
3563 return NULL;
3564 }
3565
3566 bufObj = get_buffer(ctx, "glMapBuffer", target, GL_INVALID_OPERATION);
3567 if (!bufObj)
3568 return NULL;
3569
3570 if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3571 "glMapBuffer"))
3572 return NULL;
3573
3574 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3575 "glMapBuffer");
3576 }
3577
3578 void * GLAPIENTRY
3579 _mesa_MapNamedBuffer_no_error(GLuint buffer, GLenum access)
3580 {
3581 GET_CURRENT_CONTEXT(ctx);
3582
3583 GLbitfield accessFlags;
3584 get_map_buffer_access_flags(ctx, access, &accessFlags);
3585
3586 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3587
3588 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3589 "glMapNamedBuffer");
3590 }
3591
3592 void * GLAPIENTRY
3593 _mesa_MapNamedBuffer(GLuint buffer, GLenum access)
3594 {
3595 GET_CURRENT_CONTEXT(ctx);
3596 struct gl_buffer_object *bufObj;
3597 GLbitfield accessFlags;
3598
3599 if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
3600 _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)");
3601 return NULL;
3602 }
3603
3604 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBuffer");
3605 if (!bufObj)
3606 return NULL;
3607
3608 if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3609 "glMapNamedBuffer"))
3610 return NULL;
3611
3612 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3613 "glMapNamedBuffer");
3614 }
3615
3616 void * GLAPIENTRY
3617 _mesa_MapNamedBufferEXT(GLuint buffer, GLenum access)
3618 {
3619 GET_CURRENT_CONTEXT(ctx);
3620
3621 GLbitfield accessFlags;
3622 if (!buffer) {
3623 _mesa_error(ctx, GL_INVALID_OPERATION,
3624 "glMapNamedBufferEXT(buffer=0)");
3625 return NULL;
3626 }
3627 if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
3628 _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBufferEXT(invalid access)");
3629 return NULL;
3630 }
3631
3632 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3633 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
3634 &bufObj, "glMapNamedBufferEXT"))
3635 return NULL;
3636
3637 if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3638 "glMapNamedBufferEXT"))
3639 return NULL;
3640
3641 return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3642 "glMapNamedBufferEXT");
3643 }
3644
3645 static void
3646 flush_mapped_buffer_range(struct gl_context *ctx,
3647 struct gl_buffer_object *bufObj,
3648 GLintptr offset, GLsizeiptr length,
3649 const char *func)
3650 {
3651 if (!ctx->Extensions.ARB_map_buffer_range) {
3652 _mesa_error(ctx, GL_INVALID_OPERATION,
3653 "%s(ARB_map_buffer_range not supported)", func);
3654 return;
3655 }
3656
3657 if (offset < 0) {
3658 _mesa_error(ctx, GL_INVALID_VALUE,
3659 "%s(offset %ld < 0)", func, (long) offset);
3660 return;
3661 }
3662
3663 if (length < 0) {
3664 _mesa_error(ctx, GL_INVALID_VALUE,
3665 "%s(length %ld < 0)", func, (long) length);
3666 return;
3667 }
3668
3669 if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
3670 /* buffer is not mapped */
3671 _mesa_error(ctx, GL_INVALID_OPERATION,
3672 "%s(buffer is not mapped)", func);
3673 return;
3674 }
3675
3676 if ((bufObj->Mappings[MAP_USER].AccessFlags &
3677 GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
3678 _mesa_error(ctx, GL_INVALID_OPERATION,
3679 "%s(GL_MAP_FLUSH_EXPLICIT_BIT not set)", func);
3680 return;
3681 }
3682
3683 if (offset + length > bufObj->Mappings[MAP_USER].Length) {
3684 _mesa_error(ctx, GL_INVALID_VALUE,
3685 "%s(offset %ld + length %ld > mapped length %ld)", func,
3686 (long) offset, (long) length,
3687 (long) bufObj->Mappings[MAP_USER].Length);
3688 return;
3689 }
3690
3691 assert(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT);
3692
3693 if (ctx->Driver.FlushMappedBufferRange)
3694 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
3695 MAP_USER);
3696 }
3697
3698 void GLAPIENTRY
3699 _mesa_FlushMappedBufferRange_no_error(GLenum target, GLintptr offset,
3700 GLsizeiptr length)
3701 {
3702 GET_CURRENT_CONTEXT(ctx);
3703 struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
3704 struct gl_buffer_object *bufObj = *bufObjPtr;
3705
3706 if (ctx->Driver.FlushMappedBufferRange)
3707 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
3708 MAP_USER);
3709 }
3710
3711 void GLAPIENTRY
3712 _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset,
3713 GLsizeiptr length)
3714 {
3715 GET_CURRENT_CONTEXT(ctx);
3716 struct gl_buffer_object *bufObj;
3717
3718 bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target,
3719 GL_INVALID_OPERATION);
3720 if (!bufObj)
3721 return;
3722
3723 flush_mapped_buffer_range(ctx, bufObj, offset, length,
3724 "glFlushMappedBufferRange");
3725 }
3726
3727 void GLAPIENTRY
3728 _mesa_FlushMappedNamedBufferRange_no_error(GLuint buffer, GLintptr offset,
3729 GLsizeiptr length)
3730 {
3731 GET_CURRENT_CONTEXT(ctx);
3732 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3733
3734 if (ctx->Driver.FlushMappedBufferRange)
3735 ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
3736 MAP_USER);
3737 }
3738
3739 void GLAPIENTRY
3740 _mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset,
3741 GLsizeiptr length)
3742 {
3743 GET_CURRENT_CONTEXT(ctx);
3744 struct gl_buffer_object *bufObj;
3745
3746 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
3747 "glFlushMappedNamedBufferRange");
3748 if (!bufObj)
3749 return;
3750
3751 flush_mapped_buffer_range(ctx, bufObj, offset, length,
3752 "glFlushMappedNamedBufferRange");
3753 }
3754
3755 void GLAPIENTRY
3756 _mesa_FlushMappedNamedBufferRangeEXT(GLuint buffer, GLintptr offset,
3757 GLsizeiptr length)
3758 {
3759 GET_CURRENT_CONTEXT(ctx);
3760 struct gl_buffer_object *bufObj;
3761
3762 if (!buffer) {
3763 _mesa_error(ctx, GL_INVALID_OPERATION,
3764 "glFlushMappedNamedBufferRangeEXT(buffer=0)");
3765 return;
3766 }
3767
3768 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3769 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
3770 &bufObj, "glFlushMappedNamedBufferRangeEXT"))
3771 return;
3772
3773 flush_mapped_buffer_range(ctx, bufObj, offset, length,
3774 "glFlushMappedNamedBufferRangeEXT");
3775 }
3776
3777 static void
3778 bind_buffer_range_uniform_buffer(struct gl_context *ctx, GLuint index,
3779 struct gl_buffer_object *bufObj,
3780 GLintptr offset, GLsizeiptr size)
3781 {
3782 if (!bufObj) {
3783 offset = -1;
3784 size = -1;
3785 }
3786
3787 _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
3788 bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
3789 }
3790
3791 /**
3792 * Bind a region of a buffer object to a uniform block binding point.
3793 * \param index the uniform buffer binding point index
3794 * \param bufObj the buffer object
3795 * \param offset offset to the start of buffer object region
3796 * \param size size of the buffer object region
3797 */
3798 static void
3799 bind_buffer_range_uniform_buffer_err(struct gl_context *ctx, GLuint index,
3800 struct gl_buffer_object *bufObj,
3801 GLintptr offset, GLsizeiptr size)
3802 {
3803 if (index >= ctx->Const.MaxUniformBufferBindings) {
3804 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
3805 return;
3806 }
3807
3808 if (offset & (ctx->Const.UniformBufferOffsetAlignment - 1)) {
3809 _mesa_error(ctx, GL_INVALID_VALUE,
3810 "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
3811 ctx->Const.UniformBufferOffsetAlignment);
3812 return;
3813 }
3814
3815 bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
3816 }
3817
3818 static void
3819 bind_buffer_range_shader_storage_buffer(struct gl_context *ctx,
3820 GLuint index,
3821 struct gl_buffer_object *bufObj,
3822 GLintptr offset,
3823 GLsizeiptr size)
3824 {
3825 if (!bufObj) {
3826 offset = -1;
3827 size = -1;
3828 }
3829
3830 _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
3831 bind_shader_storage_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
3832 }
3833
3834 /**
3835 * Bind a region of a buffer object to a shader storage block binding point.
3836 * \param index the shader storage buffer binding point index
3837 * \param bufObj the buffer object
3838 * \param offset offset to the start of buffer object region
3839 * \param size size of the buffer object region
3840 */
3841 static void
3842 bind_buffer_range_shader_storage_buffer_err(struct gl_context *ctx,
3843 GLuint index,
3844 struct gl_buffer_object *bufObj,
3845 GLintptr offset, GLsizeiptr size)
3846 {
3847 if (index >= ctx->Const.MaxShaderStorageBufferBindings) {
3848 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
3849 return;
3850 }
3851
3852 if (offset & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) {
3853 _mesa_error(ctx, GL_INVALID_VALUE,
3854 "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
3855 ctx->Const.ShaderStorageBufferOffsetAlignment);
3856 return;
3857 }
3858
3859 bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size);
3860 }
3861
3862 static void
3863 bind_buffer_range_atomic_buffer(struct gl_context *ctx, GLuint index,
3864 struct gl_buffer_object *bufObj,
3865 GLintptr offset, GLsizeiptr size)
3866 {
3867 if (!bufObj) {
3868 offset = -1;
3869 size = -1;
3870 }
3871
3872 _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
3873 bind_atomic_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
3874 }
3875
3876 /**
3877 * Bind a region of a buffer object to an atomic storage block binding point.
3878 * \param index the shader storage buffer binding point index
3879 * \param bufObj the buffer object
3880 * \param offset offset to the start of buffer object region
3881 * \param size size of the buffer object region
3882 */
3883 static void
3884 bind_buffer_range_atomic_buffer_err(struct gl_context *ctx,
3885 GLuint index,
3886 struct gl_buffer_object *bufObj,
3887 GLintptr offset, GLsizeiptr size)
3888 {
3889 if (index >= ctx->Const.MaxAtomicBufferBindings) {
3890 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
3891 return;
3892 }
3893
3894 if (offset & (ATOMIC_COUNTER_SIZE - 1)) {
3895 _mesa_error(ctx, GL_INVALID_VALUE,
3896 "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
3897 ATOMIC_COUNTER_SIZE);
3898 return;
3899 }
3900
3901 bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size);
3902 }
3903
3904 static inline bool
3905 bind_buffers_check_offset_and_size(struct gl_context *ctx,
3906 GLuint index,
3907 const GLintptr *offsets,
3908 const GLsizeiptr *sizes)
3909 {
3910 if (offsets[index] < 0) {
3911 /* The ARB_multi_bind spec says:
3912 *
3913 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3914 * value in <offsets> is less than zero (per binding)."
3915 */
3916 _mesa_error(ctx, GL_INVALID_VALUE,
3917 "glBindBuffersRange(offsets[%u]=%" PRId64 " < 0)",
3918 index, (int64_t) offsets[index]);
3919 return false;
3920 }
3921
3922 if (sizes[index] <= 0) {
3923 /* The ARB_multi_bind spec says:
3924 *
3925 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3926 * value in <sizes> is less than or equal to zero (per binding)."
3927 */
3928 _mesa_error(ctx, GL_INVALID_VALUE,
3929 "glBindBuffersRange(sizes[%u]=%" PRId64 " <= 0)",
3930 index, (int64_t) sizes[index]);
3931 return false;
3932 }
3933
3934 return true;
3935 }
3936
3937 static bool
3938 error_check_bind_uniform_buffers(struct gl_context *ctx,
3939 GLuint first, GLsizei count,
3940 const char *caller)
3941 {
3942 if (!ctx->Extensions.ARB_uniform_buffer_object) {
3943 _mesa_error(ctx, GL_INVALID_ENUM,
3944 "%s(target=GL_UNIFORM_BUFFER)", caller);
3945 return false;
3946 }
3947
3948 /* The ARB_multi_bind_spec says:
3949 *
3950 * "An INVALID_OPERATION error is generated if <first> + <count> is
3951 * greater than the number of target-specific indexed binding points,
3952 * as described in section 6.7.1."
3953 */
3954 if (first + count > ctx->Const.MaxUniformBufferBindings) {
3955 _mesa_error(ctx, GL_INVALID_OPERATION,
3956 "%s(first=%u + count=%d > the value of "
3957 "GL_MAX_UNIFORM_BUFFER_BINDINGS=%u)",
3958 caller, first, count,
3959 ctx->Const.MaxUniformBufferBindings);
3960 return false;
3961 }
3962
3963 return true;
3964 }
3965
3966 static bool
3967 error_check_bind_shader_storage_buffers(struct gl_context *ctx,
3968 GLuint first, GLsizei count,
3969 const char *caller)
3970 {
3971 if (!ctx->Extensions.ARB_shader_storage_buffer_object) {
3972 _mesa_error(ctx, GL_INVALID_ENUM,
3973 "%s(target=GL_SHADER_STORAGE_BUFFER)", caller);
3974 return false;
3975 }
3976
3977 /* The ARB_multi_bind_spec says:
3978 *
3979 * "An INVALID_OPERATION error is generated if <first> + <count> is
3980 * greater than the number of target-specific indexed binding points,
3981 * as described in section 6.7.1."
3982 */
3983 if (first + count > ctx->Const.MaxShaderStorageBufferBindings) {
3984 _mesa_error(ctx, GL_INVALID_OPERATION,
3985 "%s(first=%u + count=%d > the value of "
3986 "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS=%u)",
3987 caller, first, count,
3988 ctx->Const.MaxShaderStorageBufferBindings);
3989 return false;
3990 }
3991
3992 return true;
3993 }
3994
3995 /**
3996 * Unbind all uniform buffers in the range
3997 * <first> through <first>+<count>-1
3998 */
3999 static void
4000 unbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
4001 {
4002 for (int i = 0; i < count; i++)
4003 set_buffer_binding(ctx, &ctx->UniformBufferBindings[first + i],
4004 NULL, -1, -1, GL_TRUE, 0);
4005 }
4006
4007 /**
4008 * Unbind all shader storage buffers in the range
4009 * <first> through <first>+<count>-1
4010 */
4011 static void
4012 unbind_shader_storage_buffers(struct gl_context *ctx, GLuint first,
4013 GLsizei count)
4014 {
4015 for (int i = 0; i < count; i++)
4016 set_buffer_binding(ctx, &ctx->ShaderStorageBufferBindings[first + i],
4017 NULL, -1, -1, GL_TRUE, 0);
4018 }
4019
4020 static void
4021 bind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count,
4022 const GLuint *buffers,
4023 bool range,
4024 const GLintptr *offsets, const GLsizeiptr *sizes,
4025 const char *caller)
4026 {
4027 if (!error_check_bind_uniform_buffers(ctx, first, count, caller))
4028 return;
4029
4030 /* Assume that at least one binding will be changed */
4031 FLUSH_VERTICES(ctx, 0);
4032 ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
4033
4034 if (!buffers) {
4035 /* The ARB_multi_bind spec says:
4036 *
4037 * "If <buffers> is NULL, all bindings from <first> through
4038 * <first>+<count>-1 are reset to their unbound (zero) state.
4039 * In this case, the offsets and sizes associated with the
4040 * binding points are set to default values, ignoring
4041 * <offsets> and <sizes>."
4042 */
4043 unbind_uniform_buffers(ctx, first, count);
4044 return;
4045 }
4046
4047 /* Note that the error semantics for multi-bind commands differ from
4048 * those of other GL commands.
4049 *
4050 * The Issues section in the ARB_multi_bind spec says:
4051 *
4052 * "(11) Typically, OpenGL specifies that if an error is generated by a
4053 * command, that command has no effect. This is somewhat
4054 * unfortunate for multi-bind commands, because it would require a
4055 * first pass to scan the entire list of bound objects for errors
4056 * and then a second pass to actually perform the bindings.
4057 * Should we have different error semantics?
4058 *
4059 * RESOLVED: Yes. In this specification, when the parameters for
4060 * one of the <count> binding points are invalid, that binding point
4061 * is not updated and an error will be generated. However, other
4062 * binding points in the same command will be updated if their
4063 * parameters are valid and no other error occurs."
4064 */
4065
4066 _mesa_HashLockMutex(ctx->Shared->BufferObjects);
4067
4068 for (int i = 0; i < count; i++) {
4069 struct gl_buffer_binding *binding =
4070 &ctx->UniformBufferBindings[first + i];
4071 GLintptr offset = 0;
4072 GLsizeiptr size = 0;
4073
4074 if (range) {
4075 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
4076 continue;
4077
4078 /* The ARB_multi_bind spec says:
4079 *
4080 * "An INVALID_VALUE error is generated by BindBuffersRange if any
4081 * pair of values in <offsets> and <sizes> does not respectively
4082 * satisfy the constraints described for those parameters for the
4083 * specified target, as described in section 6.7.1 (per binding)."
4084 *
4085 * Section 6.7.1 refers to table 6.5, which says:
4086 *
4087 * "┌───────────────────────────────────────────────────────────────┐
4088 * │ Uniform buffer array bindings (see sec. 7.6) │
4089 * ├─────────────────────┬─────────────────────────────────────────┤
4090 * │ ... │ ... │
4091 * │ offset restriction │ multiple of value of UNIFORM_BUFFER_- │
4092 * │ │ OFFSET_ALIGNMENT │
4093 * │ ... │ ... │
4094 * │ size restriction │ none │
4095 * └─────────────────────┴─────────────────────────────────────────┘"
4096 */
4097 if (offsets[i] & (ctx->Const.UniformBufferOffsetAlignment - 1)) {
4098 _mesa_error(ctx, GL_INVALID_VALUE,
4099 "glBindBuffersRange(offsets[%u]=%" PRId64
4100 " is misaligned; it must be a multiple of the value of "
4101 "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT=%u when "
4102 "target=GL_UNIFORM_BUFFER)",
4103 i, (int64_t) offsets[i],
4104 ctx->Const.UniformBufferOffsetAlignment);
4105 continue;
4106 }
4107
4108 offset = offsets[i];
4109 size = sizes[i];
4110 }
4111
4112 set_buffer_multi_binding(ctx, buffers, i, caller,
4113 binding, offset, size, range,
4114 USAGE_UNIFORM_BUFFER);
4115 }
4116
4117 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
4118 }
4119
4120 static void
4121 bind_shader_storage_buffers(struct gl_context *ctx, GLuint first,
4122 GLsizei count, const GLuint *buffers,
4123 bool range,
4124 const GLintptr *offsets,
4125 const GLsizeiptr *sizes,
4126 const char *caller)
4127 {
4128 if (!error_check_bind_shader_storage_buffers(ctx, first, count, caller))
4129 return;
4130
4131 /* Assume that at least one binding will be changed */
4132 FLUSH_VERTICES(ctx, 0);
4133 ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer;
4134
4135 if (!buffers) {
4136 /* The ARB_multi_bind spec says:
4137 *
4138 * "If <buffers> is NULL, all bindings from <first> through
4139 * <first>+<count>-1 are reset to their unbound (zero) state.
4140 * In this case, the offsets and sizes associated with the
4141 * binding points are set to default values, ignoring
4142 * <offsets> and <sizes>."
4143 */
4144 unbind_shader_storage_buffers(ctx, first, count);
4145 return;
4146 }
4147
4148 /* Note that the error semantics for multi-bind commands differ from
4149 * those of other GL commands.
4150 *
4151 * The Issues section in the ARB_multi_bind spec says:
4152 *
4153 * "(11) Typically, OpenGL specifies that if an error is generated by a
4154 * command, that command has no effect. This is somewhat
4155 * unfortunate for multi-bind commands, because it would require a
4156 * first pass to scan the entire list of bound objects for errors
4157 * and then a second pass to actually perform the bindings.
4158 * Should we have different error semantics?
4159 *
4160 * RESOLVED: Yes. In this specification, when the parameters for
4161 * one of the <count> binding points are invalid, that binding point
4162 * is not updated and an error will be generated. However, other
4163 * binding points in the same command will be updated if their
4164 * parameters are valid and no other error occurs."
4165 */
4166
4167 _mesa_HashLockMutex(ctx->Shared->BufferObjects);
4168
4169 for (int i = 0; i < count; i++) {
4170 struct gl_buffer_binding *binding =
4171 &ctx->ShaderStorageBufferBindings[first + i];
4172 GLintptr offset = 0;
4173 GLsizeiptr size = 0;
4174
4175 if (range) {
4176 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
4177 continue;
4178
4179 /* The ARB_multi_bind spec says:
4180 *
4181 * "An INVALID_VALUE error is generated by BindBuffersRange if any
4182 * pair of values in <offsets> and <sizes> does not respectively
4183 * satisfy the constraints described for those parameters for the
4184 * specified target, as described in section 6.7.1 (per binding)."
4185 *
4186 * Section 6.7.1 refers to table 6.5, which says:
4187 *
4188 * "┌───────────────────────────────────────────────────────────────┐
4189 * │ Shader storage buffer array bindings (see sec. 7.8) │
4190 * ├─────────────────────┬─────────────────────────────────────────┤
4191 * │ ... │ ... │
4192 * │ offset restriction │ multiple of value of SHADER_STORAGE_- │
4193 * │ │ BUFFER_OFFSET_ALIGNMENT │
4194 * │ ... │ ... │
4195 * │ size restriction │ none │
4196 * └─────────────────────┴─────────────────────────────────────────┘"
4197 */
4198 if (offsets[i] & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) {
4199 _mesa_error(ctx, GL_INVALID_VALUE,
4200 "glBindBuffersRange(offsets[%u]=%" PRId64
4201 " is misaligned; it must be a multiple of the value of "
4202 "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT=%u when "
4203 "target=GL_SHADER_STORAGE_BUFFER)",
4204 i, (int64_t) offsets[i],
4205 ctx->Const.ShaderStorageBufferOffsetAlignment);
4206 continue;
4207 }
4208
4209 offset = offsets[i];
4210 size = sizes[i];
4211 }
4212
4213 set_buffer_multi_binding(ctx, buffers, i, caller,
4214 binding, offset, size, range,
4215 USAGE_SHADER_STORAGE_BUFFER);
4216 }
4217
4218 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
4219 }
4220
4221 static bool
4222 error_check_bind_xfb_buffers(struct gl_context *ctx,
4223 struct gl_transform_feedback_object *tfObj,
4224 GLuint first, GLsizei count, const char *caller)
4225 {
4226 if (!ctx->Extensions.EXT_transform_feedback) {
4227 _mesa_error(ctx, GL_INVALID_ENUM,
4228 "%s(target=GL_TRANSFORM_FEEDBACK_BUFFER)", caller);
4229 return false;
4230 }
4231
4232 /* Page 398 of the PDF of the OpenGL 4.4 (Core Profile) spec says:
4233 *
4234 * "An INVALID_OPERATION error is generated :
4235 *
4236 * ...
4237 * • by BindBufferRange or BindBufferBase if target is TRANSFORM_-
4238 * FEEDBACK_BUFFER and transform feedback is currently active."
4239 *
4240 * We assume that this is also meant to apply to BindBuffersRange
4241 * and BindBuffersBase.
4242 */
4243 if (tfObj->Active) {
4244 _mesa_error(ctx, GL_INVALID_OPERATION,
4245 "%s(Changing transform feedback buffers while "
4246 "transform feedback is active)", caller);
4247 return false;
4248 }
4249
4250 /* The ARB_multi_bind_spec says:
4251 *
4252 * "An INVALID_OPERATION error is generated if <first> + <count> is
4253 * greater than the number of target-specific indexed binding points,
4254 * as described in section 6.7.1."
4255 */
4256 if (first + count > ctx->Const.MaxTransformFeedbackBuffers) {
4257 _mesa_error(ctx, GL_INVALID_OPERATION,
4258 "%s(first=%u + count=%d > the value of "
4259 "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS=%u)",
4260 caller, first, count,
4261 ctx->Const.MaxTransformFeedbackBuffers);
4262 return false;
4263 }
4264
4265 return true;
4266 }
4267
4268 /**
4269 * Unbind all transform feedback buffers in the range
4270 * <first> through <first>+<count>-1
4271 */
4272 static void
4273 unbind_xfb_buffers(struct gl_context *ctx,
4274 struct gl_transform_feedback_object *tfObj,
4275 GLuint first, GLsizei count)
4276 {
4277 for (int i = 0; i < count; i++)
4278 _mesa_set_transform_feedback_binding(ctx, tfObj, first + i,
4279 NULL, 0, 0);
4280 }
4281
4282 static void
4283 bind_xfb_buffers(struct gl_context *ctx,
4284 GLuint first, GLsizei count,
4285 const GLuint *buffers,
4286 bool range,
4287 const GLintptr *offsets,
4288 const GLsizeiptr *sizes,
4289 const char *caller)
4290 {
4291 struct gl_transform_feedback_object *tfObj =
4292 ctx->TransformFeedback.CurrentObject;
4293
4294 if (!error_check_bind_xfb_buffers(ctx, tfObj, first, count, caller))
4295 return;
4296
4297 /* Assume that at least one binding will be changed */
4298 FLUSH_VERTICES(ctx, 0);
4299 ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback;
4300
4301 if (!buffers) {
4302 /* The ARB_multi_bind spec says:
4303 *
4304 * "If <buffers> is NULL, all bindings from <first> through
4305 * <first>+<count>-1 are reset to their unbound (zero) state.
4306 * In this case, the offsets and sizes associated with the
4307 * binding points are set to default values, ignoring
4308 * <offsets> and <sizes>."
4309 */
4310 unbind_xfb_buffers(ctx, tfObj, first, count);
4311 return;
4312 }
4313
4314 /* Note that the error semantics for multi-bind commands differ from
4315 * those of other GL commands.
4316 *
4317 * The Issues section in the ARB_multi_bind spec says:
4318 *
4319 * "(11) Typically, OpenGL specifies that if an error is generated by a
4320 * command, that command has no effect. This is somewhat
4321 * unfortunate for multi-bind commands, because it would require a
4322 * first pass to scan the entire list of bound objects for errors
4323 * and then a second pass to actually perform the bindings.
4324 * Should we have different error semantics?
4325 *
4326 * RESOLVED: Yes. In this specification, when the parameters for
4327 * one of the <count> binding points are invalid, that binding point
4328 * is not updated and an error will be generated. However, other
4329 * binding points in the same command will be updated if their
4330 * parameters are valid and no other error occurs."
4331 */
4332
4333 _mesa_HashLockMutex(ctx->Shared->BufferObjects);
4334
4335 for (int i = 0; i < count; i++) {
4336 const GLuint index = first + i;
4337 struct gl_buffer_object * const boundBufObj = tfObj->Buffers[index];
4338 struct gl_buffer_object *bufObj;
4339 GLintptr offset = 0;
4340 GLsizeiptr size = 0;
4341
4342 if (range) {
4343 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
4344 continue;
4345
4346 /* The ARB_multi_bind spec says:
4347 *
4348 * "An INVALID_VALUE error is generated by BindBuffersRange if any
4349 * pair of values in <offsets> and <sizes> does not respectively
4350 * satisfy the constraints described for those parameters for the
4351 * specified target, as described in section 6.7.1 (per binding)."
4352 *
4353 * Section 6.7.1 refers to table 6.5, which says:
4354 *
4355 * "┌───────────────────────────────────────────────────────────────┐
4356 * │ Transform feedback array bindings (see sec. 13.2.2) │
4357 * ├───────────────────────┬───────────────────────────────────────┤
4358 * │ ... │ ... │
4359 * │ offset restriction │ multiple of 4 │
4360 * │ ... │ ... │
4361 * │ size restriction │ multiple of 4 │
4362 * └───────────────────────┴───────────────────────────────────────┘"
4363 */
4364 if (offsets[i] & 0x3) {
4365 _mesa_error(ctx, GL_INVALID_VALUE,
4366 "glBindBuffersRange(offsets[%u]=%" PRId64
4367 " is misaligned; it must be a multiple of 4 when "
4368 "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
4369 i, (int64_t) offsets[i]);
4370 continue;
4371 }
4372
4373 if (sizes[i] & 0x3) {
4374 _mesa_error(ctx, GL_INVALID_VALUE,
4375 "glBindBuffersRange(sizes[%u]=%" PRId64
4376 " is misaligned; it must be a multiple of 4 when "
4377 "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
4378 i, (int64_t) sizes[i]);
4379 continue;
4380 }
4381
4382 offset = offsets[i];
4383 size = sizes[i];
4384 }
4385
4386 if (boundBufObj && boundBufObj->Name == buffers[i])
4387 bufObj = boundBufObj;
4388 else {
4389 bool error;
4390 bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller,
4391 &error);
4392 if (error)
4393 continue;
4394 }
4395
4396 _mesa_set_transform_feedback_binding(ctx, tfObj, index, bufObj,
4397 offset, size);
4398 }
4399
4400 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
4401 }
4402
4403 static bool
4404 error_check_bind_atomic_buffers(struct gl_context *ctx,
4405 GLuint first, GLsizei count,
4406 const char *caller)
4407 {
4408 if (!ctx->Extensions.ARB_shader_atomic_counters) {
4409 _mesa_error(ctx, GL_INVALID_ENUM,
4410 "%s(target=GL_ATOMIC_COUNTER_BUFFER)", caller);
4411 return false;
4412 }
4413
4414 /* The ARB_multi_bind_spec says:
4415 *
4416 * "An INVALID_OPERATION error is generated if <first> + <count> is
4417 * greater than the number of target-specific indexed binding points,
4418 * as described in section 6.7.1."
4419 */
4420 if (first + count > ctx->Const.MaxAtomicBufferBindings) {
4421 _mesa_error(ctx, GL_INVALID_OPERATION,
4422 "%s(first=%u + count=%d > the value of "
4423 "GL_MAX_ATOMIC_BUFFER_BINDINGS=%u)",
4424 caller, first, count, ctx->Const.MaxAtomicBufferBindings);
4425 return false;
4426 }
4427
4428 return true;
4429 }
4430
4431 /**
4432 * Unbind all atomic counter buffers in the range
4433 * <first> through <first>+<count>-1
4434 */
4435 static void
4436 unbind_atomic_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
4437 {
4438 for (int i = 0; i < count; i++)
4439 set_buffer_binding(ctx, &ctx->AtomicBufferBindings[first + i],
4440 NULL, -1, -1, GL_TRUE, 0);
4441 }
4442
4443 static void
4444 bind_atomic_buffers(struct gl_context *ctx,
4445 GLuint first,
4446 GLsizei count,
4447 const GLuint *buffers,
4448 bool range,
4449 const GLintptr *offsets,
4450 const GLsizeiptr *sizes,
4451 const char *caller)
4452 {
4453 if (!error_check_bind_atomic_buffers(ctx, first, count, caller))
4454 return;
4455
4456 /* Assume that at least one binding will be changed */
4457 FLUSH_VERTICES(ctx, 0);
4458 ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
4459
4460 if (!buffers) {
4461 /* The ARB_multi_bind spec says:
4462 *
4463 * "If <buffers> is NULL, all bindings from <first> through
4464 * <first>+<count>-1 are reset to their unbound (zero) state.
4465 * In this case, the offsets and sizes associated with the
4466 * binding points are set to default values, ignoring
4467 * <offsets> and <sizes>."
4468 */
4469 unbind_atomic_buffers(ctx, first, count);
4470 return;
4471 }
4472
4473 /* Note that the error semantics for multi-bind commands differ from
4474 * those of other GL commands.
4475 *
4476 * The Issues section in the ARB_multi_bind spec says:
4477 *
4478 * "(11) Typically, OpenGL specifies that if an error is generated by a
4479 * command, that command has no effect. This is somewhat
4480 * unfortunate for multi-bind commands, because it would require a
4481 * first pass to scan the entire list of bound objects for errors
4482 * and then a second pass to actually perform the bindings.
4483 * Should we have different error semantics?
4484 *
4485 * RESOLVED: Yes. In this specification, when the parameters for
4486 * one of the <count> binding points are invalid, that binding point
4487 * is not updated and an error will be generated. However, other
4488 * binding points in the same command will be updated if their
4489 * parameters are valid and no other error occurs."
4490 */
4491
4492 _mesa_HashLockMutex(ctx->Shared->BufferObjects);
4493
4494 for (int i = 0; i < count; i++) {
4495 struct gl_buffer_binding *binding =
4496 &ctx->AtomicBufferBindings[first + i];
4497 GLintptr offset = 0;
4498 GLsizeiptr size = 0;
4499
4500 if (range) {
4501 if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
4502 continue;
4503
4504 /* The ARB_multi_bind spec says:
4505 *
4506 * "An INVALID_VALUE error is generated by BindBuffersRange if any
4507 * pair of values in <offsets> and <sizes> does not respectively
4508 * satisfy the constraints described for those parameters for the
4509 * specified target, as described in section 6.7.1 (per binding)."
4510 *
4511 * Section 6.7.1 refers to table 6.5, which says:
4512 *
4513 * "┌───────────────────────────────────────────────────────────────┐
4514 * │ Atomic counter array bindings (see sec. 7.7.2) │
4515 * ├───────────────────────┬───────────────────────────────────────┤
4516 * │ ... │ ... │
4517 * │ offset restriction │ multiple of 4 │
4518 * │ ... │ ... │
4519 * │ size restriction │ none │
4520 * └───────────────────────┴───────────────────────────────────────┘"
4521 */
4522 if (offsets[i] & (ATOMIC_COUNTER_SIZE - 1)) {
4523 _mesa_error(ctx, GL_INVALID_VALUE,
4524 "glBindBuffersRange(offsets[%u]=%" PRId64
4525 " is misaligned; it must be a multiple of %d when "
4526 "target=GL_ATOMIC_COUNTER_BUFFER)",
4527 i, (int64_t) offsets[i], ATOMIC_COUNTER_SIZE);
4528 continue;
4529 }
4530
4531 offset = offsets[i];
4532 size = sizes[i];
4533 }
4534
4535 set_buffer_multi_binding(ctx, buffers, i, caller,
4536 binding, offset, size, range,
4537 USAGE_ATOMIC_COUNTER_BUFFER);
4538 }
4539
4540 _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
4541 }
4542
4543 static ALWAYS_INLINE void
4544 bind_buffer_range(GLenum target, GLuint index, GLuint buffer, GLintptr offset,
4545 GLsizeiptr size, bool no_error)
4546 {
4547 GET_CURRENT_CONTEXT(ctx);
4548 struct gl_buffer_object *bufObj;
4549
4550 if (MESA_VERBOSE & VERBOSE_API) {
4551 _mesa_debug(ctx, "glBindBufferRange(%s, %u, %u, %lu, %lu)\n",
4552 _mesa_enum_to_string(target), index, buffer,
4553 (unsigned long) offset, (unsigned long) size);
4554 }
4555
4556 if (buffer == 0) {
4557 bufObj = NULL;
4558 } else {
4559 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4560 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
4561 &bufObj, "glBindBufferRange"))
4562 return;
4563
4564 if (!no_error && !bufObj) {
4565 _mesa_error(ctx, GL_INVALID_OPERATION,
4566 "glBindBufferRange(invalid buffer=%u)", buffer);
4567 return;
4568 }
4569 }
4570
4571 if (no_error) {
4572 switch (target) {
4573 case GL_TRANSFORM_FEEDBACK_BUFFER:
4574 _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject,
4575 index, bufObj, offset, size);
4576 return;
4577 case GL_UNIFORM_BUFFER:
4578 bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
4579 return;
4580 case GL_SHADER_STORAGE_BUFFER:
4581 bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset,
4582 size);
4583 return;
4584 case GL_ATOMIC_COUNTER_BUFFER:
4585 bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size);
4586 return;
4587 default:
4588 unreachable("invalid BindBufferRange target with KHR_no_error");
4589 }
4590 } else {
4591 if (buffer != 0) {
4592 if (size <= 0) {
4593 _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)",
4594 (int) size);
4595 return;
4596 }
4597 }
4598
4599 switch (target) {
4600 case GL_TRANSFORM_FEEDBACK_BUFFER:
4601 if (!_mesa_validate_buffer_range_xfb(ctx,
4602 ctx->TransformFeedback.CurrentObject,
4603 index, bufObj, offset, size,
4604 false))
4605 return;
4606
4607 _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject,
4608 index, bufObj, offset, size);
4609 return;
4610 case GL_UNIFORM_BUFFER:
4611 bind_buffer_range_uniform_buffer_err(ctx, index, bufObj, offset,
4612 size);
4613 return;
4614 case GL_SHADER_STORAGE_BUFFER:
4615 bind_buffer_range_shader_storage_buffer_err(ctx, index, bufObj,
4616 offset, size);
4617 return;
4618 case GL_ATOMIC_COUNTER_BUFFER:
4619 bind_buffer_range_atomic_buffer_err(ctx, index, bufObj,
4620 offset, size);
4621 return;
4622 default:
4623 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
4624 return;
4625 }
4626 }
4627 }
4628
4629 void GLAPIENTRY
4630 _mesa_BindBufferRange_no_error(GLenum target, GLuint index, GLuint buffer,
4631 GLintptr offset, GLsizeiptr size)
4632 {
4633 bind_buffer_range(target, index, buffer, offset, size, true);
4634 }
4635
4636 void GLAPIENTRY
4637 _mesa_BindBufferRange(GLenum target, GLuint index,
4638 GLuint buffer, GLintptr offset, GLsizeiptr size)
4639 {
4640 bind_buffer_range(target, index, buffer, offset, size, false);
4641 }
4642
4643 void GLAPIENTRY
4644 _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
4645 {
4646 GET_CURRENT_CONTEXT(ctx);
4647 struct gl_buffer_object *bufObj;
4648
4649 if (MESA_VERBOSE & VERBOSE_API) {
4650 _mesa_debug(ctx, "glBindBufferBase(%s, %u, %u)\n",
4651 _mesa_enum_to_string(target), index, buffer);
4652 }
4653
4654 if (buffer == 0) {
4655 bufObj = NULL;
4656 } else {
4657 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4658 if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
4659 &bufObj, "glBindBufferBase"))
4660 return;
4661
4662 if (!bufObj) {
4663 _mesa_error(ctx, GL_INVALID_OPERATION,
4664 "glBindBufferBase(invalid buffer=%u)", buffer);
4665 return;
4666 }
4667 }
4668
4669 /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with
4670 * regards to BindBufferBase. It says (GL 3.1 core spec, page 63):
4671 *
4672 * "BindBufferBase is equivalent to calling BindBufferRange with offset
4673 * zero and size equal to the size of buffer."
4674 *
4675 * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230):
4676 *
4677 * "If the parameter (starting offset or size) was not specified when the
4678 * buffer object was bound, zero is returned."
4679 *
4680 * What happens if the size of the buffer changes? Does the size of the
4681 * buffer at the moment glBindBufferBase was called still play a role, like
4682 * the first quote would imply, or is the size meaningless in the
4683 * glBindBufferBase case like the second quote would suggest? The GL 4.1
4684 * core spec page 45 says:
4685 *
4686 * "It is equivalent to calling BindBufferRange with offset zero, while
4687 * size is determined by the size of the bound buffer at the time the
4688 * binding is used."
4689 *
4690 * My interpretation is that the GL 4.1 spec was a clarification of the
4691 * behavior, not a change. In particular, this choice will only make
4692 * rendering work in cases where it would have had undefined results.
4693 */
4694
4695 switch (target) {
4696 case GL_TRANSFORM_FEEDBACK_BUFFER:
4697 _mesa_bind_buffer_base_transform_feedback(ctx,
4698 ctx->TransformFeedback.CurrentObject,
4699 index, bufObj, false);
4700 return;
4701 case GL_UNIFORM_BUFFER:
4702 bind_buffer_base_uniform_buffer(ctx, index, bufObj);
4703 return;
4704 case GL_SHADER_STORAGE_BUFFER:
4705 bind_buffer_base_shader_storage_buffer(ctx, index, bufObj);
4706 return;
4707 case GL_ATOMIC_COUNTER_BUFFER:
4708 bind_buffer_base_atomic_buffer(ctx, index, bufObj);
4709 return;
4710 default:
4711 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
4712 return;
4713 }
4714 }
4715
4716 void GLAPIENTRY
4717 _mesa_BindBuffersRange(GLenum target, GLuint first, GLsizei count,
4718 const GLuint *buffers,
4719 const GLintptr *offsets, const GLsizeiptr *sizes)
4720 {
4721 GET_CURRENT_CONTEXT(ctx);
4722
4723 if (MESA_VERBOSE & VERBOSE_API) {
4724 _mesa_debug(ctx, "glBindBuffersRange(%s, %u, %d, %p, %p, %p)\n",
4725 _mesa_enum_to_string(target), first, count,
4726 buffers, offsets, sizes);
4727 }
4728
4729 switch (target) {
4730 case GL_TRANSFORM_FEEDBACK_BUFFER:
4731 bind_xfb_buffers(ctx, first, count, buffers, true, offsets, sizes,
4732 "glBindBuffersRange");
4733 return;
4734 case GL_UNIFORM_BUFFER:
4735 bind_uniform_buffers(ctx, first, count, buffers, true, offsets, sizes,
4736 "glBindBuffersRange");
4737 return;
4738 case GL_SHADER_STORAGE_BUFFER:
4739 bind_shader_storage_buffers(ctx, first, count, buffers, true, offsets, sizes,
4740 "glBindBuffersRange");
4741 return;
4742 case GL_ATOMIC_COUNTER_BUFFER:
4743 bind_atomic_buffers(ctx, first, count, buffers, true, offsets, sizes,
4744 "glBindBuffersRange");
4745 return;
4746 default:
4747 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersRange(target=%s)",
4748 _mesa_enum_to_string(target));
4749 break;
4750 }
4751 }
4752
4753 void GLAPIENTRY
4754 _mesa_BindBuffersBase(GLenum target, GLuint first, GLsizei count,
4755 const GLuint *buffers)
4756 {
4757 GET_CURRENT_CONTEXT(ctx);
4758
4759 if (MESA_VERBOSE & VERBOSE_API) {
4760 _mesa_debug(ctx, "glBindBuffersBase(%s, %u, %d, %p)\n",
4761 _mesa_enum_to_string(target), first, count, buffers);
4762 }
4763
4764 switch (target) {
4765 case GL_TRANSFORM_FEEDBACK_BUFFER:
4766 bind_xfb_buffers(ctx, first, count, buffers, false, NULL, NULL,
4767 "glBindBuffersBase");
4768 return;
4769 case GL_UNIFORM_BUFFER:
4770 bind_uniform_buffers(ctx, first, count, buffers, false, NULL, NULL,
4771 "glBindBuffersBase");
4772 return;
4773 case GL_SHADER_STORAGE_BUFFER:
4774 bind_shader_storage_buffers(ctx, first, count, buffers, false, NULL, NULL,
4775 "glBindBuffersBase");
4776 return;
4777 case GL_ATOMIC_COUNTER_BUFFER:
4778 bind_atomic_buffers(ctx, first, count, buffers, false, NULL, NULL,
4779 "glBindBuffersBase");
4780 return;
4781 default:
4782 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersBase(target=%s)",
4783 _mesa_enum_to_string(target));
4784 break;
4785 }
4786 }
4787
4788 static ALWAYS_INLINE void
4789 invalidate_buffer_subdata(struct gl_context *ctx,
4790 struct gl_buffer_object *bufObj, GLintptr offset,
4791 GLsizeiptr length)
4792 {
4793 if (ctx->Driver.InvalidateBufferSubData)
4794 ctx->Driver.InvalidateBufferSubData(ctx, bufObj, offset, length);
4795 }
4796
4797 void GLAPIENTRY
4798 _mesa_InvalidateBufferSubData_no_error(GLuint buffer, GLintptr offset,
4799 GLsizeiptr length)
4800 {
4801 GET_CURRENT_CONTEXT(ctx);
4802
4803 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4804 invalidate_buffer_subdata(ctx, bufObj, offset, length);
4805 }
4806
4807 void GLAPIENTRY
4808 _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset,
4809 GLsizeiptr length)
4810 {
4811 GET_CURRENT_CONTEXT(ctx);
4812 struct gl_buffer_object *bufObj;
4813 const GLintptr end = offset + length;
4814
4815 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
4816 * Profile) spec says:
4817 *
4818 * "An INVALID_VALUE error is generated if buffer is zero or is not the
4819 * name of an existing buffer object."
4820 */
4821 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4822 if (!bufObj || bufObj == &DummyBufferObject) {
4823 _mesa_error(ctx, GL_INVALID_VALUE,
4824 "glInvalidateBufferSubData(name = %u) invalid object",
4825 buffer);
4826 return;
4827 }
4828
4829 /* The GL_ARB_invalidate_subdata spec says:
4830 *
4831 * "An INVALID_VALUE error is generated if <offset> or <length> is
4832 * negative, or if <offset> + <length> is greater than the value of
4833 * BUFFER_SIZE."
4834 */
4835 if (offset < 0 || length < 0 || end > bufObj->Size) {
4836 _mesa_error(ctx, GL_INVALID_VALUE,
4837 "glInvalidateBufferSubData(invalid offset or length)");
4838 return;
4839 }
4840
4841 /* The OpenGL 4.4 (Core Profile) spec says:
4842 *
4843 * "An INVALID_OPERATION error is generated if buffer is currently
4844 * mapped by MapBuffer or if the invalidate range intersects the range
4845 * currently mapped by MapBufferRange, unless it was mapped
4846 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
4847 */
4848 if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) &&
4849 bufferobj_range_mapped(bufObj, offset, length)) {
4850 _mesa_error(ctx, GL_INVALID_OPERATION,
4851 "glInvalidateBufferSubData(intersection with mapped "
4852 "range)");
4853 return;
4854 }
4855
4856 invalidate_buffer_subdata(ctx, bufObj, offset, length);
4857 }
4858
4859 void GLAPIENTRY
4860 _mesa_InvalidateBufferData_no_error(GLuint buffer)
4861 {
4862 GET_CURRENT_CONTEXT(ctx);
4863
4864 struct gl_buffer_object *bufObj =_mesa_lookup_bufferobj(ctx, buffer);
4865 invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size);
4866 }
4867
4868 void GLAPIENTRY
4869 _mesa_InvalidateBufferData(GLuint buffer)
4870 {
4871 GET_CURRENT_CONTEXT(ctx);
4872 struct gl_buffer_object *bufObj;
4873
4874 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
4875 * Profile) spec says:
4876 *
4877 * "An INVALID_VALUE error is generated if buffer is zero or is not the
4878 * name of an existing buffer object."
4879 */
4880 bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4881 if (!bufObj || bufObj == &DummyBufferObject) {
4882 _mesa_error(ctx, GL_INVALID_VALUE,
4883 "glInvalidateBufferData(name = %u) invalid object",
4884 buffer);
4885 return;
4886 }
4887
4888 /* The OpenGL 4.4 (Core Profile) spec says:
4889 *
4890 * "An INVALID_OPERATION error is generated if buffer is currently
4891 * mapped by MapBuffer or if the invalidate range intersects the range
4892 * currently mapped by MapBufferRange, unless it was mapped
4893 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
4894 */
4895 if (_mesa_check_disallowed_mapping(bufObj)) {
4896 _mesa_error(ctx, GL_INVALID_OPERATION,
4897 "glInvalidateBufferData(intersection with mapped "
4898 "range)");
4899 return;
4900 }
4901
4902 invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size);
4903 }
4904
4905 static void
4906 buffer_page_commitment(struct gl_context *ctx,
4907 struct gl_buffer_object *bufferObj,
4908 GLintptr offset, GLsizeiptr size,
4909 GLboolean commit, const char *func)
4910 {
4911 if (!(bufferObj->StorageFlags & GL_SPARSE_STORAGE_BIT_ARB)) {
4912 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(not a sparse buffer object)",
4913 func);
4914 return;
4915 }
4916
4917 if (size < 0 || size > bufferObj->Size ||
4918 offset < 0 || offset > bufferObj->Size - size) {
4919 _mesa_error(ctx, GL_INVALID_VALUE, "%s(out of bounds)",
4920 func);
4921 return;
4922 }
4923
4924 /* The GL_ARB_sparse_buffer extension specification says:
4925 *
4926 * "INVALID_VALUE is generated by BufferPageCommitmentARB if <offset> is
4927 * not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB, or if <size>
4928 * is not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB and does
4929 * not extend to the end of the buffer's data store."
4930 */
4931 if (offset % ctx->Const.SparseBufferPageSize != 0) {
4932 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset not aligned to page size)",
4933 func);
4934 return;
4935 }
4936
4937 if (size % ctx->Const.SparseBufferPageSize != 0 &&
4938 offset + size != bufferObj->Size) {
4939 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size not aligned to page size)",
4940 func);
4941 return;
4942 }
4943
4944 ctx->Driver.BufferPageCommitment(ctx, bufferObj, offset, size, commit);
4945 }
4946
4947 void GLAPIENTRY
4948 _mesa_BufferPageCommitmentARB(GLenum target, GLintptr offset, GLsizeiptr size,
4949 GLboolean commit)
4950 {
4951 GET_CURRENT_CONTEXT(ctx);
4952 struct gl_buffer_object *bufferObj;
4953
4954 bufferObj = get_buffer(ctx, "glBufferPageCommitmentARB", target,
4955 GL_INVALID_ENUM);
4956 if (!bufferObj)
4957 return;
4958
4959 buffer_page_commitment(ctx, bufferObj, offset, size, commit,
4960 "glBufferPageCommitmentARB");
4961 }
4962
4963 void GLAPIENTRY
4964 _mesa_NamedBufferPageCommitmentARB(GLuint buffer, GLintptr offset,
4965 GLsizeiptr size, GLboolean commit)
4966 {
4967 GET_CURRENT_CONTEXT(ctx);
4968 struct gl_buffer_object *bufferObj;
4969
4970 bufferObj = _mesa_lookup_bufferobj(ctx, buffer);
4971 if (!bufferObj || bufferObj == &DummyBufferObject) {
4972 /* Note: the extension spec is not clear about the excpected error value. */
4973 _mesa_error(ctx, GL_INVALID_VALUE,
4974 "glNamedBufferPageCommitmentARB(name = %u) invalid object",
4975 buffer);
4976 return;
4977 }
4978
4979 buffer_page_commitment(ctx, bufferObj, offset, size, commit,
4980 "glNamedBufferPageCommitmentARB");
4981 }
4982
4983 void GLAPIENTRY
4984 _mesa_NamedBufferPageCommitmentEXT(GLuint buffer, GLintptr offset,
4985 GLsizeiptr size, GLboolean commit)
4986 {
4987 GET_CURRENT_CONTEXT(ctx);
4988 struct gl_buffer_object *bufferObj;
4989
4990 /* Use NamedBuffer* functions logic from EXT_direct_state_access */
4991 if (buffer != 0) {
4992 bufferObj = _mesa_lookup_bufferobj(ctx, buffer);
4993 if (!_mesa_handle_bind_buffer_gen(ctx, buffer, &bufferObj,
4994 "glNamedBufferPageCommitmentEXT"))
4995 return;
4996 } else {
4997 /* GL_EXT_direct_state_access says about NamedBuffer* functions:
4998 *
4999 * There is no buffer corresponding to the name zero, these commands
5000 * generate the INVALID_OPERATION error if the buffer parameter is
5001 * zero.
5002 */
5003 _mesa_error(ctx, GL_INVALID_OPERATION,
5004 "glNamedBufferPageCommitmentEXT(buffer = 0)");
5005 return;
5006 }
5007 buffer_page_commitment(ctx, bufferObj, offset, size, commit,
5008 "glNamedBufferPageCommitmentEXT");
5009 }