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