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