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