2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
29 * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
30 * \author Brian Paul, Ian Romanick
34 #include <inttypes.h> /* for PRId64 macro */
35 #include "util/debug.h"
41 #include "bufferobj.h"
42 #include "externalobjects.h"
45 #include "glformats.h"
47 #include "transformfeedback.h"
49 #include "util/u_atomic.h"
54 /*#define BOUNDS_CHECK*/
58 * We count the number of buffer modification calls to check for
59 * inefficient buffer use. This is the number of such calls before we
62 #define BUFFER_WARNING_CALL_COUNT 4
66 * Helper to warn of possible performance issues, such as frequently
67 * updating a buffer created with GL_STATIC_DRAW. Called via the macro
71 buffer_usage_warning(struct gl_context
*ctx
, GLuint
*id
, const char *fmt
, ...)
76 _mesa_gl_vdebug(ctx
, id
,
77 MESA_DEBUG_SOURCE_API
,
78 MESA_DEBUG_TYPE_PERFORMANCE
,
79 MESA_DEBUG_SEVERITY_MEDIUM
,
84 #define BUFFER_USAGE_WARNING(CTX, FMT, ...) \
86 static GLuint id = 0; \
87 buffer_usage_warning(CTX, &id, FMT, ##__VA_ARGS__); \
92 * Used as a placeholder for buffer objects between glGenBuffers() and
93 * glBindBuffer() so that glIsBuffer() can work correctly.
95 static struct gl_buffer_object DummyBufferObject
;
99 * Return pointer to address of a buffer object target.
100 * \param ctx the GL context
101 * \param target the buffer object target to be retrieved.
102 * \return pointer to pointer to the buffer object bound to \c target in the
103 * specified context or \c NULL if \c target is invalid.
105 static inline struct gl_buffer_object
**
106 get_buffer_target(struct gl_context
*ctx
, GLenum target
)
108 /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0.
110 if (!_mesa_is_desktop_gl(ctx
) && !_mesa_is_gles3(ctx
)
111 && target
!= GL_ARRAY_BUFFER
&& target
!= GL_ELEMENT_ARRAY_BUFFER
)
115 case GL_ARRAY_BUFFER_ARB
:
116 return &ctx
->Array
.ArrayBufferObj
;
117 case GL_ELEMENT_ARRAY_BUFFER_ARB
:
118 return &ctx
->Array
.VAO
->IndexBufferObj
;
119 case GL_PIXEL_PACK_BUFFER_EXT
:
120 return &ctx
->Pack
.BufferObj
;
121 case GL_PIXEL_UNPACK_BUFFER_EXT
:
122 return &ctx
->Unpack
.BufferObj
;
123 case GL_COPY_READ_BUFFER
:
124 return &ctx
->CopyReadBuffer
;
125 case GL_COPY_WRITE_BUFFER
:
126 return &ctx
->CopyWriteBuffer
;
127 case GL_QUERY_BUFFER
:
128 if (_mesa_has_ARB_query_buffer_object(ctx
))
129 return &ctx
->QueryBuffer
;
131 case GL_DRAW_INDIRECT_BUFFER
:
132 if ((ctx
->API
== API_OPENGL_CORE
&&
133 ctx
->Extensions
.ARB_draw_indirect
) ||
134 _mesa_is_gles31(ctx
)) {
135 return &ctx
->DrawIndirectBuffer
;
138 case GL_PARAMETER_BUFFER_ARB
:
139 if (_mesa_has_ARB_indirect_parameters(ctx
)) {
140 return &ctx
->ParameterBuffer
;
143 case GL_DISPATCH_INDIRECT_BUFFER
:
144 if (_mesa_has_compute_shaders(ctx
)) {
145 return &ctx
->DispatchIndirectBuffer
;
148 case GL_TRANSFORM_FEEDBACK_BUFFER
:
149 if (ctx
->Extensions
.EXT_transform_feedback
) {
150 return &ctx
->TransformFeedback
.CurrentBuffer
;
153 case GL_TEXTURE_BUFFER
:
154 if (_mesa_has_ARB_texture_buffer_object(ctx
) ||
155 _mesa_has_OES_texture_buffer(ctx
)) {
156 return &ctx
->Texture
.BufferObject
;
159 case GL_UNIFORM_BUFFER
:
160 if (ctx
->Extensions
.ARB_uniform_buffer_object
) {
161 return &ctx
->UniformBuffer
;
164 case GL_SHADER_STORAGE_BUFFER
:
165 if (ctx
->Extensions
.ARB_shader_storage_buffer_object
) {
166 return &ctx
->ShaderStorageBuffer
;
169 case GL_ATOMIC_COUNTER_BUFFER
:
170 if (ctx
->Extensions
.ARB_shader_atomic_counters
) {
171 return &ctx
->AtomicBuffer
;
174 case GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
:
175 if (ctx
->Extensions
.AMD_pinned_memory
) {
176 return &ctx
->ExternalVirtualMemoryBuffer
;
187 * Get the buffer object bound to the specified target in a GL context.
188 * \param ctx the GL context
189 * \param target the buffer object target to be retrieved.
190 * \param error the GL error to record if target is illegal.
191 * \return pointer to the buffer object bound to \c target in the
192 * specified context or \c NULL if \c target is invalid.
194 static inline struct gl_buffer_object
*
195 get_buffer(struct gl_context
*ctx
, const char *func
, GLenum target
,
198 struct gl_buffer_object
**bufObj
= get_buffer_target(ctx
, target
);
201 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
205 if (!_mesa_is_bufferobj(*bufObj
)) {
206 _mesa_error(ctx
, error
, "%s(no buffer bound)", func
);
215 * Convert a GLbitfield describing the mapped buffer access flags
216 * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
219 simplified_access_mode(struct gl_context
*ctx
, GLbitfield access
)
221 const GLbitfield rwFlags
= GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
;
222 if ((access
& rwFlags
) == rwFlags
)
223 return GL_READ_WRITE
;
224 if ((access
& GL_MAP_READ_BIT
) == GL_MAP_READ_BIT
)
226 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
)
227 return GL_WRITE_ONLY
;
229 /* Otherwise, AccessFlags is zero (the default state).
231 * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says:
233 * Name Type Initial Value Legal Values
235 * BUFFER_ACCESS enum READ_WRITE READ_ONLY, WRITE_ONLY
238 * However, table 6.8 in the GL_OES_mapbuffer extension says:
240 * Get Value Type Get Command Value Description
241 * --------- ---- ----------- ----- -----------
242 * BUFFER_ACCESS_OES Z1 GetBufferParameteriv WRITE_ONLY_OES buffer map flag
244 * The difference is because GL_OES_mapbuffer only supports mapping buffers
249 return _mesa_is_gles(ctx
) ? GL_WRITE_ONLY
: GL_READ_WRITE
;
254 * Test if the buffer is mapped, and if so, if the mapped range overlaps the
256 * The regions do not overlap if and only if the end of the given
257 * region is before the mapped region or the start of the given region
258 * is after the mapped region.
260 * \param obj Buffer object target on which to operate.
261 * \param offset Offset of the first byte of the subdata range.
262 * \param size Size, in bytes, of the subdata range.
263 * \return true if ranges overlap, false otherwise
267 bufferobj_range_mapped(const struct gl_buffer_object
*obj
,
268 GLintptr offset
, GLsizeiptr size
)
270 if (_mesa_bufferobj_mapped(obj
, MAP_USER
)) {
271 const GLintptr end
= offset
+ size
;
272 const GLintptr mapEnd
= obj
->Mappings
[MAP_USER
].Offset
+
273 obj
->Mappings
[MAP_USER
].Length
;
275 if (!(end
<= obj
->Mappings
[MAP_USER
].Offset
|| offset
>= mapEnd
)) {
284 * Tests the subdata range parameters and sets the GL error code for
285 * \c glBufferSubDataARB, \c glGetBufferSubDataARB and
286 * \c glClearBufferSubData.
288 * \param ctx GL context.
289 * \param bufObj The buffer object.
290 * \param offset Offset of the first byte of the subdata range.
291 * \param size Size, in bytes, of the subdata range.
292 * \param mappedRange If true, checks if an overlapping range is mapped.
293 * If false, checks if buffer is mapped.
294 * \param caller Name of calling function for recording errors.
295 * \return false if error, true otherwise
297 * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData
300 buffer_object_subdata_range_good(struct gl_context
*ctx
,
301 const struct gl_buffer_object
*bufObj
,
302 GLintptr offset
, GLsizeiptr size
,
303 bool mappedRange
, const char *caller
)
306 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(size < 0)", caller
);
311 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(offset < 0)", caller
);
315 if (offset
+ size
> bufObj
->Size
) {
316 _mesa_error(ctx
, GL_INVALID_VALUE
,
317 "%s(offset %lu + size %lu > buffer size %lu)", caller
,
318 (unsigned long) offset
,
319 (unsigned long) size
,
320 (unsigned long) bufObj
->Size
);
324 if (bufObj
->Mappings
[MAP_USER
].AccessFlags
& GL_MAP_PERSISTENT_BIT
)
328 if (bufferobj_range_mapped(bufObj
, offset
, size
)) {
329 _mesa_error(ctx
, GL_INVALID_OPERATION
,
330 "%s(range is mapped without persistent bit)",
336 if (_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
337 _mesa_error(ctx
, GL_INVALID_OPERATION
,
338 "%s(buffer is mapped without persistent bit)",
349 * Test the format and type parameters and set the GL error code for
350 * \c glClearBufferData and \c glClearBufferSubData.
352 * \param ctx GL context.
353 * \param internalformat Format to which the data is to be converted.
354 * \param format Format of the supplied data.
355 * \param type Type of the supplied data.
356 * \param caller Name of calling function for recording errors.
357 * \return If internalformat, format and type are legal the mesa_format
358 * corresponding to internalformat, otherwise MESA_FORMAT_NONE.
360 * \sa glClearBufferData and glClearBufferSubData
363 validate_clear_buffer_format(struct gl_context
*ctx
,
364 GLenum internalformat
,
365 GLenum format
, GLenum type
,
368 mesa_format mesaFormat
;
369 GLenum errorFormatType
;
371 mesaFormat
= _mesa_validate_texbuffer_format(ctx
, internalformat
);
372 if (mesaFormat
== MESA_FORMAT_NONE
) {
373 _mesa_error(ctx
, GL_INVALID_ENUM
,
374 "%s(invalid internalformat)", caller
);
375 return MESA_FORMAT_NONE
;
378 /* NOTE: not mentioned in ARB_clear_buffer_object but according to
379 * EXT_texture_integer there is no conversion between integer and
380 * non-integer formats
382 if (_mesa_is_enum_format_signed_int(format
) !=
383 _mesa_is_format_integer_color(mesaFormat
)) {
384 _mesa_error(ctx
, GL_INVALID_OPERATION
,
385 "%s(integer vs non-integer)", caller
);
386 return MESA_FORMAT_NONE
;
389 if (!_mesa_is_color_format(format
)) {
390 _mesa_error(ctx
, GL_INVALID_ENUM
,
391 "%s(format is not a color format)", caller
);
392 return MESA_FORMAT_NONE
;
395 errorFormatType
= _mesa_error_check_format_and_type(ctx
, format
, type
);
396 if (errorFormatType
!= GL_NO_ERROR
) {
397 _mesa_error(ctx
, GL_INVALID_ENUM
,
398 "%s(invalid format or type)", caller
);
399 return MESA_FORMAT_NONE
;
407 * Convert user-specified clear value to the specified internal format.
409 * \param ctx GL context.
410 * \param internalformat Format to which the data is converted.
411 * \param clearValue Points to the converted clear value.
412 * \param format Format of the supplied data.
413 * \param type Type of the supplied data.
414 * \param data Data which is to be converted to internalformat.
415 * \param caller Name of calling function for recording errors.
416 * \return true if data could be converted, false otherwise.
418 * \sa glClearBufferData, glClearBufferSubData
421 convert_clear_buffer_data(struct gl_context
*ctx
,
422 mesa_format internalformat
,
423 GLubyte
*clearValue
, GLenum format
, GLenum type
,
424 const GLvoid
*data
, const char *caller
)
426 GLenum internalformatBase
= _mesa_get_format_base_format(internalformat
);
428 if (_mesa_texstore(ctx
, 1, internalformatBase
, internalformat
,
429 0, &clearValue
, 1, 1, 1,
430 format
, type
, data
, &ctx
->Unpack
)) {
434 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s", caller
);
441 * Allocate and initialize a new buffer object.
443 * Default callback for the \c dd_function_table::NewBufferObject() hook.
445 static struct gl_buffer_object
*
446 _mesa_new_buffer_object(struct gl_context
*ctx
, GLuint name
)
448 struct gl_buffer_object
*obj
= MALLOC_STRUCT(gl_buffer_object
);
452 _mesa_initialize_buffer_object(ctx
, obj
, name
);
458 * Delete a buffer object.
460 * Default callback for the \c dd_function_table::DeleteBuffer() hook.
463 _mesa_delete_buffer_object(struct gl_context
*ctx
,
464 struct gl_buffer_object
*bufObj
)
468 vbo_delete_minmax_cache(bufObj
);
469 _mesa_align_free(bufObj
->Data
);
471 /* assign strange values here to help w/ debugging */
472 bufObj
->RefCount
= -1000;
475 simple_mtx_destroy(&bufObj
->MinMaxCacheMutex
);
483 * Set ptr to bufObj w/ reference counting.
484 * This is normally only called from the _mesa_reference_buffer_object() macro
485 * when there's a real pointer change.
488 _mesa_reference_buffer_object_(struct gl_context
*ctx
,
489 struct gl_buffer_object
**ptr
,
490 struct gl_buffer_object
*bufObj
)
493 /* Unreference the old buffer */
494 struct gl_buffer_object
*oldObj
= *ptr
;
496 if (p_atomic_dec_zero(&oldObj
->RefCount
)) {
497 assert(ctx
->Driver
.DeleteBuffer
);
498 ctx
->Driver
.DeleteBuffer(ctx
, oldObj
);
506 /* reference new buffer */
507 p_atomic_inc(&bufObj
->RefCount
);
514 * Get the value of MESA_NO_MINMAX_CACHE.
517 get_no_minmax_cache()
519 static bool read
= false;
520 static bool disable
= false;
523 disable
= env_var_as_boolean("MESA_NO_MINMAX_CACHE", false);
532 * Initialize a buffer object to default values.
535 _mesa_initialize_buffer_object(struct gl_context
*ctx
,
536 struct gl_buffer_object
*obj
,
539 memset(obj
, 0, sizeof(struct gl_buffer_object
));
542 obj
->Usage
= GL_STATIC_DRAW_ARB
;
544 simple_mtx_init(&obj
->MinMaxCacheMutex
, mtx_plain
);
545 if (get_no_minmax_cache())
546 obj
->UsageHistory
|= USAGE_DISABLE_MINMAX_CACHE
;
552 * Callback called from _mesa_HashWalk()
555 count_buffer_size(GLuint key
, void *data
, void *userData
)
557 const struct gl_buffer_object
*bufObj
=
558 (const struct gl_buffer_object
*) data
;
559 GLuint
*total
= (GLuint
*) userData
;
562 *total
= *total
+ bufObj
->Size
;
567 * Compute total size (in bytes) of all buffer objects for the given context.
568 * For debugging purposes.
571 _mesa_total_buffer_object_memory(struct gl_context
*ctx
)
575 _mesa_HashWalk(ctx
->Shared
->BufferObjects
, count_buffer_size
, &total
);
582 * Allocate space for and store data in a buffer object. Any data that was
583 * previously stored in the buffer object is lost. If \c data is \c NULL,
584 * memory will be allocated, but no copy will occur.
586 * This is the default callback for \c dd_function_table::BufferData()
587 * Note that all GL error checking will have been done already.
589 * \param ctx GL context.
590 * \param target Buffer object target on which to operate.
591 * \param size Size, in bytes, of the new data store.
592 * \param data Pointer to the data to store in the buffer object. This
593 * pointer may be \c NULL.
594 * \param usage Hints about how the data will be used.
595 * \param bufObj Object to be used.
597 * \return GL_TRUE for success, GL_FALSE for failure
598 * \sa glBufferDataARB, dd_function_table::BufferData.
601 buffer_data_fallback(struct gl_context
*ctx
, GLenum target
, GLsizeiptr size
,
602 const GLvoid
*data
, GLenum usage
, GLenum storageFlags
,
603 struct gl_buffer_object
*bufObj
)
609 _mesa_align_free( bufObj
->Data
);
611 new_data
= _mesa_align_malloc( size
, ctx
->Const
.MinMapBufferAlignment
);
613 bufObj
->Data
= (GLubyte
*) new_data
;
615 bufObj
->Usage
= usage
;
616 bufObj
->StorageFlags
= storageFlags
;
619 memcpy( bufObj
->Data
, data
, size
);
631 * Replace data in a subrange of buffer object. If the data range
632 * specified by \c size + \c offset extends beyond the end of the buffer or
633 * if \c data is \c NULL, no copy is performed.
635 * This is the default callback for \c dd_function_table::BufferSubData()
636 * Note that all GL error checking will have been done already.
638 * \param ctx GL context.
639 * \param offset Offset of the first byte to be modified.
640 * \param size Size, in bytes, of the data range.
641 * \param data Pointer to the data to store in the buffer object.
642 * \param bufObj Object to be used.
644 * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
647 buffer_sub_data_fallback(struct gl_context
*ctx
, GLintptr offset
,
648 GLsizeiptr size
, const GLvoid
*data
,
649 struct gl_buffer_object
*bufObj
)
653 /* this should have been caught in _mesa_BufferSubData() */
654 assert(size
+ offset
<= bufObj
->Size
);
657 memcpy( (GLubyte
*) bufObj
->Data
+ offset
, data
, size
);
663 * Retrieve data from a subrange of buffer object. If the data range
664 * specified by \c size + \c offset extends beyond the end of the buffer or
665 * if \c data is \c NULL, no copy is performed.
667 * This is the default callback for \c dd_function_table::GetBufferSubData()
668 * Note that all GL error checking will have been done already.
670 * \param ctx GL context.
671 * \param target Buffer object target on which to operate.
672 * \param offset Offset of the first byte to be fetched.
673 * \param size Size, in bytes, of the data range.
674 * \param data Destination for data
675 * \param bufObj Object to be used.
677 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
680 buffer_get_subdata(struct gl_context
*ctx
, GLintptrARB offset
,
681 GLsizeiptrARB size
, GLvoid
*data
,
682 struct gl_buffer_object
*bufObj
)
686 if (bufObj
->Data
&& ((GLsizeiptrARB
) (size
+ offset
) <= bufObj
->Size
)) {
687 memcpy( data
, (GLubyte
*) bufObj
->Data
+ offset
, size
);
693 * Clear a subrange of the buffer object with copies of the supplied data.
694 * If data is NULL the buffer is filled with zeros.
696 * This is the default callback for \c dd_function_table::ClearBufferSubData()
697 * Note that all GL error checking will have been done already.
699 * \param ctx GL context.
700 * \param offset Offset of the first byte to be cleared.
701 * \param size Size, in bytes, of the to be cleared range.
702 * \param clearValue Source of the data.
703 * \param clearValueSize Size, in bytes, of the supplied data.
704 * \param bufObj Object to be cleared.
706 * \sa glClearBufferSubData, glClearBufferData and
707 * dd_function_table::ClearBufferSubData.
710 _mesa_ClearBufferSubData_sw(struct gl_context
*ctx
,
711 GLintptr offset
, GLsizeiptr size
,
712 const GLvoid
*clearValue
,
713 GLsizeiptr clearValueSize
,
714 struct gl_buffer_object
*bufObj
)
719 assert(ctx
->Driver
.MapBufferRange
);
720 dest
= ctx
->Driver
.MapBufferRange(ctx
, offset
, size
,
722 GL_MAP_INVALIDATE_RANGE_BIT
,
723 bufObj
, MAP_INTERNAL
);
726 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glClearBuffer[Sub]Data");
730 if (clearValue
== NULL
) {
731 /* Clear with zeros, per the spec */
732 memset(dest
, 0, size
);
733 ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, MAP_INTERNAL
);
737 for (i
= 0; i
< size
/clearValueSize
; ++i
) {
738 memcpy(dest
, clearValue
, clearValueSize
);
739 dest
+= clearValueSize
;
742 ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, MAP_INTERNAL
);
747 * Default fallback for \c dd_function_table::MapBufferRange().
748 * Called via glMapBufferRange().
751 map_buffer_range_fallback(struct gl_context
*ctx
, GLintptr offset
,
752 GLsizeiptr length
, GLbitfield access
,
753 struct gl_buffer_object
*bufObj
,
754 gl_map_buffer_index index
)
757 assert(!_mesa_bufferobj_mapped(bufObj
, index
));
758 /* Just return a direct pointer to the data */
759 bufObj
->Mappings
[index
].Pointer
= bufObj
->Data
+ offset
;
760 bufObj
->Mappings
[index
].Length
= length
;
761 bufObj
->Mappings
[index
].Offset
= offset
;
762 bufObj
->Mappings
[index
].AccessFlags
= access
;
763 return bufObj
->Mappings
[index
].Pointer
;
768 * Default fallback for \c dd_function_table::FlushMappedBufferRange().
769 * Called via glFlushMappedBufferRange().
772 flush_mapped_buffer_range_fallback(struct gl_context
*ctx
,
773 GLintptr offset
, GLsizeiptr length
,
774 struct gl_buffer_object
*obj
,
775 gl_map_buffer_index index
)
787 * Default callback for \c dd_function_table::UnmapBuffer().
789 * The input parameters will have been already tested for errors.
791 * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
794 unmap_buffer_fallback(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
795 gl_map_buffer_index index
)
798 /* XXX we might assert here that bufObj->Pointer is non-null */
799 bufObj
->Mappings
[index
].Pointer
= NULL
;
800 bufObj
->Mappings
[index
].Length
= 0;
801 bufObj
->Mappings
[index
].Offset
= 0;
802 bufObj
->Mappings
[index
].AccessFlags
= 0x0;
808 * Default fallback for \c dd_function_table::CopyBufferSubData().
809 * Called via glCopyBufferSubData().
812 copy_buffer_sub_data_fallback(struct gl_context
*ctx
,
813 struct gl_buffer_object
*src
,
814 struct gl_buffer_object
*dst
,
815 GLintptr readOffset
, GLintptr writeOffset
,
818 GLubyte
*srcPtr
, *dstPtr
;
821 srcPtr
= dstPtr
= ctx
->Driver
.MapBufferRange(ctx
, 0, src
->Size
,
823 GL_MAP_WRITE_BIT
, src
,
829 srcPtr
+= readOffset
;
830 dstPtr
+= writeOffset
;
832 srcPtr
= ctx
->Driver
.MapBufferRange(ctx
, readOffset
, size
,
833 GL_MAP_READ_BIT
, src
,
835 dstPtr
= ctx
->Driver
.MapBufferRange(ctx
, writeOffset
, size
,
837 GL_MAP_INVALIDATE_RANGE_BIT
), dst
,
841 /* Note: the src and dst regions will never overlap. Trying to do so
842 * would generate GL_INVALID_VALUE earlier.
844 if (srcPtr
&& dstPtr
)
845 memcpy(dstPtr
, srcPtr
, size
);
847 ctx
->Driver
.UnmapBuffer(ctx
, src
, MAP_INTERNAL
);
849 ctx
->Driver
.UnmapBuffer(ctx
, dst
, MAP_INTERNAL
);
855 * Initialize the state associated with buffer objects
858 _mesa_init_buffer_objects( struct gl_context
*ctx
)
862 memset(&DummyBufferObject
, 0, sizeof(DummyBufferObject
));
863 simple_mtx_init(&DummyBufferObject
.MinMaxCacheMutex
, mtx_plain
);
864 DummyBufferObject
.RefCount
= 1000*1000*1000; /* never delete */
866 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
,
867 ctx
->Shared
->NullBufferObj
);
869 _mesa_reference_buffer_object(ctx
, &ctx
->CopyReadBuffer
,
870 ctx
->Shared
->NullBufferObj
);
871 _mesa_reference_buffer_object(ctx
, &ctx
->CopyWriteBuffer
,
872 ctx
->Shared
->NullBufferObj
);
874 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
,
875 ctx
->Shared
->NullBufferObj
);
877 _mesa_reference_buffer_object(ctx
, &ctx
->ShaderStorageBuffer
,
878 ctx
->Shared
->NullBufferObj
);
880 _mesa_reference_buffer_object(ctx
, &ctx
->AtomicBuffer
,
881 ctx
->Shared
->NullBufferObj
);
883 _mesa_reference_buffer_object(ctx
, &ctx
->DrawIndirectBuffer
,
884 ctx
->Shared
->NullBufferObj
);
886 _mesa_reference_buffer_object(ctx
, &ctx
->ParameterBuffer
,
887 ctx
->Shared
->NullBufferObj
);
889 _mesa_reference_buffer_object(ctx
, &ctx
->DispatchIndirectBuffer
,
890 ctx
->Shared
->NullBufferObj
);
892 _mesa_reference_buffer_object(ctx
, &ctx
->QueryBuffer
,
893 ctx
->Shared
->NullBufferObj
);
895 for (i
= 0; i
< MAX_COMBINED_UNIFORM_BUFFERS
; i
++) {
896 _mesa_reference_buffer_object(ctx
,
897 &ctx
->UniformBufferBindings
[i
].BufferObject
,
898 ctx
->Shared
->NullBufferObj
);
899 ctx
->UniformBufferBindings
[i
].Offset
= -1;
900 ctx
->UniformBufferBindings
[i
].Size
= -1;
903 for (i
= 0; i
< MAX_COMBINED_SHADER_STORAGE_BUFFERS
; i
++) {
904 _mesa_reference_buffer_object(ctx
,
905 &ctx
->ShaderStorageBufferBindings
[i
].BufferObject
,
906 ctx
->Shared
->NullBufferObj
);
907 ctx
->ShaderStorageBufferBindings
[i
].Offset
= -1;
908 ctx
->ShaderStorageBufferBindings
[i
].Size
= -1;
911 for (i
= 0; i
< MAX_COMBINED_ATOMIC_BUFFERS
; i
++) {
912 _mesa_reference_buffer_object(ctx
,
913 &ctx
->AtomicBufferBindings
[i
].BufferObject
,
914 ctx
->Shared
->NullBufferObj
);
915 ctx
->AtomicBufferBindings
[i
].Offset
= 0;
916 ctx
->AtomicBufferBindings
[i
].Size
= 0;
922 _mesa_free_buffer_objects( struct gl_context
*ctx
)
926 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
, NULL
);
928 _mesa_reference_buffer_object(ctx
, &ctx
->CopyReadBuffer
, NULL
);
929 _mesa_reference_buffer_object(ctx
, &ctx
->CopyWriteBuffer
, NULL
);
931 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
, NULL
);
933 _mesa_reference_buffer_object(ctx
, &ctx
->ShaderStorageBuffer
, NULL
);
935 _mesa_reference_buffer_object(ctx
, &ctx
->AtomicBuffer
, NULL
);
937 _mesa_reference_buffer_object(ctx
, &ctx
->DrawIndirectBuffer
, NULL
);
939 _mesa_reference_buffer_object(ctx
, &ctx
->ParameterBuffer
, NULL
);
941 _mesa_reference_buffer_object(ctx
, &ctx
->DispatchIndirectBuffer
, NULL
);
943 _mesa_reference_buffer_object(ctx
, &ctx
->QueryBuffer
, NULL
);
945 for (i
= 0; i
< MAX_COMBINED_UNIFORM_BUFFERS
; i
++) {
946 _mesa_reference_buffer_object(ctx
,
947 &ctx
->UniformBufferBindings
[i
].BufferObject
,
951 for (i
= 0; i
< MAX_COMBINED_SHADER_STORAGE_BUFFERS
; i
++) {
952 _mesa_reference_buffer_object(ctx
,
953 &ctx
->ShaderStorageBufferBindings
[i
].BufferObject
,
957 for (i
= 0; i
< MAX_COMBINED_ATOMIC_BUFFERS
; i
++) {
958 _mesa_reference_buffer_object(ctx
,
959 &ctx
->AtomicBufferBindings
[i
].BufferObject
,
966 _mesa_handle_bind_buffer_gen(struct gl_context
*ctx
,
968 struct gl_buffer_object
**buf_handle
,
971 struct gl_buffer_object
*buf
= *buf_handle
;
973 if (!buf
&& (ctx
->API
== API_OPENGL_CORE
)) {
974 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(non-gen name)", caller
);
978 if (!buf
|| buf
== &DummyBufferObject
) {
979 /* If this is a new buffer object id, or one which was generated but
980 * never used before, allocate a buffer object now.
982 buf
= ctx
->Driver
.NewBufferObject(ctx
, buffer
);
984 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s", caller
);
987 _mesa_HashInsert(ctx
->Shared
->BufferObjects
, buffer
, buf
);
995 * Bind the specified target to buffer for the specified context.
996 * Called by glBindBuffer() and other functions.
999 bind_buffer_object(struct gl_context
*ctx
,
1000 struct gl_buffer_object
**bindTarget
, GLuint buffer
)
1002 struct gl_buffer_object
*oldBufObj
;
1003 struct gl_buffer_object
*newBufObj
= NULL
;
1007 /* Get pointer to old buffer object (to be unbound) */
1008 oldBufObj
= *bindTarget
;
1009 if (oldBufObj
&& oldBufObj
->Name
== buffer
&& !oldBufObj
->DeletePending
)
1010 return; /* rebinding the same buffer object- no change */
1013 * Get pointer to new buffer object (newBufObj)
1016 /* The spec says there's not a buffer object named 0, but we use
1017 * one internally because it simplifies things.
1019 newBufObj
= ctx
->Shared
->NullBufferObj
;
1022 /* non-default buffer object */
1023 newBufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
1024 if (!_mesa_handle_bind_buffer_gen(ctx
, buffer
,
1025 &newBufObj
, "glBindBuffer"))
1029 /* record usage history */
1030 if (bindTarget
== &ctx
->Pack
.BufferObj
) {
1031 newBufObj
->UsageHistory
|= USAGE_PIXEL_PACK_BUFFER
;
1034 /* bind new buffer */
1035 _mesa_reference_buffer_object(ctx
, bindTarget
, newBufObj
);
1040 * Update the default buffer objects in the given context to reference those
1041 * specified in the shared state and release those referencing the old
1045 _mesa_update_default_objects_buffer_objects(struct gl_context
*ctx
)
1047 /* Bind the NullBufferObj to remove references to those
1048 * in the shared context hash table.
1050 bind_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
, 0);
1051 bind_buffer_object(ctx
, &ctx
->Array
.VAO
->IndexBufferObj
, 0);
1052 bind_buffer_object(ctx
, &ctx
->Pack
.BufferObj
, 0);
1053 bind_buffer_object(ctx
, &ctx
->Unpack
.BufferObj
, 0);
1059 * Return the gl_buffer_object for the given ID.
1060 * Always return NULL for ID 0.
1062 struct gl_buffer_object
*
1063 _mesa_lookup_bufferobj(struct gl_context
*ctx
, GLuint buffer
)
1068 return (struct gl_buffer_object
*)
1069 _mesa_HashLookup(ctx
->Shared
->BufferObjects
, buffer
);
1073 struct gl_buffer_object
*
1074 _mesa_lookup_bufferobj_locked(struct gl_context
*ctx
, GLuint buffer
)
1079 return (struct gl_buffer_object
*)
1080 _mesa_HashLookupLocked(ctx
->Shared
->BufferObjects
, buffer
);
1084 * A convenience function for direct state access functions that throws
1085 * GL_INVALID_OPERATION if buffer is not the name of an existing
1088 struct gl_buffer_object
*
1089 _mesa_lookup_bufferobj_err(struct gl_context
*ctx
, GLuint buffer
,
1092 struct gl_buffer_object
*bufObj
;
1094 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
1095 if (!bufObj
|| bufObj
== &DummyBufferObject
) {
1096 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1097 "%s(non-existent buffer object %u)", caller
, buffer
);
1106 * Look up a buffer object for a multi-bind function.
1108 * Unlike _mesa_lookup_bufferobj(), this function also takes care
1109 * of generating an error if the buffer ID is not zero or the name
1110 * of an existing buffer object.
1112 * If the buffer ID refers to an existing buffer object, a pointer
1113 * to the buffer object is returned. If the ID is zero, a pointer
1114 * to the shared NullBufferObj is returned. If the ID is not zero
1115 * and does not refer to a valid buffer object, this function
1118 * This function assumes that the caller has already locked the
1119 * hash table mutex by calling
1120 * _mesa_HashLockMutex(ctx->Shared->BufferObjects).
1122 struct gl_buffer_object
*
1123 _mesa_multi_bind_lookup_bufferobj(struct gl_context
*ctx
,
1124 const GLuint
*buffers
,
1125 GLuint index
, const char *caller
)
1127 struct gl_buffer_object
*bufObj
;
1129 if (buffers
[index
] != 0) {
1130 bufObj
= _mesa_lookup_bufferobj_locked(ctx
, buffers
[index
]);
1132 /* The multi-bind functions don't create the buffer objects
1133 when they don't exist. */
1134 if (bufObj
== &DummyBufferObject
)
1137 bufObj
= ctx
->Shared
->NullBufferObj
;
1140 /* The ARB_multi_bind spec says:
1142 * "An INVALID_OPERATION error is generated if any value
1143 * in <buffers> is not zero or the name of an existing
1144 * buffer object (per binding)."
1146 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1147 "%s(buffers[%u]=%u is not zero or the name "
1148 "of an existing buffer object)",
1149 caller
, index
, buffers
[index
]);
1157 * If *ptr points to obj, set ptr = the Null/default buffer object.
1158 * This is a helper for buffer object deletion.
1159 * The GL spec says that deleting a buffer object causes it to get
1160 * unbound from all arrays in the current context.
1163 unbind(struct gl_context
*ctx
,
1164 struct gl_vertex_array_object
*vao
, unsigned index
,
1165 struct gl_buffer_object
*obj
)
1167 if (vao
->BufferBinding
[index
].BufferObj
== obj
) {
1168 _mesa_bind_vertex_buffer(ctx
, vao
, index
, ctx
->Shared
->NullBufferObj
,
1169 vao
->BufferBinding
[index
].Offset
,
1170 vao
->BufferBinding
[index
].Stride
, true);
1176 * Plug default/fallback buffer object functions into the device
1180 _mesa_init_buffer_object_functions(struct dd_function_table
*driver
)
1182 /* GL_ARB_vertex/pixel_buffer_object */
1183 driver
->NewBufferObject
= _mesa_new_buffer_object
;
1184 driver
->DeleteBuffer
= _mesa_delete_buffer_object
;
1185 driver
->BufferData
= buffer_data_fallback
;
1186 driver
->BufferSubData
= buffer_sub_data_fallback
;
1187 driver
->GetBufferSubData
= buffer_get_subdata
;
1188 driver
->UnmapBuffer
= unmap_buffer_fallback
;
1190 /* GL_ARB_clear_buffer_object */
1191 driver
->ClearBufferSubData
= _mesa_ClearBufferSubData_sw
;
1193 /* GL_ARB_map_buffer_range */
1194 driver
->MapBufferRange
= map_buffer_range_fallback
;
1195 driver
->FlushMappedBufferRange
= flush_mapped_buffer_range_fallback
;
1197 /* GL_ARB_copy_buffer */
1198 driver
->CopyBufferSubData
= copy_buffer_sub_data_fallback
;
1203 _mesa_buffer_unmap_all_mappings(struct gl_context
*ctx
,
1204 struct gl_buffer_object
*bufObj
)
1206 for (int i
= 0; i
< MAP_COUNT
; i
++) {
1207 if (_mesa_bufferobj_mapped(bufObj
, i
)) {
1208 ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, i
);
1209 assert(bufObj
->Mappings
[i
].Pointer
== NULL
);
1210 bufObj
->Mappings
[i
].AccessFlags
= 0;
1216 /**********************************************************************/
1218 /**********************************************************************/
1221 _mesa_BindBuffer_no_error(GLenum target
, GLuint buffer
)
1223 GET_CURRENT_CONTEXT(ctx
);
1225 struct gl_buffer_object
**bindTarget
= get_buffer_target(ctx
, target
);
1226 bind_buffer_object(ctx
, bindTarget
, buffer
);
1231 _mesa_BindBuffer(GLenum target
, GLuint buffer
)
1233 GET_CURRENT_CONTEXT(ctx
);
1235 if (MESA_VERBOSE
& VERBOSE_API
) {
1236 _mesa_debug(ctx
, "glBindBuffer(%s, %u)\n",
1237 _mesa_enum_to_string(target
), buffer
);
1240 struct gl_buffer_object
**bindTarget
= get_buffer_target(ctx
, target
);
1242 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBufferARB(target %s)",
1243 _mesa_enum_to_string(target
));
1247 bind_buffer_object(ctx
, bindTarget
, buffer
);
1251 * Binds a buffer object to a binding point.
1253 * The caller is responsible for validating the offset,
1254 * flushing the vertices and updating NewDriverState.
1257 set_buffer_binding(struct gl_context
*ctx
,
1258 struct gl_buffer_binding
*binding
,
1259 struct gl_buffer_object
*bufObj
,
1262 bool autoSize
, gl_buffer_usage usage
)
1264 _mesa_reference_buffer_object(ctx
, &binding
->BufferObject
, bufObj
);
1266 binding
->Offset
= offset
;
1267 binding
->Size
= size
;
1268 binding
->AutomaticSize
= autoSize
;
1270 /* If this is a real buffer object, mark it has having been used
1271 * at some point as an atomic counter buffer.
1274 bufObj
->UsageHistory
|= usage
;
1278 set_buffer_multi_binding(struct gl_context
*ctx
,
1279 const GLuint
*buffers
,
1282 struct gl_buffer_binding
*binding
,
1286 gl_buffer_usage usage
)
1288 struct gl_buffer_object
*bufObj
;
1289 if (binding
->BufferObject
&& binding
->BufferObject
->Name
== buffers
[idx
])
1290 bufObj
= binding
->BufferObject
;
1292 bufObj
= _mesa_multi_bind_lookup_bufferobj(ctx
, buffers
, idx
, caller
);
1295 if (bufObj
== ctx
->Shared
->NullBufferObj
)
1296 set_buffer_binding(ctx
, binding
, bufObj
, -1, -1, !range
, usage
);
1298 set_buffer_binding(ctx
, binding
, bufObj
, offset
, size
, !range
, usage
);
1303 bind_buffer(struct gl_context
*ctx
,
1304 struct gl_buffer_binding
*binding
,
1305 struct gl_buffer_object
*bufObj
,
1309 uint64_t driver_state
,
1310 gl_buffer_usage usage
)
1312 if (binding
->BufferObject
== bufObj
&&
1313 binding
->Offset
== offset
&&
1314 binding
->Size
== size
&&
1315 binding
->AutomaticSize
== autoSize
) {
1319 FLUSH_VERTICES(ctx
, 0);
1320 ctx
->NewDriverState
|= driver_state
;
1322 set_buffer_binding(ctx
, binding
, bufObj
, offset
, size
, autoSize
, usage
);
1326 * Binds a buffer object to a uniform buffer binding point.
1328 * Unlike set_buffer_binding(), this function also flushes vertices
1329 * and updates NewDriverState. It also checks if the binding
1330 * has actually changed before updating it.
1333 bind_uniform_buffer(struct gl_context
*ctx
,
1335 struct gl_buffer_object
*bufObj
,
1340 bind_buffer(ctx
, &ctx
->UniformBufferBindings
[index
],
1341 bufObj
, offset
, size
, autoSize
,
1342 ctx
->DriverFlags
.NewUniformBuffer
,
1343 USAGE_UNIFORM_BUFFER
);
1347 * Binds a buffer object to a shader storage buffer binding point.
1349 * Unlike set_ssbo_binding(), this function also flushes vertices
1350 * and updates NewDriverState. It also checks if the binding
1351 * has actually changed before updating it.
1354 bind_shader_storage_buffer(struct gl_context
*ctx
,
1356 struct gl_buffer_object
*bufObj
,
1361 bind_buffer(ctx
, &ctx
->ShaderStorageBufferBindings
[index
],
1362 bufObj
, offset
, size
, autoSize
,
1363 ctx
->DriverFlags
.NewShaderStorageBuffer
,
1364 USAGE_SHADER_STORAGE_BUFFER
);
1368 * Binds a buffer object to an atomic buffer binding point.
1370 * Unlike set_atomic_binding(), this function also flushes vertices
1371 * and updates NewDriverState. It also checks if the binding
1372 * has actually changed before updating it.
1375 bind_atomic_buffer(struct gl_context
*ctx
, unsigned index
,
1376 struct gl_buffer_object
*bufObj
, GLintptr offset
,
1377 GLsizeiptr size
, GLboolean autoSize
)
1379 bind_buffer(ctx
, &ctx
->AtomicBufferBindings
[index
],
1380 bufObj
, offset
, size
, autoSize
,
1381 ctx
->DriverFlags
.NewAtomicBuffer
,
1382 USAGE_ATOMIC_COUNTER_BUFFER
);
1386 * Bind a buffer object to a uniform block binding point.
1387 * As above, but offset = 0.
1390 bind_buffer_base_uniform_buffer(struct gl_context
*ctx
,
1392 struct gl_buffer_object
*bufObj
)
1394 if (index
>= ctx
->Const
.MaxUniformBufferBindings
) {
1395 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferBase(index=%d)", index
);
1399 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
, bufObj
);
1401 if (bufObj
== ctx
->Shared
->NullBufferObj
)
1402 bind_uniform_buffer(ctx
, index
, bufObj
, -1, -1, GL_TRUE
);
1404 bind_uniform_buffer(ctx
, index
, bufObj
, 0, 0, GL_TRUE
);
1408 * Bind a buffer object to a shader storage block binding point.
1409 * As above, but offset = 0.
1412 bind_buffer_base_shader_storage_buffer(struct gl_context
*ctx
,
1414 struct gl_buffer_object
*bufObj
)
1416 if (index
>= ctx
->Const
.MaxShaderStorageBufferBindings
) {
1417 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferBase(index=%d)", index
);
1421 _mesa_reference_buffer_object(ctx
, &ctx
->ShaderStorageBuffer
, bufObj
);
1423 if (bufObj
== ctx
->Shared
->NullBufferObj
)
1424 bind_shader_storage_buffer(ctx
, index
, bufObj
, -1, -1, GL_TRUE
);
1426 bind_shader_storage_buffer(ctx
, index
, bufObj
, 0, 0, GL_TRUE
);
1430 * Bind a buffer object to a shader storage block binding point.
1431 * As above, but offset = 0.
1434 bind_buffer_base_atomic_buffer(struct gl_context
*ctx
,
1436 struct gl_buffer_object
*bufObj
)
1438 if (index
>= ctx
->Const
.MaxAtomicBufferBindings
) {
1439 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferBase(index=%d)", index
);
1443 _mesa_reference_buffer_object(ctx
, &ctx
->AtomicBuffer
, bufObj
);
1445 if (bufObj
== ctx
->Shared
->NullBufferObj
)
1446 bind_atomic_buffer(ctx
, index
, bufObj
, -1, -1, GL_TRUE
);
1448 bind_atomic_buffer(ctx
, index
, bufObj
, 0, 0, GL_TRUE
);
1452 * Delete a set of buffer objects.
1454 * \param n Number of buffer objects to delete.
1455 * \param ids Array of \c n buffer object IDs.
1458 delete_buffers(struct gl_context
*ctx
, GLsizei n
, const GLuint
*ids
)
1460 FLUSH_VERTICES(ctx
, 0);
1462 _mesa_HashLockMutex(ctx
->Shared
->BufferObjects
);
1464 for (GLsizei i
= 0; i
< n
; i
++) {
1465 struct gl_buffer_object
*bufObj
=
1466 _mesa_lookup_bufferobj_locked(ctx
, ids
[i
]);
1468 struct gl_vertex_array_object
*vao
= ctx
->Array
.VAO
;
1471 assert(bufObj
->Name
== ids
[i
] || bufObj
== &DummyBufferObject
);
1473 _mesa_buffer_unmap_all_mappings(ctx
, bufObj
);
1475 /* unbind any vertex pointers bound to this buffer */
1476 for (j
= 0; j
< ARRAY_SIZE(vao
->BufferBinding
); j
++) {
1477 unbind(ctx
, vao
, j
, bufObj
);
1480 if (ctx
->Array
.ArrayBufferObj
== bufObj
) {
1481 bind_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
, 0);
1483 if (vao
->IndexBufferObj
== bufObj
) {
1484 bind_buffer_object(ctx
, &vao
->IndexBufferObj
, 0);
1487 /* unbind ARB_draw_indirect binding point */
1488 if (ctx
->DrawIndirectBuffer
== bufObj
) {
1489 bind_buffer_object(ctx
, &ctx
->DrawIndirectBuffer
, 0);
1492 /* unbind ARB_indirect_parameters binding point */
1493 if (ctx
->ParameterBuffer
== bufObj
) {
1494 bind_buffer_object(ctx
, &ctx
->ParameterBuffer
, 0);
1497 /* unbind ARB_compute_shader binding point */
1498 if (ctx
->DispatchIndirectBuffer
== bufObj
) {
1499 bind_buffer_object(ctx
, &ctx
->DispatchIndirectBuffer
, 0);
1502 /* unbind ARB_copy_buffer binding points */
1503 if (ctx
->CopyReadBuffer
== bufObj
) {
1504 bind_buffer_object(ctx
, &ctx
->CopyReadBuffer
, 0);
1506 if (ctx
->CopyWriteBuffer
== bufObj
) {
1507 bind_buffer_object(ctx
, &ctx
->CopyWriteBuffer
, 0);
1510 /* unbind transform feedback binding points */
1511 if (ctx
->TransformFeedback
.CurrentBuffer
== bufObj
) {
1512 bind_buffer_object(ctx
, &ctx
->TransformFeedback
.CurrentBuffer
, 0);
1514 for (j
= 0; j
< MAX_FEEDBACK_BUFFERS
; j
++) {
1515 if (ctx
->TransformFeedback
.CurrentObject
->Buffers
[j
] == bufObj
) {
1516 _mesa_bind_buffer_base_transform_feedback(ctx
,
1517 ctx
->TransformFeedback
.CurrentObject
,
1518 j
, ctx
->Shared
->NullBufferObj
,
1523 /* unbind UBO binding points */
1524 for (j
= 0; j
< ctx
->Const
.MaxUniformBufferBindings
; j
++) {
1525 if (ctx
->UniformBufferBindings
[j
].BufferObject
== bufObj
) {
1526 bind_buffer_base_uniform_buffer(ctx
, j
,
1527 ctx
->Shared
->NullBufferObj
);
1531 if (ctx
->UniformBuffer
== bufObj
) {
1532 bind_buffer_object(ctx
, &ctx
->UniformBuffer
, 0);
1535 /* unbind SSBO binding points */
1536 for (j
= 0; j
< ctx
->Const
.MaxShaderStorageBufferBindings
; j
++) {
1537 if (ctx
->ShaderStorageBufferBindings
[j
].BufferObject
== bufObj
) {
1538 bind_buffer_base_shader_storage_buffer(ctx
, j
,
1539 ctx
->Shared
->NullBufferObj
);
1543 if (ctx
->ShaderStorageBuffer
== bufObj
) {
1544 bind_buffer_object(ctx
, &ctx
->ShaderStorageBuffer
, 0);
1547 /* unbind Atomci Buffer binding points */
1548 for (j
= 0; j
< ctx
->Const
.MaxAtomicBufferBindings
; j
++) {
1549 if (ctx
->AtomicBufferBindings
[j
].BufferObject
== bufObj
) {
1550 bind_buffer_base_atomic_buffer(ctx
, j
,
1551 ctx
->Shared
->NullBufferObj
);
1555 if (ctx
->AtomicBuffer
== bufObj
) {
1556 bind_buffer_object(ctx
, &ctx
->AtomicBuffer
, 0);
1559 /* unbind any pixel pack/unpack pointers bound to this buffer */
1560 if (ctx
->Pack
.BufferObj
== bufObj
) {
1561 bind_buffer_object(ctx
, &ctx
->Pack
.BufferObj
, 0);
1563 if (ctx
->Unpack
.BufferObj
== bufObj
) {
1564 bind_buffer_object(ctx
, &ctx
->Unpack
.BufferObj
, 0);
1567 if (ctx
->Texture
.BufferObject
== bufObj
) {
1568 bind_buffer_object(ctx
, &ctx
->Texture
.BufferObject
, 0);
1571 if (ctx
->ExternalVirtualMemoryBuffer
== bufObj
) {
1572 bind_buffer_object(ctx
, &ctx
->ExternalVirtualMemoryBuffer
, 0);
1575 /* unbind query buffer binding point */
1576 if (ctx
->QueryBuffer
== bufObj
) {
1577 bind_buffer_object(ctx
, &ctx
->QueryBuffer
, 0);
1580 /* The ID is immediately freed for re-use */
1581 _mesa_HashRemoveLocked(ctx
->Shared
->BufferObjects
, ids
[i
]);
1582 /* Make sure we do not run into the classic ABA problem on bind.
1583 * We don't want to allow re-binding a buffer object that's been
1584 * "deleted" by glDeleteBuffers().
1586 * The explicit rebinding to the default object in the current context
1587 * prevents the above in the current context, but another context
1588 * sharing the same objects might suffer from this problem.
1589 * The alternative would be to do the hash lookup in any case on bind
1590 * which would introduce more runtime overhead than this.
1592 bufObj
->DeletePending
= GL_TRUE
;
1593 _mesa_reference_buffer_object(ctx
, &bufObj
, NULL
);
1597 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
1602 _mesa_DeleteBuffers_no_error(GLsizei n
, const GLuint
*ids
)
1604 GET_CURRENT_CONTEXT(ctx
);
1605 delete_buffers(ctx
, n
, ids
);
1610 _mesa_DeleteBuffers(GLsizei n
, const GLuint
*ids
)
1612 GET_CURRENT_CONTEXT(ctx
);
1615 _mesa_error(ctx
, GL_INVALID_VALUE
, "glDeleteBuffersARB(n)");
1619 delete_buffers(ctx
, n
, ids
);
1624 * This is the implementation for glGenBuffers and glCreateBuffers. It is not
1625 * exposed to the rest of Mesa to encourage the use of nameless buffers in
1629 create_buffers(struct gl_context
*ctx
, GLsizei n
, GLuint
*buffers
, bool dsa
)
1632 struct gl_buffer_object
*buf
;
1638 * This must be atomic (generation and allocation of buffer object IDs)
1640 _mesa_HashLockMutex(ctx
->Shared
->BufferObjects
);
1642 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->BufferObjects
, n
);
1644 /* Insert the ID and pointer into the hash table. If non-DSA, insert a
1645 * DummyBufferObject. Otherwise, create a new buffer object and insert
1648 for (int i
= 0; i
< n
; i
++) {
1649 buffers
[i
] = first
+ i
;
1651 assert(ctx
->Driver
.NewBufferObject
);
1652 buf
= ctx
->Driver
.NewBufferObject(ctx
, buffers
[i
]);
1654 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCreateBuffers");
1655 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
1660 buf
= &DummyBufferObject
;
1662 _mesa_HashInsertLocked(ctx
->Shared
->BufferObjects
, buffers
[i
], buf
);
1665 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
1670 create_buffers_err(struct gl_context
*ctx
, GLsizei n
, GLuint
*buffers
, bool dsa
)
1672 const char *func
= dsa
? "glCreateBuffers" : "glGenBuffers";
1674 if (MESA_VERBOSE
& VERBOSE_API
)
1675 _mesa_debug(ctx
, "%s(%d)\n", func
, n
);
1678 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(n %d < 0)", func
, n
);
1682 create_buffers(ctx
, n
, buffers
, dsa
);
1686 * Generate a set of unique buffer object IDs and store them in \c buffers.
1688 * \param n Number of IDs to generate.
1689 * \param buffers Array of \c n locations to store the IDs.
1692 _mesa_GenBuffers_no_error(GLsizei n
, GLuint
*buffers
)
1694 GET_CURRENT_CONTEXT(ctx
);
1695 create_buffers(ctx
, n
, buffers
, false);
1700 _mesa_GenBuffers(GLsizei n
, GLuint
*buffers
)
1702 GET_CURRENT_CONTEXT(ctx
);
1703 create_buffers_err(ctx
, n
, buffers
, false);
1707 * Create a set of buffer objects and store their unique IDs in \c buffers.
1709 * \param n Number of IDs to generate.
1710 * \param buffers Array of \c n locations to store the IDs.
1713 _mesa_CreateBuffers_no_error(GLsizei n
, GLuint
*buffers
)
1715 GET_CURRENT_CONTEXT(ctx
);
1716 create_buffers(ctx
, n
, buffers
, true);
1721 _mesa_CreateBuffers(GLsizei n
, GLuint
*buffers
)
1723 GET_CURRENT_CONTEXT(ctx
);
1724 create_buffers_err(ctx
, n
, buffers
, true);
1729 * Determine if ID is the name of a buffer object.
1731 * \param id ID of the potential buffer object.
1732 * \return \c GL_TRUE if \c id is the name of a buffer object,
1733 * \c GL_FALSE otherwise.
1735 GLboolean GLAPIENTRY
1736 _mesa_IsBuffer(GLuint id
)
1738 struct gl_buffer_object
*bufObj
;
1739 GET_CURRENT_CONTEXT(ctx
);
1740 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
1742 bufObj
= _mesa_lookup_bufferobj(ctx
, id
);
1744 return bufObj
&& bufObj
!= &DummyBufferObject
;
1749 validate_buffer_storage(struct gl_context
*ctx
,
1750 struct gl_buffer_object
*bufObj
, GLsizeiptr size
,
1751 GLbitfield flags
, const char *func
)
1754 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(size <= 0)", func
);
1758 GLbitfield valid_flags
= GL_MAP_READ_BIT
|
1760 GL_MAP_PERSISTENT_BIT
|
1761 GL_MAP_COHERENT_BIT
|
1762 GL_DYNAMIC_STORAGE_BIT
|
1763 GL_CLIENT_STORAGE_BIT
;
1765 if (ctx
->Extensions
.ARB_sparse_buffer
)
1766 valid_flags
|= GL_SPARSE_STORAGE_BIT_ARB
;
1768 if (flags
& ~valid_flags
) {
1769 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(invalid flag bits set)", func
);
1773 /* The Errors section of the GL_ARB_sparse_buffer spec says:
1775 * "INVALID_VALUE is generated by BufferStorage if <flags> contains
1776 * SPARSE_STORAGE_BIT_ARB and <flags> also contains any combination of
1777 * MAP_READ_BIT or MAP_WRITE_BIT."
1779 if (flags
& GL_SPARSE_STORAGE_BIT_ARB
&&
1780 flags
& (GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
)) {
1781 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(SPARSE_STORAGE and READ/WRITE)", func
);
1785 if (flags
& GL_MAP_PERSISTENT_BIT
&&
1786 !(flags
& (GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
))) {
1787 _mesa_error(ctx
, GL_INVALID_VALUE
,
1788 "%s(PERSISTENT and flags!=READ/WRITE)", func
);
1792 if (flags
& GL_MAP_COHERENT_BIT
&& !(flags
& GL_MAP_PERSISTENT_BIT
)) {
1793 _mesa_error(ctx
, GL_INVALID_VALUE
,
1794 "%s(COHERENT and flags!=PERSISTENT)", func
);
1798 if (bufObj
->Immutable
|| bufObj
->HandleAllocated
) {
1799 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(immutable)", func
);
1808 buffer_storage(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
1809 struct gl_memory_object
*memObj
, GLenum target
,
1810 GLsizeiptr size
, const GLvoid
*data
, GLbitfield flags
,
1811 GLuint64 offset
, const char *func
)
1815 /* Unmap the existing buffer. We'll replace it now. Not an error. */
1816 _mesa_buffer_unmap_all_mappings(ctx
, bufObj
);
1818 FLUSH_VERTICES(ctx
, 0);
1820 bufObj
->Written
= GL_TRUE
;
1821 bufObj
->Immutable
= GL_TRUE
;
1822 bufObj
->MinMaxCacheDirty
= true;
1825 assert(ctx
->Driver
.BufferDataMem
);
1826 res
= ctx
->Driver
.BufferDataMem(ctx
, target
, size
, memObj
, offset
,
1827 GL_DYNAMIC_DRAW
, bufObj
);
1830 assert(ctx
->Driver
.BufferData
);
1831 res
= ctx
->Driver
.BufferData(ctx
, target
, size
, data
, GL_DYNAMIC_DRAW
,
1836 if (target
== GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
) {
1837 /* Even though the interaction between AMD_pinned_memory and
1838 * glBufferStorage is not described in the spec, Graham Sellers
1839 * said that it should behave the same as glBufferData.
1841 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s", func
);
1844 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s", func
);
1850 static ALWAYS_INLINE
void
1851 inlined_buffer_storage(GLenum target
, GLuint buffer
, GLsizeiptr size
,
1852 const GLvoid
*data
, GLbitfield flags
,
1853 GLuint memory
, GLuint64 offset
,
1854 bool dsa
, bool mem
, bool no_error
, const char *func
)
1856 GET_CURRENT_CONTEXT(ctx
);
1857 struct gl_buffer_object
*bufObj
;
1858 struct gl_memory_object
*memObj
= NULL
;
1862 if (!ctx
->Extensions
.EXT_memory_object
) {
1863 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(unsupported)", func
);
1867 /* From the EXT_external_objects spec:
1869 * "An INVALID_VALUE error is generated by BufferStorageMemEXT and
1870 * NamedBufferStorageMemEXT if <memory> is 0, or ..."
1873 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(memory == 0)", func
);
1877 memObj
= _mesa_lookup_memory_object(ctx
, memory
);
1881 /* From the EXT_external_objects spec:
1883 * "An INVALID_OPERATION error is generated if <memory> names a
1884 * valid memory object which has no associated memory."
1886 if (!no_error
&& !memObj
->Immutable
) {
1887 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(no associated memory)",
1895 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
1897 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
, func
);
1903 struct gl_buffer_object
**bufObjPtr
= get_buffer_target(ctx
, target
);
1904 bufObj
= *bufObjPtr
;
1906 bufObj
= get_buffer(ctx
, func
, target
, GL_INVALID_OPERATION
);
1912 if (no_error
|| validate_buffer_storage(ctx
, bufObj
, size
, flags
, func
))
1913 buffer_storage(ctx
, bufObj
, memObj
, target
, size
, data
, flags
, offset
, func
);
1918 _mesa_BufferStorage_no_error(GLenum target
, GLsizeiptr size
,
1919 const GLvoid
*data
, GLbitfield flags
)
1921 inlined_buffer_storage(target
, 0, size
, data
, flags
, GL_NONE
, 0,
1922 false, false, true, "glBufferStorage");
1927 _mesa_BufferStorage(GLenum target
, GLsizeiptr size
, const GLvoid
*data
,
1930 inlined_buffer_storage(target
, 0, size
, data
, flags
, GL_NONE
, 0,
1931 false, false, false, "glBufferStorage");
1936 _mesa_BufferStorageMemEXT(GLenum target
, GLsizeiptr size
,
1937 GLuint memory
, GLuint64 offset
)
1939 inlined_buffer_storage(target
, 0, size
, NULL
, 0, memory
, offset
,
1940 false, true, false, "glBufferStorageMemEXT");
1945 _mesa_BufferStorageMemEXT_no_error(GLenum target
, GLsizeiptr size
,
1946 GLuint memory
, GLuint64 offset
)
1948 inlined_buffer_storage(target
, 0, size
, NULL
, 0, memory
, offset
,
1949 false, true, true, "glBufferStorageMemEXT");
1954 _mesa_NamedBufferStorage_no_error(GLuint buffer
, GLsizeiptr size
,
1955 const GLvoid
*data
, GLbitfield flags
)
1957 /* In direct state access, buffer objects have an unspecified target
1958 * since they are not required to be bound.
1960 inlined_buffer_storage(GL_NONE
, buffer
, size
, data
, flags
, GL_NONE
, 0,
1961 true, false, true, "glNamedBufferStorage");
1966 _mesa_NamedBufferStorage(GLuint buffer
, GLsizeiptr size
, const GLvoid
*data
,
1969 /* In direct state access, buffer objects have an unspecified target
1970 * since they are not required to be bound.
1972 inlined_buffer_storage(GL_NONE
, buffer
, size
, data
, flags
, GL_NONE
, 0,
1973 true, false, false, "glNamedBufferStorage");
1977 _mesa_NamedBufferStorageMemEXT(GLuint buffer
, GLsizeiptr size
,
1978 GLuint memory
, GLuint64 offset
)
1980 inlined_buffer_storage(GL_NONE
, buffer
, size
, GL_NONE
, 0, memory
, offset
,
1981 true, true, false, "glNamedBufferStorageMemEXT");
1986 _mesa_NamedBufferStorageMemEXT_no_error(GLuint buffer
, GLsizeiptr size
,
1987 GLuint memory
, GLuint64 offset
)
1989 inlined_buffer_storage(GL_NONE
, buffer
, size
, GL_NONE
, 0, memory
, offset
,
1990 true, true, true, "glNamedBufferStorageMemEXT");
1994 static ALWAYS_INLINE
void
1995 buffer_data(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
1996 GLenum target
, GLsizeiptr size
, const GLvoid
*data
, GLenum usage
,
1997 const char *func
, bool no_error
)
2001 if (MESA_VERBOSE
& VERBOSE_API
) {
2002 _mesa_debug(ctx
, "%s(%s, %ld, %p, %s)\n",
2004 _mesa_enum_to_string(target
),
2005 (long int) size
, data
,
2006 _mesa_enum_to_string(usage
));
2011 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(size < 0)", func
);
2016 case GL_STREAM_DRAW_ARB
:
2017 valid_usage
= (ctx
->API
!= API_OPENGLES
);
2019 case GL_STATIC_DRAW_ARB
:
2020 case GL_DYNAMIC_DRAW_ARB
:
2023 case GL_STREAM_READ_ARB
:
2024 case GL_STREAM_COPY_ARB
:
2025 case GL_STATIC_READ_ARB
:
2026 case GL_STATIC_COPY_ARB
:
2027 case GL_DYNAMIC_READ_ARB
:
2028 case GL_DYNAMIC_COPY_ARB
:
2029 valid_usage
= _mesa_is_desktop_gl(ctx
) || _mesa_is_gles3(ctx
);
2032 valid_usage
= false;
2037 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(invalid usage: %s)", func
,
2038 _mesa_enum_to_string(usage
));
2042 if (bufObj
->Immutable
|| bufObj
->HandleAllocated
) {
2043 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(immutable)", func
);
2048 /* Unmap the existing buffer. We'll replace it now. Not an error. */
2049 _mesa_buffer_unmap_all_mappings(ctx
, bufObj
);
2051 FLUSH_VERTICES(ctx
, 0);
2053 bufObj
->Written
= GL_TRUE
;
2054 bufObj
->MinMaxCacheDirty
= true;
2057 printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
2058 bufObj
->Name
, size
, data
, usage
);
2065 assert(ctx
->Driver
.BufferData
);
2066 if (!ctx
->Driver
.BufferData(ctx
, target
, size
, data
, usage
,
2069 GL_DYNAMIC_STORAGE_BIT
,
2071 if (target
== GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
) {
2073 /* From GL_AMD_pinned_memory:
2075 * INVALID_OPERATION is generated by BufferData if <target> is
2076 * EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be
2077 * mapped to the GPU address space.
2079 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s", func
);
2082 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s", func
);
2088 buffer_data_error(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
2089 GLenum target
, GLsizeiptr size
, const GLvoid
*data
,
2090 GLenum usage
, const char *func
)
2092 buffer_data(ctx
, bufObj
, target
, size
, data
, usage
, func
, false);
2096 buffer_data_no_error(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
2097 GLenum target
, GLsizeiptr size
, const GLvoid
*data
,
2098 GLenum usage
, const char *func
)
2100 buffer_data(ctx
, bufObj
, target
, size
, data
, usage
, func
, true);
2104 _mesa_buffer_data(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
2105 GLenum target
, GLsizeiptr size
, const GLvoid
*data
,
2106 GLenum usage
, const char *func
)
2108 buffer_data_error(ctx
, bufObj
, target
, size
, data
, usage
, func
);
2112 _mesa_BufferData_no_error(GLenum target
, GLsizeiptr size
, const GLvoid
*data
,
2115 GET_CURRENT_CONTEXT(ctx
);
2117 struct gl_buffer_object
**bufObj
= get_buffer_target(ctx
, target
);
2118 buffer_data_no_error(ctx
, *bufObj
, target
, size
, data
, usage
,
2123 _mesa_BufferData(GLenum target
, GLsizeiptr size
,
2124 const GLvoid
*data
, GLenum usage
)
2126 GET_CURRENT_CONTEXT(ctx
);
2127 struct gl_buffer_object
*bufObj
;
2129 bufObj
= get_buffer(ctx
, "glBufferData", target
, GL_INVALID_OPERATION
);
2133 _mesa_buffer_data(ctx
, bufObj
, target
, size
, data
, usage
,
2138 _mesa_NamedBufferData_no_error(GLuint buffer
, GLsizeiptr size
,
2139 const GLvoid
*data
, GLenum usage
)
2141 GET_CURRENT_CONTEXT(ctx
);
2143 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2144 buffer_data_no_error(ctx
, bufObj
, GL_NONE
, size
, data
, usage
,
2145 "glNamedBufferData");
2149 _mesa_NamedBufferData(GLuint buffer
, GLsizeiptr size
, const GLvoid
*data
,
2152 GET_CURRENT_CONTEXT(ctx
);
2153 struct gl_buffer_object
*bufObj
;
2155 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
, "glNamedBufferData");
2159 /* In direct state access, buffer objects have an unspecified target since
2160 * they are not required to be bound.
2162 _mesa_buffer_data(ctx
, bufObj
, GL_NONE
, size
, data
, usage
,
2163 "glNamedBufferData");
2168 validate_buffer_sub_data(struct gl_context
*ctx
,
2169 struct gl_buffer_object
*bufObj
,
2170 GLintptr offset
, GLsizeiptr size
,
2173 if (!buffer_object_subdata_range_good(ctx
, bufObj
, offset
, size
,
2175 /* error already recorded */
2179 if (bufObj
->Immutable
&&
2180 !(bufObj
->StorageFlags
& GL_DYNAMIC_STORAGE_BIT
)) {
2181 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s", func
);
2185 if ((bufObj
->Usage
== GL_STATIC_DRAW
||
2186 bufObj
->Usage
== GL_STATIC_COPY
) &&
2187 bufObj
->NumSubDataCalls
>= BUFFER_WARNING_CALL_COUNT
- 1) {
2188 /* If the application declared the buffer as static draw/copy or stream
2189 * draw, it should not be frequently modified with glBufferSubData.
2191 BUFFER_USAGE_WARNING(ctx
,
2192 "using %s(buffer %u, offset %u, size %u) to "
2193 "update a %s buffer",
2194 func
, bufObj
->Name
, offset
, size
,
2195 _mesa_enum_to_string(bufObj
->Usage
));
2203 * Implementation for glBufferSubData and glNamedBufferSubData.
2205 * \param ctx GL context.
2206 * \param bufObj The buffer object.
2207 * \param offset Offset of the first byte of the subdata range.
2208 * \param size Size, in bytes, of the subdata range.
2209 * \param data The data store.
2210 * \param func Name of calling function for recording errors.
2214 _mesa_buffer_sub_data(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
2215 GLintptr offset
, GLsizeiptr size
, const GLvoid
*data
)
2220 bufObj
->NumSubDataCalls
++;
2221 bufObj
->Written
= GL_TRUE
;
2222 bufObj
->MinMaxCacheDirty
= true;
2224 assert(ctx
->Driver
.BufferSubData
);
2225 ctx
->Driver
.BufferSubData(ctx
, offset
, size
, data
, bufObj
);
2229 static ALWAYS_INLINE
void
2230 buffer_sub_data(GLenum target
, GLuint buffer
, GLintptr offset
,
2231 GLsizeiptr size
, const GLvoid
*data
,
2232 bool dsa
, bool no_error
, const char *func
)
2234 GET_CURRENT_CONTEXT(ctx
);
2235 struct gl_buffer_object
*bufObj
;
2239 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2241 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
, func
);
2247 struct gl_buffer_object
**bufObjPtr
= get_buffer_target(ctx
, target
);
2248 bufObj
= *bufObjPtr
;
2250 bufObj
= get_buffer(ctx
, func
, target
, GL_INVALID_OPERATION
);
2256 if (no_error
|| validate_buffer_sub_data(ctx
, bufObj
, offset
, size
, func
))
2257 _mesa_buffer_sub_data(ctx
, bufObj
, offset
, size
, data
);
2262 _mesa_BufferSubData_no_error(GLenum target
, GLintptr offset
,
2263 GLsizeiptr size
, const GLvoid
*data
)
2265 buffer_sub_data(target
, 0, offset
, size
, data
, false, true,
2271 _mesa_BufferSubData(GLenum target
, GLintptr offset
,
2272 GLsizeiptr size
, const GLvoid
*data
)
2274 buffer_sub_data(target
, 0, offset
, size
, data
, false, false,
2279 _mesa_NamedBufferSubData_no_error(GLuint buffer
, GLintptr offset
,
2280 GLsizeiptr size
, const GLvoid
*data
)
2282 buffer_sub_data(0, buffer
, offset
, size
, data
, true, true,
2283 "glNamedBufferSubData");
2287 _mesa_NamedBufferSubData(GLuint buffer
, GLintptr offset
,
2288 GLsizeiptr size
, const GLvoid
*data
)
2290 buffer_sub_data(0, buffer
, offset
, size
, data
, true, false,
2291 "glNamedBufferSubData");
2296 _mesa_GetBufferSubData(GLenum target
, GLintptr offset
,
2297 GLsizeiptr size
, GLvoid
*data
)
2299 GET_CURRENT_CONTEXT(ctx
);
2300 struct gl_buffer_object
*bufObj
;
2302 bufObj
= get_buffer(ctx
, "glGetBufferSubData", target
,
2303 GL_INVALID_OPERATION
);
2307 if (!buffer_object_subdata_range_good(ctx
, bufObj
, offset
, size
, false,
2308 "glGetBufferSubData")) {
2312 assert(ctx
->Driver
.GetBufferSubData
);
2313 ctx
->Driver
.GetBufferSubData(ctx
, offset
, size
, data
, bufObj
);
2317 _mesa_GetNamedBufferSubData(GLuint buffer
, GLintptr offset
,
2318 GLsizeiptr size
, GLvoid
*data
)
2320 GET_CURRENT_CONTEXT(ctx
);
2321 struct gl_buffer_object
*bufObj
;
2323 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
,
2324 "glGetNamedBufferSubData");
2328 if (!buffer_object_subdata_range_good(ctx
, bufObj
, offset
, size
, false,
2329 "glGetNamedBufferSubData")) {
2333 assert(ctx
->Driver
.GetBufferSubData
);
2334 ctx
->Driver
.GetBufferSubData(ctx
, offset
, size
, data
, bufObj
);
2339 * \param subdata true if caller is *SubData, false if *Data
2341 static ALWAYS_INLINE
void
2342 clear_buffer_sub_data(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
2343 GLenum internalformat
, GLintptr offset
, GLsizeiptr size
,
2344 GLenum format
, GLenum type
, const GLvoid
*data
,
2345 const char *func
, bool subdata
, bool no_error
)
2347 mesa_format mesaFormat
;
2348 GLubyte clearValue
[MAX_PIXEL_BYTES
];
2349 GLsizeiptr clearValueSize
;
2351 /* This checks for disallowed mappings. */
2352 if (!no_error
&& !buffer_object_subdata_range_good(ctx
, bufObj
, offset
, size
,
2358 mesaFormat
= _mesa_get_texbuffer_format(ctx
, internalformat
);
2360 mesaFormat
= validate_clear_buffer_format(ctx
, internalformat
,
2361 format
, type
, func
);
2364 if (mesaFormat
== MESA_FORMAT_NONE
)
2367 clearValueSize
= _mesa_get_format_bytes(mesaFormat
);
2369 (offset
% clearValueSize
!= 0 || size
% clearValueSize
!= 0)) {
2370 _mesa_error(ctx
, GL_INVALID_VALUE
,
2371 "%s(offset or size is not a multiple of "
2372 "internalformat size)", func
);
2376 /* Bail early. Negative size has already been checked. */
2380 bufObj
->MinMaxCacheDirty
= true;
2383 /* clear to zeros, per the spec */
2384 ctx
->Driver
.ClearBufferSubData(ctx
, offset
, size
,
2385 NULL
, clearValueSize
, bufObj
);
2389 if (!convert_clear_buffer_data(ctx
, mesaFormat
, clearValue
,
2390 format
, type
, data
, func
)) {
2394 ctx
->Driver
.ClearBufferSubData(ctx
, offset
, size
,
2395 clearValue
, clearValueSize
, bufObj
);
2399 clear_buffer_sub_data_error(struct gl_context
*ctx
,
2400 struct gl_buffer_object
*bufObj
,
2401 GLenum internalformat
, GLintptr offset
,
2402 GLsizeiptr size
, GLenum format
, GLenum type
,
2403 const GLvoid
*data
, const char *func
, bool subdata
)
2405 clear_buffer_sub_data(ctx
, bufObj
, internalformat
, offset
, size
, format
,
2406 type
, data
, func
, subdata
, false);
2411 clear_buffer_sub_data_no_error(struct gl_context
*ctx
,
2412 struct gl_buffer_object
*bufObj
,
2413 GLenum internalformat
, GLintptr offset
,
2414 GLsizeiptr size
, GLenum format
, GLenum type
,
2415 const GLvoid
*data
, const char *func
,
2418 clear_buffer_sub_data(ctx
, bufObj
, internalformat
, offset
, size
, format
,
2419 type
, data
, func
, subdata
, true);
2424 _mesa_ClearBufferData_no_error(GLenum target
, GLenum internalformat
,
2425 GLenum format
, GLenum type
, const GLvoid
*data
)
2427 GET_CURRENT_CONTEXT(ctx
);
2429 struct gl_buffer_object
**bufObj
= get_buffer_target(ctx
, target
);
2430 clear_buffer_sub_data_no_error(ctx
, *bufObj
, internalformat
, 0,
2431 (*bufObj
)->Size
, format
, type
, data
,
2432 "glClearBufferData", false);
2437 _mesa_ClearBufferData(GLenum target
, GLenum internalformat
, GLenum format
,
2438 GLenum type
, const GLvoid
*data
)
2440 GET_CURRENT_CONTEXT(ctx
);
2441 struct gl_buffer_object
*bufObj
;
2443 bufObj
= get_buffer(ctx
, "glClearBufferData", target
, GL_INVALID_VALUE
);
2447 clear_buffer_sub_data_error(ctx
, bufObj
, internalformat
, 0, bufObj
->Size
,
2448 format
, type
, data
, "glClearBufferData", false);
2453 _mesa_ClearNamedBufferData_no_error(GLuint buffer
, GLenum internalformat
,
2454 GLenum format
, GLenum type
,
2457 GET_CURRENT_CONTEXT(ctx
);
2459 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2460 clear_buffer_sub_data_no_error(ctx
, bufObj
, internalformat
, 0, bufObj
->Size
,
2461 format
, type
, data
, "glClearNamedBufferData",
2467 _mesa_ClearNamedBufferData(GLuint buffer
, GLenum internalformat
,
2468 GLenum format
, GLenum type
, const GLvoid
*data
)
2470 GET_CURRENT_CONTEXT(ctx
);
2471 struct gl_buffer_object
*bufObj
;
2473 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
, "glClearNamedBufferData");
2477 clear_buffer_sub_data_error(ctx
, bufObj
, internalformat
, 0, bufObj
->Size
,
2478 format
, type
, data
, "glClearNamedBufferData",
2484 _mesa_ClearBufferSubData_no_error(GLenum target
, GLenum internalformat
,
2485 GLintptr offset
, GLsizeiptr size
,
2486 GLenum format
, GLenum type
,
2489 GET_CURRENT_CONTEXT(ctx
);
2491 struct gl_buffer_object
**bufObj
= get_buffer_target(ctx
, target
);
2492 clear_buffer_sub_data_no_error(ctx
, *bufObj
, internalformat
, offset
, size
,
2493 format
, type
, data
, "glClearBufferSubData",
2499 _mesa_ClearBufferSubData(GLenum target
, GLenum internalformat
,
2500 GLintptr offset
, GLsizeiptr size
,
2501 GLenum format
, GLenum type
,
2504 GET_CURRENT_CONTEXT(ctx
);
2505 struct gl_buffer_object
*bufObj
;
2507 bufObj
= get_buffer(ctx
, "glClearBufferSubData", target
, GL_INVALID_VALUE
);
2511 clear_buffer_sub_data_error(ctx
, bufObj
, internalformat
, offset
, size
,
2512 format
, type
, data
, "glClearBufferSubData",
2518 _mesa_ClearNamedBufferSubData_no_error(GLuint buffer
, GLenum internalformat
,
2519 GLintptr offset
, GLsizeiptr size
,
2520 GLenum format
, GLenum type
,
2523 GET_CURRENT_CONTEXT(ctx
);
2525 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2526 clear_buffer_sub_data_no_error(ctx
, bufObj
, internalformat
, offset
, size
,
2528 "glClearNamedBufferSubData", true);
2533 _mesa_ClearNamedBufferSubData(GLuint buffer
, GLenum internalformat
,
2534 GLintptr offset
, GLsizeiptr size
,
2535 GLenum format
, GLenum type
,
2538 GET_CURRENT_CONTEXT(ctx
);
2539 struct gl_buffer_object
*bufObj
;
2541 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
,
2542 "glClearNamedBufferSubData");
2546 clear_buffer_sub_data_error(ctx
, bufObj
, internalformat
, offset
, size
,
2547 format
, type
, data
, "glClearNamedBufferSubData",
2552 unmap_buffer(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
)
2554 GLboolean status
= ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, MAP_USER
);
2555 bufObj
->Mappings
[MAP_USER
].AccessFlags
= 0;
2556 assert(bufObj
->Mappings
[MAP_USER
].Pointer
== NULL
);
2557 assert(bufObj
->Mappings
[MAP_USER
].Offset
== 0);
2558 assert(bufObj
->Mappings
[MAP_USER
].Length
== 0);
2564 validate_and_unmap_buffer(struct gl_context
*ctx
,
2565 struct gl_buffer_object
*bufObj
,
2568 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
2570 if (!_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
2571 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2572 "%s(buffer is not mapped)", func
);
2577 if (bufObj
->Access
!= GL_READ_ONLY_ARB
) {
2578 GLubyte
*buf
= (GLubyte
*) bufObj
->Pointer
;
2580 /* check that last 100 bytes are still = magic value */
2581 for (i
= 0; i
< 100; i
++) {
2582 GLuint pos
= bufObj
->Size
- i
- 1;
2583 if (buf
[pos
] != 123) {
2584 _mesa_warning(ctx
, "Out of bounds buffer object write detected"
2585 " at position %d (value = %u)\n",
2593 if (bufObj
->AccessFlags
& GL_MAP_WRITE_BIT
) {
2594 GLuint i
, unchanged
= 0;
2595 GLubyte
*b
= (GLubyte
*) bufObj
->Pointer
;
2597 /* check which bytes changed */
2598 for (i
= 0; i
< bufObj
->Size
- 1; i
++) {
2599 if (b
[i
] == (i
& 0xff) && b
[i
+1] == ((i
+1) & 0xff)) {
2606 printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
2607 bufObj
->Name
, unchanged
, bufObj
->Size
, pos
);
2612 return unmap_buffer(ctx
, bufObj
);
2615 GLboolean GLAPIENTRY
2616 _mesa_UnmapBuffer_no_error(GLenum target
)
2618 GET_CURRENT_CONTEXT(ctx
);
2619 struct gl_buffer_object
**bufObjPtr
= get_buffer_target(ctx
, target
);
2620 struct gl_buffer_object
*bufObj
= *bufObjPtr
;
2622 return unmap_buffer(ctx
, bufObj
);
2625 GLboolean GLAPIENTRY
2626 _mesa_UnmapBuffer(GLenum target
)
2628 GET_CURRENT_CONTEXT(ctx
);
2629 struct gl_buffer_object
*bufObj
;
2631 bufObj
= get_buffer(ctx
, "glUnmapBuffer", target
, GL_INVALID_OPERATION
);
2635 return validate_and_unmap_buffer(ctx
, bufObj
, "glUnmapBuffer");
2638 GLboolean GLAPIENTRY
2639 _mesa_UnmapNamedBuffer_no_error(GLuint buffer
)
2641 GET_CURRENT_CONTEXT(ctx
);
2642 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2644 return unmap_buffer(ctx
, bufObj
);
2647 GLboolean GLAPIENTRY
2648 _mesa_UnmapNamedBuffer(GLuint buffer
)
2650 GET_CURRENT_CONTEXT(ctx
);
2651 struct gl_buffer_object
*bufObj
;
2653 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
, "glUnmapNamedBuffer");
2657 return validate_and_unmap_buffer(ctx
, bufObj
, "glUnmapNamedBuffer");
2662 get_buffer_parameter(struct gl_context
*ctx
,
2663 struct gl_buffer_object
*bufObj
, GLenum pname
,
2664 GLint64
*params
, const char *func
)
2667 case GL_BUFFER_SIZE_ARB
:
2668 *params
= bufObj
->Size
;
2670 case GL_BUFFER_USAGE_ARB
:
2671 *params
= bufObj
->Usage
;
2673 case GL_BUFFER_ACCESS_ARB
:
2674 *params
= simplified_access_mode(ctx
,
2675 bufObj
->Mappings
[MAP_USER
].AccessFlags
);
2677 case GL_BUFFER_MAPPED_ARB
:
2678 *params
= _mesa_bufferobj_mapped(bufObj
, MAP_USER
);
2680 case GL_BUFFER_ACCESS_FLAGS
:
2681 if (!ctx
->Extensions
.ARB_map_buffer_range
)
2683 *params
= bufObj
->Mappings
[MAP_USER
].AccessFlags
;
2685 case GL_BUFFER_MAP_OFFSET
:
2686 if (!ctx
->Extensions
.ARB_map_buffer_range
)
2688 *params
= bufObj
->Mappings
[MAP_USER
].Offset
;
2690 case GL_BUFFER_MAP_LENGTH
:
2691 if (!ctx
->Extensions
.ARB_map_buffer_range
)
2693 *params
= bufObj
->Mappings
[MAP_USER
].Length
;
2695 case GL_BUFFER_IMMUTABLE_STORAGE
:
2696 if (!ctx
->Extensions
.ARB_buffer_storage
)
2698 *params
= bufObj
->Immutable
;
2700 case GL_BUFFER_STORAGE_FLAGS
:
2701 if (!ctx
->Extensions
.ARB_buffer_storage
)
2703 *params
= bufObj
->StorageFlags
;
2712 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(invalid pname: %s)", func
,
2713 _mesa_enum_to_string(pname
));
2718 _mesa_GetBufferParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
2720 GET_CURRENT_CONTEXT(ctx
);
2721 struct gl_buffer_object
*bufObj
;
2724 bufObj
= get_buffer(ctx
, "glGetBufferParameteriv", target
,
2725 GL_INVALID_OPERATION
);
2729 if (!get_buffer_parameter(ctx
, bufObj
, pname
, ¶meter
,
2730 "glGetBufferParameteriv"))
2731 return; /* Error already recorded. */
2733 *params
= (GLint
) parameter
;
2737 _mesa_GetBufferParameteri64v(GLenum target
, GLenum pname
, GLint64
*params
)
2739 GET_CURRENT_CONTEXT(ctx
);
2740 struct gl_buffer_object
*bufObj
;
2743 bufObj
= get_buffer(ctx
, "glGetBufferParameteri64v", target
,
2744 GL_INVALID_OPERATION
);
2748 if (!get_buffer_parameter(ctx
, bufObj
, pname
, ¶meter
,
2749 "glGetBufferParameteri64v"))
2750 return; /* Error already recorded. */
2752 *params
= parameter
;
2756 _mesa_GetNamedBufferParameteriv(GLuint buffer
, GLenum pname
, GLint
*params
)
2758 GET_CURRENT_CONTEXT(ctx
);
2759 struct gl_buffer_object
*bufObj
;
2762 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
,
2763 "glGetNamedBufferParameteriv");
2767 if (!get_buffer_parameter(ctx
, bufObj
, pname
, ¶meter
,
2768 "glGetNamedBufferParameteriv"))
2769 return; /* Error already recorded. */
2771 *params
= (GLint
) parameter
;
2775 _mesa_GetNamedBufferParameteri64v(GLuint buffer
, GLenum pname
,
2778 GET_CURRENT_CONTEXT(ctx
);
2779 struct gl_buffer_object
*bufObj
;
2782 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
,
2783 "glGetNamedBufferParameteri64v");
2787 if (!get_buffer_parameter(ctx
, bufObj
, pname
, ¶meter
,
2788 "glGetNamedBufferParameteri64v"))
2789 return; /* Error already recorded. */
2791 *params
= parameter
;
2796 _mesa_GetBufferPointerv(GLenum target
, GLenum pname
, GLvoid
**params
)
2798 GET_CURRENT_CONTEXT(ctx
);
2799 struct gl_buffer_object
*bufObj
;
2801 if (pname
!= GL_BUFFER_MAP_POINTER
) {
2802 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetBufferPointerv(pname != "
2803 "GL_BUFFER_MAP_POINTER)");
2807 bufObj
= get_buffer(ctx
, "glGetBufferPointerv", target
,
2808 GL_INVALID_OPERATION
);
2812 *params
= bufObj
->Mappings
[MAP_USER
].Pointer
;
2816 _mesa_GetNamedBufferPointerv(GLuint buffer
, GLenum pname
, GLvoid
**params
)
2818 GET_CURRENT_CONTEXT(ctx
);
2819 struct gl_buffer_object
*bufObj
;
2821 if (pname
!= GL_BUFFER_MAP_POINTER
) {
2822 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetNamedBufferPointerv(pname != "
2823 "GL_BUFFER_MAP_POINTER)");
2827 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
,
2828 "glGetNamedBufferPointerv");
2832 *params
= bufObj
->Mappings
[MAP_USER
].Pointer
;
2837 copy_buffer_sub_data(struct gl_context
*ctx
, struct gl_buffer_object
*src
,
2838 struct gl_buffer_object
*dst
, GLintptr readOffset
,
2839 GLintptr writeOffset
, GLsizeiptr size
, const char *func
)
2841 if (_mesa_check_disallowed_mapping(src
)) {
2842 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2843 "%s(readBuffer is mapped)", func
);
2847 if (_mesa_check_disallowed_mapping(dst
)) {
2848 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2849 "%s(writeBuffer is mapped)", func
);
2853 if (readOffset
< 0) {
2854 _mesa_error(ctx
, GL_INVALID_VALUE
,
2855 "%s(readOffset %d < 0)", func
, (int) readOffset
);
2859 if (writeOffset
< 0) {
2860 _mesa_error(ctx
, GL_INVALID_VALUE
,
2861 "%s(writeOffset %d < 0)", func
, (int) writeOffset
);
2866 _mesa_error(ctx
, GL_INVALID_VALUE
,
2867 "%s(size %d < 0)", func
, (int) size
);
2871 if (readOffset
+ size
> src
->Size
) {
2872 _mesa_error(ctx
, GL_INVALID_VALUE
,
2873 "%s(readOffset %d + size %d > src_buffer_size %d)", func
,
2874 (int) readOffset
, (int) size
, (int) src
->Size
);
2878 if (writeOffset
+ size
> dst
->Size
) {
2879 _mesa_error(ctx
, GL_INVALID_VALUE
,
2880 "%s(writeOffset %d + size %d > dst_buffer_size %d)", func
,
2881 (int) writeOffset
, (int) size
, (int) dst
->Size
);
2886 if (readOffset
+ size
<= writeOffset
) {
2889 else if (writeOffset
+ size
<= readOffset
) {
2893 /* overlapping src/dst is illegal */
2894 _mesa_error(ctx
, GL_INVALID_VALUE
,
2895 "%s(overlapping src/dst)", func
);
2900 dst
->MinMaxCacheDirty
= true;
2902 ctx
->Driver
.CopyBufferSubData(ctx
, src
, dst
, readOffset
, writeOffset
, size
);
2906 _mesa_CopyBufferSubData_no_error(GLenum readTarget
, GLenum writeTarget
,
2907 GLintptr readOffset
, GLintptr writeOffset
,
2910 GET_CURRENT_CONTEXT(ctx
);
2912 struct gl_buffer_object
**src_ptr
= get_buffer_target(ctx
, readTarget
);
2913 struct gl_buffer_object
*src
= *src_ptr
;
2915 struct gl_buffer_object
**dst_ptr
= get_buffer_target(ctx
, writeTarget
);
2916 struct gl_buffer_object
*dst
= *dst_ptr
;
2918 dst
->MinMaxCacheDirty
= true;
2919 ctx
->Driver
.CopyBufferSubData(ctx
, src
, dst
, readOffset
, writeOffset
,
2924 _mesa_CopyBufferSubData(GLenum readTarget
, GLenum writeTarget
,
2925 GLintptr readOffset
, GLintptr writeOffset
,
2928 GET_CURRENT_CONTEXT(ctx
);
2929 struct gl_buffer_object
*src
, *dst
;
2931 src
= get_buffer(ctx
, "glCopyBufferSubData", readTarget
,
2932 GL_INVALID_OPERATION
);
2936 dst
= get_buffer(ctx
, "glCopyBufferSubData", writeTarget
,
2937 GL_INVALID_OPERATION
);
2941 copy_buffer_sub_data(ctx
, src
, dst
, readOffset
, writeOffset
, size
,
2942 "glCopyBufferSubData");
2946 _mesa_CopyNamedBufferSubData_no_error(GLuint readBuffer
, GLuint writeBuffer
,
2947 GLintptr readOffset
,
2948 GLintptr writeOffset
, GLsizeiptr size
)
2950 GET_CURRENT_CONTEXT(ctx
);
2952 struct gl_buffer_object
*src
= _mesa_lookup_bufferobj(ctx
, readBuffer
);
2953 struct gl_buffer_object
*dst
= _mesa_lookup_bufferobj(ctx
, writeBuffer
);
2955 dst
->MinMaxCacheDirty
= true;
2956 ctx
->Driver
.CopyBufferSubData(ctx
, src
, dst
, readOffset
, writeOffset
,
2961 _mesa_CopyNamedBufferSubData(GLuint readBuffer
, GLuint writeBuffer
,
2962 GLintptr readOffset
, GLintptr writeOffset
,
2965 GET_CURRENT_CONTEXT(ctx
);
2966 struct gl_buffer_object
*src
, *dst
;
2968 src
= _mesa_lookup_bufferobj_err(ctx
, readBuffer
,
2969 "glCopyNamedBufferSubData");
2973 dst
= _mesa_lookup_bufferobj_err(ctx
, writeBuffer
,
2974 "glCopyNamedBufferSubData");
2978 copy_buffer_sub_data(ctx
, src
, dst
, readOffset
, writeOffset
, size
,
2979 "glCopyNamedBufferSubData");
2983 validate_map_buffer_range(struct gl_context
*ctx
,
2984 struct gl_buffer_object
*bufObj
, GLintptr offset
,
2985 GLsizeiptr length
, GLbitfield access
,
2988 GLbitfield allowed_access
;
2990 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, false);
2993 _mesa_error(ctx
, GL_INVALID_VALUE
,
2994 "%s(offset %ld < 0)", func
, (long) offset
);
2999 _mesa_error(ctx
, GL_INVALID_VALUE
,
3000 "%s(length %ld < 0)", func
, (long) length
);
3004 /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
3006 * "An INVALID_OPERATION error is generated for any of the following
3009 * * <length> is zero."
3011 * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec
3012 * (30.10.2014) also says this, so it's no longer allowed for desktop GL,
3016 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(length = 0)", func
);
3020 allowed_access
= GL_MAP_READ_BIT
|
3022 GL_MAP_INVALIDATE_RANGE_BIT
|
3023 GL_MAP_INVALIDATE_BUFFER_BIT
|
3024 GL_MAP_FLUSH_EXPLICIT_BIT
|
3025 GL_MAP_UNSYNCHRONIZED_BIT
;
3027 if (ctx
->Extensions
.ARB_buffer_storage
) {
3028 allowed_access
|= GL_MAP_PERSISTENT_BIT
|
3029 GL_MAP_COHERENT_BIT
;
3032 if (access
& ~allowed_access
) {
3033 /* generate an error if any bits other than those allowed are set */
3034 _mesa_error(ctx
, GL_INVALID_VALUE
,
3035 "%s(access has undefined bits set)", func
);
3039 if ((access
& (GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
)) == 0) {
3040 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3041 "%s(access indicates neither read or write)", func
);
3045 if ((access
& GL_MAP_READ_BIT
) &&
3046 (access
& (GL_MAP_INVALIDATE_RANGE_BIT
|
3047 GL_MAP_INVALIDATE_BUFFER_BIT
|
3048 GL_MAP_UNSYNCHRONIZED_BIT
))) {
3049 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3050 "%s(read access with disallowed bits)", func
);
3054 if ((access
& GL_MAP_FLUSH_EXPLICIT_BIT
) &&
3055 ((access
& GL_MAP_WRITE_BIT
) == 0)) {
3056 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3057 "%s(access has flush explicit without write)", func
);
3061 if (access
& GL_MAP_READ_BIT
&&
3062 !(bufObj
->StorageFlags
& GL_MAP_READ_BIT
)) {
3063 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3064 "%s(buffer does not allow read access)", func
);
3068 if (access
& GL_MAP_WRITE_BIT
&&
3069 !(bufObj
->StorageFlags
& GL_MAP_WRITE_BIT
)) {
3070 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3071 "%s(buffer does not allow write access)", func
);
3075 if (access
& GL_MAP_COHERENT_BIT
&&
3076 !(bufObj
->StorageFlags
& GL_MAP_COHERENT_BIT
)) {
3077 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3078 "%s(buffer does not allow coherent access)", func
);
3082 if (access
& GL_MAP_PERSISTENT_BIT
&&
3083 !(bufObj
->StorageFlags
& GL_MAP_PERSISTENT_BIT
)) {
3084 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3085 "%s(buffer does not allow persistent access)", func
);
3089 if (offset
+ length
> bufObj
->Size
) {
3090 _mesa_error(ctx
, GL_INVALID_VALUE
,
3091 "%s(offset %lu + length %lu > buffer_size %lu)", func
,
3092 (unsigned long) offset
, (unsigned long) length
,
3093 (unsigned long) bufObj
->Size
);
3097 if (_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
3098 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3099 "%s(buffer already mapped)", func
);
3103 if (access
& GL_MAP_WRITE_BIT
) {
3104 bufObj
->NumMapBufferWriteCalls
++;
3105 if ((bufObj
->Usage
== GL_STATIC_DRAW
||
3106 bufObj
->Usage
== GL_STATIC_COPY
) &&
3107 bufObj
->NumMapBufferWriteCalls
>= BUFFER_WARNING_CALL_COUNT
) {
3108 BUFFER_USAGE_WARNING(ctx
,
3109 "using %s(buffer %u, offset %u, length %u) to "
3110 "update a %s buffer",
3111 func
, bufObj
->Name
, offset
, length
,
3112 _mesa_enum_to_string(bufObj
->Usage
));
3120 map_buffer_range(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
3121 GLintptr offset
, GLsizeiptr length
, GLbitfield access
,
3124 if (!bufObj
->Size
) {
3125 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s(buffer size = 0)", func
);
3129 assert(ctx
->Driver
.MapBufferRange
);
3130 void *map
= ctx
->Driver
.MapBufferRange(ctx
, offset
, length
, access
, bufObj
,
3133 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s(map failed)", func
);
3136 /* The driver callback should have set all these fields.
3137 * This is important because other modules (like VBO) might call
3138 * the driver function directly.
3140 assert(bufObj
->Mappings
[MAP_USER
].Pointer
== map
);
3141 assert(bufObj
->Mappings
[MAP_USER
].Length
== length
);
3142 assert(bufObj
->Mappings
[MAP_USER
].Offset
== offset
);
3143 assert(bufObj
->Mappings
[MAP_USER
].AccessFlags
== access
);
3146 if (access
& GL_MAP_WRITE_BIT
) {
3147 bufObj
->Written
= GL_TRUE
;
3148 bufObj
->MinMaxCacheDirty
= true;
3152 if (strstr(func
, "Range") == NULL
) { /* If not MapRange */
3153 printf("glMapBuffer(%u, sz %ld, access 0x%x)\n",
3154 bufObj
->Name
, bufObj
->Size
, access
);
3155 /* Access must be write only */
3156 if ((access
& GL_MAP_WRITE_BIT
) && (!(access
& ~GL_MAP_WRITE_BIT
))) {
3158 GLubyte
*b
= (GLubyte
*) bufObj
->Pointer
;
3159 for (i
= 0; i
< bufObj
->Size
; i
++)
3166 if (strstr(func
, "Range") == NULL
) { /* If not MapRange */
3167 GLubyte
*buf
= (GLubyte
*) bufObj
->Pointer
;
3169 /* buffer is 100 bytes larger than requested, fill with magic value */
3170 for (i
= 0; i
< 100; i
++) {
3171 buf
[bufObj
->Size
- i
- 1] = 123;
3180 _mesa_MapBufferRange_no_error(GLenum target
, GLintptr offset
,
3181 GLsizeiptr length
, GLbitfield access
)
3183 GET_CURRENT_CONTEXT(ctx
);
3185 struct gl_buffer_object
**bufObjPtr
= get_buffer_target(ctx
, target
);
3186 struct gl_buffer_object
*bufObj
= *bufObjPtr
;
3188 return map_buffer_range(ctx
, bufObj
, offset
, length
, access
,
3189 "glMapBufferRange");
3193 _mesa_MapBufferRange(GLenum target
, GLintptr offset
, GLsizeiptr length
,
3196 GET_CURRENT_CONTEXT(ctx
);
3197 struct gl_buffer_object
*bufObj
;
3199 if (!ctx
->Extensions
.ARB_map_buffer_range
) {
3200 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3201 "glMapBufferRange(ARB_map_buffer_range not supported)");
3205 bufObj
= get_buffer(ctx
, "glMapBufferRange", target
, GL_INVALID_OPERATION
);
3209 if (!validate_map_buffer_range(ctx
, bufObj
, offset
, length
, access
,
3210 "glMapBufferRange"))
3213 return map_buffer_range(ctx
, bufObj
, offset
, length
, access
,
3214 "glMapBufferRange");
3218 _mesa_MapNamedBufferRange_no_error(GLuint buffer
, GLintptr offset
,
3219 GLsizeiptr length
, GLbitfield access
)
3221 GET_CURRENT_CONTEXT(ctx
);
3222 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
3224 return map_buffer_range(ctx
, bufObj
, offset
, length
, access
,
3225 "glMapNamedBufferRange");
3229 _mesa_MapNamedBufferRange(GLuint buffer
, GLintptr offset
, GLsizeiptr length
,
3232 GET_CURRENT_CONTEXT(ctx
);
3233 struct gl_buffer_object
*bufObj
;
3235 if (!ctx
->Extensions
.ARB_map_buffer_range
) {
3236 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3237 "glMapNamedBufferRange("
3238 "ARB_map_buffer_range not supported)");
3242 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
, "glMapNamedBufferRange");
3246 if (!validate_map_buffer_range(ctx
, bufObj
, offset
, length
, access
,
3247 "glMapNamedBufferRange"))
3250 return map_buffer_range(ctx
, bufObj
, offset
, length
, access
,
3251 "glMapNamedBufferRange");
3255 * Converts GLenum access from MapBuffer and MapNamedBuffer into
3256 * flags for input to map_buffer_range.
3258 * \return true if the type of requested access is permissible.
3261 get_map_buffer_access_flags(struct gl_context
*ctx
, GLenum access
,
3265 case GL_READ_ONLY_ARB
:
3266 *flags
= GL_MAP_READ_BIT
;
3267 return _mesa_is_desktop_gl(ctx
);
3268 case GL_WRITE_ONLY_ARB
:
3269 *flags
= GL_MAP_WRITE_BIT
;
3271 case GL_READ_WRITE_ARB
:
3272 *flags
= GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
;
3273 return _mesa_is_desktop_gl(ctx
);
3281 _mesa_MapBuffer_no_error(GLenum target
, GLenum access
)
3283 GET_CURRENT_CONTEXT(ctx
);
3285 GLbitfield accessFlags
;
3286 get_map_buffer_access_flags(ctx
, access
, &accessFlags
);
3288 struct gl_buffer_object
**bufObjPtr
= get_buffer_target(ctx
, target
);
3289 struct gl_buffer_object
*bufObj
= *bufObjPtr
;
3291 return map_buffer_range(ctx
, bufObj
, 0, bufObj
->Size
, accessFlags
,
3296 _mesa_MapBuffer(GLenum target
, GLenum access
)
3298 GET_CURRENT_CONTEXT(ctx
);
3299 struct gl_buffer_object
*bufObj
;
3300 GLbitfield accessFlags
;
3302 if (!get_map_buffer_access_flags(ctx
, access
, &accessFlags
)) {
3303 _mesa_error(ctx
, GL_INVALID_ENUM
, "glMapBuffer(invalid access)");
3307 bufObj
= get_buffer(ctx
, "glMapBuffer", target
, GL_INVALID_OPERATION
);
3311 if (!validate_map_buffer_range(ctx
, bufObj
, 0, bufObj
->Size
, accessFlags
,
3315 return map_buffer_range(ctx
, bufObj
, 0, bufObj
->Size
, accessFlags
,
3320 _mesa_MapNamedBuffer_no_error(GLuint buffer
, GLenum access
)
3322 GET_CURRENT_CONTEXT(ctx
);
3324 GLbitfield accessFlags
;
3325 get_map_buffer_access_flags(ctx
, access
, &accessFlags
);
3327 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
3329 return map_buffer_range(ctx
, bufObj
, 0, bufObj
->Size
, accessFlags
,
3330 "glMapNamedBuffer");
3334 _mesa_MapNamedBuffer(GLuint buffer
, GLenum access
)
3336 GET_CURRENT_CONTEXT(ctx
);
3337 struct gl_buffer_object
*bufObj
;
3338 GLbitfield accessFlags
;
3340 if (!get_map_buffer_access_flags(ctx
, access
, &accessFlags
)) {
3341 _mesa_error(ctx
, GL_INVALID_ENUM
, "glMapNamedBuffer(invalid access)");
3345 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
, "glMapNamedBuffer");
3349 if (!validate_map_buffer_range(ctx
, bufObj
, 0, bufObj
->Size
, accessFlags
,
3350 "glMapNamedBuffer"))
3353 return map_buffer_range(ctx
, bufObj
, 0, bufObj
->Size
, accessFlags
,
3354 "glMapNamedBuffer");
3359 flush_mapped_buffer_range(struct gl_context
*ctx
,
3360 struct gl_buffer_object
*bufObj
,
3361 GLintptr offset
, GLsizeiptr length
,
3364 if (!ctx
->Extensions
.ARB_map_buffer_range
) {
3365 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3366 "%s(ARB_map_buffer_range not supported)", func
);
3371 _mesa_error(ctx
, GL_INVALID_VALUE
,
3372 "%s(offset %ld < 0)", func
, (long) offset
);
3377 _mesa_error(ctx
, GL_INVALID_VALUE
,
3378 "%s(length %ld < 0)", func
, (long) length
);
3382 if (!_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
3383 /* buffer is not mapped */
3384 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3385 "%s(buffer is not mapped)", func
);
3389 if ((bufObj
->Mappings
[MAP_USER
].AccessFlags
&
3390 GL_MAP_FLUSH_EXPLICIT_BIT
) == 0) {
3391 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3392 "%s(GL_MAP_FLUSH_EXPLICIT_BIT not set)", func
);
3396 if (offset
+ length
> bufObj
->Mappings
[MAP_USER
].Length
) {
3397 _mesa_error(ctx
, GL_INVALID_VALUE
,
3398 "%s(offset %ld + length %ld > mapped length %ld)", func
,
3399 (long) offset
, (long) length
,
3400 (long) bufObj
->Mappings
[MAP_USER
].Length
);
3404 assert(bufObj
->Mappings
[MAP_USER
].AccessFlags
& GL_MAP_WRITE_BIT
);
3406 if (ctx
->Driver
.FlushMappedBufferRange
)
3407 ctx
->Driver
.FlushMappedBufferRange(ctx
, offset
, length
, bufObj
,
3412 _mesa_FlushMappedBufferRange_no_error(GLenum target
, GLintptr offset
,
3415 GET_CURRENT_CONTEXT(ctx
);
3416 struct gl_buffer_object
**bufObjPtr
= get_buffer_target(ctx
, target
);
3417 struct gl_buffer_object
*bufObj
= *bufObjPtr
;
3419 if (ctx
->Driver
.FlushMappedBufferRange
)
3420 ctx
->Driver
.FlushMappedBufferRange(ctx
, offset
, length
, bufObj
,
3425 _mesa_FlushMappedBufferRange(GLenum target
, GLintptr offset
,
3428 GET_CURRENT_CONTEXT(ctx
);
3429 struct gl_buffer_object
*bufObj
;
3431 bufObj
= get_buffer(ctx
, "glFlushMappedBufferRange", target
,
3432 GL_INVALID_OPERATION
);
3436 flush_mapped_buffer_range(ctx
, bufObj
, offset
, length
,
3437 "glFlushMappedBufferRange");
3441 _mesa_FlushMappedNamedBufferRange_no_error(GLuint buffer
, GLintptr offset
,
3444 GET_CURRENT_CONTEXT(ctx
);
3445 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
3447 if (ctx
->Driver
.FlushMappedBufferRange
)
3448 ctx
->Driver
.FlushMappedBufferRange(ctx
, offset
, length
, bufObj
,
3453 _mesa_FlushMappedNamedBufferRange(GLuint buffer
, GLintptr offset
,
3456 GET_CURRENT_CONTEXT(ctx
);
3457 struct gl_buffer_object
*bufObj
;
3459 bufObj
= _mesa_lookup_bufferobj_err(ctx
, buffer
,
3460 "glFlushMappedNamedBufferRange");
3464 flush_mapped_buffer_range(ctx
, bufObj
, offset
, length
,
3465 "glFlushMappedNamedBufferRange");
3469 bind_buffer_range_uniform_buffer(struct gl_context
*ctx
, GLuint index
,
3470 struct gl_buffer_object
*bufObj
,
3471 GLintptr offset
, GLsizeiptr size
)
3473 if (bufObj
== ctx
->Shared
->NullBufferObj
) {
3478 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
, bufObj
);
3479 bind_uniform_buffer(ctx
, index
, bufObj
, offset
, size
, GL_FALSE
);
3483 * Bind a region of a buffer object to a uniform block binding point.
3484 * \param index the uniform buffer binding point index
3485 * \param bufObj the buffer object
3486 * \param offset offset to the start of buffer object region
3487 * \param size size of the buffer object region
3490 bind_buffer_range_uniform_buffer_err(struct gl_context
*ctx
, GLuint index
,
3491 struct gl_buffer_object
*bufObj
,
3492 GLintptr offset
, GLsizeiptr size
)
3494 if (index
>= ctx
->Const
.MaxUniformBufferBindings
) {
3495 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferRange(index=%d)", index
);
3499 if (offset
& (ctx
->Const
.UniformBufferOffsetAlignment
- 1)) {
3500 _mesa_error(ctx
, GL_INVALID_VALUE
,
3501 "glBindBufferRange(offset misaligned %d/%d)", (int) offset
,
3502 ctx
->Const
.UniformBufferOffsetAlignment
);
3506 bind_buffer_range_uniform_buffer(ctx
, index
, bufObj
, offset
, size
);
3510 bind_buffer_range_shader_storage_buffer(struct gl_context
*ctx
,
3512 struct gl_buffer_object
*bufObj
,
3516 if (bufObj
== ctx
->Shared
->NullBufferObj
) {
3521 _mesa_reference_buffer_object(ctx
, &ctx
->ShaderStorageBuffer
, bufObj
);
3522 bind_shader_storage_buffer(ctx
, index
, bufObj
, offset
, size
, GL_FALSE
);
3526 * Bind a region of a buffer object to a shader storage block binding point.
3527 * \param index the shader storage buffer binding point index
3528 * \param bufObj the buffer object
3529 * \param offset offset to the start of buffer object region
3530 * \param size size of the buffer object region
3533 bind_buffer_range_shader_storage_buffer_err(struct gl_context
*ctx
,
3535 struct gl_buffer_object
*bufObj
,
3536 GLintptr offset
, GLsizeiptr size
)
3538 if (index
>= ctx
->Const
.MaxShaderStorageBufferBindings
) {
3539 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferRange(index=%d)", index
);
3543 if (offset
& (ctx
->Const
.ShaderStorageBufferOffsetAlignment
- 1)) {
3544 _mesa_error(ctx
, GL_INVALID_VALUE
,
3545 "glBindBufferRange(offset misaligned %d/%d)", (int) offset
,
3546 ctx
->Const
.ShaderStorageBufferOffsetAlignment
);
3550 bind_buffer_range_shader_storage_buffer(ctx
, index
, bufObj
, offset
, size
);
3554 bind_buffer_range_atomic_buffer(struct gl_context
*ctx
, GLuint index
,
3555 struct gl_buffer_object
*bufObj
,
3556 GLintptr offset
, GLsizeiptr size
)
3558 if (bufObj
== ctx
->Shared
->NullBufferObj
) {
3563 _mesa_reference_buffer_object(ctx
, &ctx
->AtomicBuffer
, bufObj
);
3564 bind_atomic_buffer(ctx
, index
, bufObj
, offset
, size
, GL_FALSE
);
3568 * Bind a region of a buffer object to an atomic storage block binding point.
3569 * \param index the shader storage buffer binding point index
3570 * \param bufObj the buffer object
3571 * \param offset offset to the start of buffer object region
3572 * \param size size of the buffer object region
3575 bind_buffer_range_atomic_buffer_err(struct gl_context
*ctx
,
3577 struct gl_buffer_object
*bufObj
,
3578 GLintptr offset
, GLsizeiptr size
)
3580 if (index
>= ctx
->Const
.MaxAtomicBufferBindings
) {
3581 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferRange(index=%d)", index
);
3585 if (offset
& (ATOMIC_COUNTER_SIZE
- 1)) {
3586 _mesa_error(ctx
, GL_INVALID_VALUE
,
3587 "glBindBufferRange(offset misaligned %d/%d)", (int) offset
,
3588 ATOMIC_COUNTER_SIZE
);
3592 bind_buffer_range_atomic_buffer(ctx
, index
, bufObj
, offset
, size
);
3596 bind_buffers_check_offset_and_size(struct gl_context
*ctx
,
3598 const GLintptr
*offsets
,
3599 const GLsizeiptr
*sizes
)
3601 if (offsets
[index
] < 0) {
3602 /* The ARB_multi_bind spec says:
3604 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3605 * value in <offsets> is less than zero (per binding)."
3607 _mesa_error(ctx
, GL_INVALID_VALUE
,
3608 "glBindBuffersRange(offsets[%u]=%" PRId64
" < 0)",
3609 index
, (int64_t) offsets
[index
]);
3613 if (sizes
[index
] <= 0) {
3614 /* The ARB_multi_bind spec says:
3616 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3617 * value in <sizes> is less than or equal to zero (per binding)."
3619 _mesa_error(ctx
, GL_INVALID_VALUE
,
3620 "glBindBuffersRange(sizes[%u]=%" PRId64
" <= 0)",
3621 index
, (int64_t) sizes
[index
]);
3629 error_check_bind_uniform_buffers(struct gl_context
*ctx
,
3630 GLuint first
, GLsizei count
,
3633 if (!ctx
->Extensions
.ARB_uniform_buffer_object
) {
3634 _mesa_error(ctx
, GL_INVALID_ENUM
,
3635 "%s(target=GL_UNIFORM_BUFFER)", caller
);
3639 /* The ARB_multi_bind_spec says:
3641 * "An INVALID_OPERATION error is generated if <first> + <count> is
3642 * greater than the number of target-specific indexed binding points,
3643 * as described in section 6.7.1."
3645 if (first
+ count
> ctx
->Const
.MaxUniformBufferBindings
) {
3646 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3647 "%s(first=%u + count=%d > the value of "
3648 "GL_MAX_UNIFORM_BUFFER_BINDINGS=%u)",
3649 caller
, first
, count
,
3650 ctx
->Const
.MaxUniformBufferBindings
);
3658 error_check_bind_shader_storage_buffers(struct gl_context
*ctx
,
3659 GLuint first
, GLsizei count
,
3662 if (!ctx
->Extensions
.ARB_shader_storage_buffer_object
) {
3663 _mesa_error(ctx
, GL_INVALID_ENUM
,
3664 "%s(target=GL_SHADER_STORAGE_BUFFER)", caller
);
3668 /* The ARB_multi_bind_spec says:
3670 * "An INVALID_OPERATION error is generated if <first> + <count> is
3671 * greater than the number of target-specific indexed binding points,
3672 * as described in section 6.7.1."
3674 if (first
+ count
> ctx
->Const
.MaxShaderStorageBufferBindings
) {
3675 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3676 "%s(first=%u + count=%d > the value of "
3677 "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS=%u)",
3678 caller
, first
, count
,
3679 ctx
->Const
.MaxShaderStorageBufferBindings
);
3687 * Unbind all uniform buffers in the range
3688 * <first> through <first>+<count>-1
3691 unbind_uniform_buffers(struct gl_context
*ctx
, GLuint first
, GLsizei count
)
3693 struct gl_buffer_object
*bufObj
= ctx
->Shared
->NullBufferObj
;
3695 for (int i
= 0; i
< count
; i
++)
3696 set_buffer_binding(ctx
, &ctx
->UniformBufferBindings
[first
+ i
],
3697 bufObj
, -1, -1, GL_TRUE
, 0);
3701 * Unbind all shader storage buffers in the range
3702 * <first> through <first>+<count>-1
3705 unbind_shader_storage_buffers(struct gl_context
*ctx
, GLuint first
,
3708 struct gl_buffer_object
*bufObj
= ctx
->Shared
->NullBufferObj
;
3710 for (int i
= 0; i
< count
; i
++)
3711 set_buffer_binding(ctx
, &ctx
->ShaderStorageBufferBindings
[first
+ i
],
3712 bufObj
, -1, -1, GL_TRUE
, 0);
3716 bind_uniform_buffers(struct gl_context
*ctx
, GLuint first
, GLsizei count
,
3717 const GLuint
*buffers
,
3719 const GLintptr
*offsets
, const GLsizeiptr
*sizes
,
3722 if (!error_check_bind_uniform_buffers(ctx
, first
, count
, caller
))
3725 /* Assume that at least one binding will be changed */
3726 FLUSH_VERTICES(ctx
, 0);
3727 ctx
->NewDriverState
|= ctx
->DriverFlags
.NewUniformBuffer
;
3730 /* The ARB_multi_bind spec says:
3732 * "If <buffers> is NULL, all bindings from <first> through
3733 * <first>+<count>-1 are reset to their unbound (zero) state.
3734 * In this case, the offsets and sizes associated with the
3735 * binding points are set to default values, ignoring
3736 * <offsets> and <sizes>."
3738 unbind_uniform_buffers(ctx
, first
, count
);
3742 /* Note that the error semantics for multi-bind commands differ from
3743 * those of other GL commands.
3745 * The Issues section in the ARB_multi_bind spec says:
3747 * "(11) Typically, OpenGL specifies that if an error is generated by a
3748 * command, that command has no effect. This is somewhat
3749 * unfortunate for multi-bind commands, because it would require a
3750 * first pass to scan the entire list of bound objects for errors
3751 * and then a second pass to actually perform the bindings.
3752 * Should we have different error semantics?
3754 * RESOLVED: Yes. In this specification, when the parameters for
3755 * one of the <count> binding points are invalid, that binding point
3756 * is not updated and an error will be generated. However, other
3757 * binding points in the same command will be updated if their
3758 * parameters are valid and no other error occurs."
3761 _mesa_HashLockMutex(ctx
->Shared
->BufferObjects
);
3763 for (int i
= 0; i
< count
; i
++) {
3764 struct gl_buffer_binding
*binding
=
3765 &ctx
->UniformBufferBindings
[first
+ i
];
3766 GLintptr offset
= 0;
3767 GLsizeiptr size
= 0;
3770 if (!bind_buffers_check_offset_and_size(ctx
, i
, offsets
, sizes
))
3773 /* The ARB_multi_bind spec says:
3775 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3776 * pair of values in <offsets> and <sizes> does not respectively
3777 * satisfy the constraints described for those parameters for the
3778 * specified target, as described in section 6.7.1 (per binding)."
3780 * Section 6.7.1 refers to table 6.5, which says:
3782 * "┌───────────────────────────────────────────────────────────────┐
3783 * │ Uniform buffer array bindings (see sec. 7.6) │
3784 * ├─────────────────────┬─────────────────────────────────────────┤
3786 * │ offset restriction │ multiple of value of UNIFORM_BUFFER_- │
3787 * │ │ OFFSET_ALIGNMENT │
3789 * │ size restriction │ none │
3790 * └─────────────────────┴─────────────────────────────────────────┘"
3792 if (offsets
[i
] & (ctx
->Const
.UniformBufferOffsetAlignment
- 1)) {
3793 _mesa_error(ctx
, GL_INVALID_VALUE
,
3794 "glBindBuffersRange(offsets[%u]=%" PRId64
3795 " is misaligned; it must be a multiple of the value of "
3796 "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT=%u when "
3797 "target=GL_UNIFORM_BUFFER)",
3798 i
, (int64_t) offsets
[i
],
3799 ctx
->Const
.UniformBufferOffsetAlignment
);
3803 offset
= offsets
[i
];
3807 set_buffer_multi_binding(ctx
, buffers
, i
, caller
,
3808 binding
, offset
, size
, range
,
3809 USAGE_UNIFORM_BUFFER
);
3812 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
3816 bind_shader_storage_buffers(struct gl_context
*ctx
, GLuint first
,
3817 GLsizei count
, const GLuint
*buffers
,
3819 const GLintptr
*offsets
,
3820 const GLsizeiptr
*sizes
,
3823 if (!error_check_bind_shader_storage_buffers(ctx
, first
, count
, caller
))
3826 /* Assume that at least one binding will be changed */
3827 FLUSH_VERTICES(ctx
, 0);
3828 ctx
->NewDriverState
|= ctx
->DriverFlags
.NewShaderStorageBuffer
;
3831 /* The ARB_multi_bind spec says:
3833 * "If <buffers> is NULL, all bindings from <first> through
3834 * <first>+<count>-1 are reset to their unbound (zero) state.
3835 * In this case, the offsets and sizes associated with the
3836 * binding points are set to default values, ignoring
3837 * <offsets> and <sizes>."
3839 unbind_shader_storage_buffers(ctx
, first
, count
);
3843 /* Note that the error semantics for multi-bind commands differ from
3844 * those of other GL commands.
3846 * The Issues section in the ARB_multi_bind spec says:
3848 * "(11) Typically, OpenGL specifies that if an error is generated by a
3849 * command, that command has no effect. This is somewhat
3850 * unfortunate for multi-bind commands, because it would require a
3851 * first pass to scan the entire list of bound objects for errors
3852 * and then a second pass to actually perform the bindings.
3853 * Should we have different error semantics?
3855 * RESOLVED: Yes. In this specification, when the parameters for
3856 * one of the <count> binding points are invalid, that binding point
3857 * is not updated and an error will be generated. However, other
3858 * binding points in the same command will be updated if their
3859 * parameters are valid and no other error occurs."
3862 _mesa_HashLockMutex(ctx
->Shared
->BufferObjects
);
3864 for (int i
= 0; i
< count
; i
++) {
3865 struct gl_buffer_binding
*binding
=
3866 &ctx
->ShaderStorageBufferBindings
[first
+ i
];
3867 GLintptr offset
= 0;
3868 GLsizeiptr size
= 0;
3871 if (!bind_buffers_check_offset_and_size(ctx
, i
, offsets
, sizes
))
3874 /* The ARB_multi_bind spec says:
3876 * "An INVALID_VALUE error is generated by BindBuffersRange if any
3877 * pair of values in <offsets> and <sizes> does not respectively
3878 * satisfy the constraints described for those parameters for the
3879 * specified target, as described in section 6.7.1 (per binding)."
3881 * Section 6.7.1 refers to table 6.5, which says:
3883 * "┌───────────────────────────────────────────────────────────────┐
3884 * │ Shader storage buffer array bindings (see sec. 7.8) │
3885 * ├─────────────────────┬─────────────────────────────────────────┤
3887 * │ offset restriction │ multiple of value of SHADER_STORAGE_- │
3888 * │ │ BUFFER_OFFSET_ALIGNMENT │
3890 * │ size restriction │ none │
3891 * └─────────────────────┴─────────────────────────────────────────┘"
3893 if (offsets
[i
] & (ctx
->Const
.ShaderStorageBufferOffsetAlignment
- 1)) {
3894 _mesa_error(ctx
, GL_INVALID_VALUE
,
3895 "glBindBuffersRange(offsets[%u]=%" PRId64
3896 " is misaligned; it must be a multiple of the value of "
3897 "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT=%u when "
3898 "target=GL_SHADER_STORAGE_BUFFER)",
3899 i
, (int64_t) offsets
[i
],
3900 ctx
->Const
.ShaderStorageBufferOffsetAlignment
);
3904 offset
= offsets
[i
];
3908 set_buffer_multi_binding(ctx
, buffers
, i
, caller
,
3909 binding
, offset
, size
, range
,
3910 USAGE_SHADER_STORAGE_BUFFER
);
3913 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
3917 error_check_bind_xfb_buffers(struct gl_context
*ctx
,
3918 struct gl_transform_feedback_object
*tfObj
,
3919 GLuint first
, GLsizei count
, const char *caller
)
3921 if (!ctx
->Extensions
.EXT_transform_feedback
) {
3922 _mesa_error(ctx
, GL_INVALID_ENUM
,
3923 "%s(target=GL_TRANSFORM_FEEDBACK_BUFFER)", caller
);
3927 /* Page 398 of the PDF of the OpenGL 4.4 (Core Profile) spec says:
3929 * "An INVALID_OPERATION error is generated :
3932 * • by BindBufferRange or BindBufferBase if target is TRANSFORM_-
3933 * FEEDBACK_BUFFER and transform feedback is currently active."
3935 * We assume that this is also meant to apply to BindBuffersRange
3936 * and BindBuffersBase.
3938 if (tfObj
->Active
) {
3939 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3940 "%s(Changing transform feedback buffers while "
3941 "transform feedback is active)", caller
);
3945 /* The ARB_multi_bind_spec says:
3947 * "An INVALID_OPERATION error is generated if <first> + <count> is
3948 * greater than the number of target-specific indexed binding points,
3949 * as described in section 6.7.1."
3951 if (first
+ count
> ctx
->Const
.MaxTransformFeedbackBuffers
) {
3952 _mesa_error(ctx
, GL_INVALID_OPERATION
,
3953 "%s(first=%u + count=%d > the value of "
3954 "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS=%u)",
3955 caller
, first
, count
,
3956 ctx
->Const
.MaxTransformFeedbackBuffers
);
3964 * Unbind all transform feedback buffers in the range
3965 * <first> through <first>+<count>-1
3968 unbind_xfb_buffers(struct gl_context
*ctx
,
3969 struct gl_transform_feedback_object
*tfObj
,
3970 GLuint first
, GLsizei count
)
3972 struct gl_buffer_object
* const bufObj
= ctx
->Shared
->NullBufferObj
;
3974 for (int i
= 0; i
< count
; i
++)
3975 _mesa_set_transform_feedback_binding(ctx
, tfObj
, first
+ i
,
3980 bind_xfb_buffers(struct gl_context
*ctx
,
3981 GLuint first
, GLsizei count
,
3982 const GLuint
*buffers
,
3984 const GLintptr
*offsets
,
3985 const GLsizeiptr
*sizes
,
3988 struct gl_transform_feedback_object
*tfObj
=
3989 ctx
->TransformFeedback
.CurrentObject
;
3991 if (!error_check_bind_xfb_buffers(ctx
, tfObj
, first
, count
, caller
))
3994 /* Assume that at least one binding will be changed */
3995 FLUSH_VERTICES(ctx
, 0);
3996 ctx
->NewDriverState
|= ctx
->DriverFlags
.NewTransformFeedback
;
3999 /* The ARB_multi_bind spec says:
4001 * "If <buffers> is NULL, all bindings from <first> through
4002 * <first>+<count>-1 are reset to their unbound (zero) state.
4003 * In this case, the offsets and sizes associated with the
4004 * binding points are set to default values, ignoring
4005 * <offsets> and <sizes>."
4007 unbind_xfb_buffers(ctx
, tfObj
, first
, count
);
4011 /* Note that the error semantics for multi-bind commands differ from
4012 * those of other GL commands.
4014 * The Issues section in the ARB_multi_bind spec says:
4016 * "(11) Typically, OpenGL specifies that if an error is generated by a
4017 * command, that command has no effect. This is somewhat
4018 * unfortunate for multi-bind commands, because it would require a
4019 * first pass to scan the entire list of bound objects for errors
4020 * and then a second pass to actually perform the bindings.
4021 * Should we have different error semantics?
4023 * RESOLVED: Yes. In this specification, when the parameters for
4024 * one of the <count> binding points are invalid, that binding point
4025 * is not updated and an error will be generated. However, other
4026 * binding points in the same command will be updated if their
4027 * parameters are valid and no other error occurs."
4030 _mesa_HashLockMutex(ctx
->Shared
->BufferObjects
);
4032 for (int i
= 0; i
< count
; i
++) {
4033 const GLuint index
= first
+ i
;
4034 struct gl_buffer_object
* const boundBufObj
= tfObj
->Buffers
[index
];
4035 struct gl_buffer_object
*bufObj
;
4036 GLintptr offset
= 0;
4037 GLsizeiptr size
= 0;
4040 if (!bind_buffers_check_offset_and_size(ctx
, i
, offsets
, sizes
))
4043 /* The ARB_multi_bind spec says:
4045 * "An INVALID_VALUE error is generated by BindBuffersRange if any
4046 * pair of values in <offsets> and <sizes> does not respectively
4047 * satisfy the constraints described for those parameters for the
4048 * specified target, as described in section 6.7.1 (per binding)."
4050 * Section 6.7.1 refers to table 6.5, which says:
4052 * "┌───────────────────────────────────────────────────────────────┐
4053 * │ Transform feedback array bindings (see sec. 13.2.2) │
4054 * ├───────────────────────┬───────────────────────────────────────┤
4056 * │ offset restriction │ multiple of 4 │
4058 * │ size restriction │ multiple of 4 │
4059 * └───────────────────────┴───────────────────────────────────────┘"
4061 if (offsets
[i
] & 0x3) {
4062 _mesa_error(ctx
, GL_INVALID_VALUE
,
4063 "glBindBuffersRange(offsets[%u]=%" PRId64
4064 " is misaligned; it must be a multiple of 4 when "
4065 "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
4066 i
, (int64_t) offsets
[i
]);
4070 if (sizes
[i
] & 0x3) {
4071 _mesa_error(ctx
, GL_INVALID_VALUE
,
4072 "glBindBuffersRange(sizes[%u]=%" PRId64
4073 " is misaligned; it must be a multiple of 4 when "
4074 "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
4075 i
, (int64_t) sizes
[i
]);
4079 offset
= offsets
[i
];
4083 if (boundBufObj
&& boundBufObj
->Name
== buffers
[i
])
4084 bufObj
= boundBufObj
;
4086 bufObj
= _mesa_multi_bind_lookup_bufferobj(ctx
, buffers
, i
, caller
);
4089 _mesa_set_transform_feedback_binding(ctx
, tfObj
, index
, bufObj
,
4093 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
4097 error_check_bind_atomic_buffers(struct gl_context
*ctx
,
4098 GLuint first
, GLsizei count
,
4101 if (!ctx
->Extensions
.ARB_shader_atomic_counters
) {
4102 _mesa_error(ctx
, GL_INVALID_ENUM
,
4103 "%s(target=GL_ATOMIC_COUNTER_BUFFER)", caller
);
4107 /* The ARB_multi_bind_spec says:
4109 * "An INVALID_OPERATION error is generated if <first> + <count> is
4110 * greater than the number of target-specific indexed binding points,
4111 * as described in section 6.7.1."
4113 if (first
+ count
> ctx
->Const
.MaxAtomicBufferBindings
) {
4114 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4115 "%s(first=%u + count=%d > the value of "
4116 "GL_MAX_ATOMIC_BUFFER_BINDINGS=%u)",
4117 caller
, first
, count
, ctx
->Const
.MaxAtomicBufferBindings
);
4125 * Unbind all atomic counter buffers in the range
4126 * <first> through <first>+<count>-1
4129 unbind_atomic_buffers(struct gl_context
*ctx
, GLuint first
, GLsizei count
)
4131 struct gl_buffer_object
* const bufObj
= ctx
->Shared
->NullBufferObj
;
4133 for (int i
= 0; i
< count
; i
++)
4134 set_buffer_binding(ctx
, &ctx
->AtomicBufferBindings
[first
+ i
],
4135 bufObj
, -1, -1, GL_TRUE
, 0);
4139 bind_atomic_buffers(struct gl_context
*ctx
,
4142 const GLuint
*buffers
,
4144 const GLintptr
*offsets
,
4145 const GLsizeiptr
*sizes
,
4148 if (!error_check_bind_atomic_buffers(ctx
, first
, count
, caller
))
4151 /* Assume that at least one binding will be changed */
4152 FLUSH_VERTICES(ctx
, 0);
4153 ctx
->NewDriverState
|= ctx
->DriverFlags
.NewAtomicBuffer
;
4156 /* The ARB_multi_bind spec says:
4158 * "If <buffers> is NULL, all bindings from <first> through
4159 * <first>+<count>-1 are reset to their unbound (zero) state.
4160 * In this case, the offsets and sizes associated with the
4161 * binding points are set to default values, ignoring
4162 * <offsets> and <sizes>."
4164 unbind_atomic_buffers(ctx
, first
, count
);
4168 /* Note that the error semantics for multi-bind commands differ from
4169 * those of other GL commands.
4171 * The Issues section in the ARB_multi_bind spec says:
4173 * "(11) Typically, OpenGL specifies that if an error is generated by a
4174 * command, that command has no effect. This is somewhat
4175 * unfortunate for multi-bind commands, because it would require a
4176 * first pass to scan the entire list of bound objects for errors
4177 * and then a second pass to actually perform the bindings.
4178 * Should we have different error semantics?
4180 * RESOLVED: Yes. In this specification, when the parameters for
4181 * one of the <count> binding points are invalid, that binding point
4182 * is not updated and an error will be generated. However, other
4183 * binding points in the same command will be updated if their
4184 * parameters are valid and no other error occurs."
4187 _mesa_HashLockMutex(ctx
->Shared
->BufferObjects
);
4189 for (int i
= 0; i
< count
; i
++) {
4190 struct gl_buffer_binding
*binding
=
4191 &ctx
->AtomicBufferBindings
[first
+ i
];
4192 GLintptr offset
= 0;
4193 GLsizeiptr size
= 0;
4196 if (!bind_buffers_check_offset_and_size(ctx
, i
, offsets
, sizes
))
4199 /* The ARB_multi_bind spec says:
4201 * "An INVALID_VALUE error is generated by BindBuffersRange if any
4202 * pair of values in <offsets> and <sizes> does not respectively
4203 * satisfy the constraints described for those parameters for the
4204 * specified target, as described in section 6.7.1 (per binding)."
4206 * Section 6.7.1 refers to table 6.5, which says:
4208 * "┌───────────────────────────────────────────────────────────────┐
4209 * │ Atomic counter array bindings (see sec. 7.7.2) │
4210 * ├───────────────────────┬───────────────────────────────────────┤
4212 * │ offset restriction │ multiple of 4 │
4214 * │ size restriction │ none │
4215 * └───────────────────────┴───────────────────────────────────────┘"
4217 if (offsets
[i
] & (ATOMIC_COUNTER_SIZE
- 1)) {
4218 _mesa_error(ctx
, GL_INVALID_VALUE
,
4219 "glBindBuffersRange(offsets[%u]=%" PRId64
4220 " is misaligned; it must be a multiple of %d when "
4221 "target=GL_ATOMIC_COUNTER_BUFFER)",
4222 i
, (int64_t) offsets
[i
], ATOMIC_COUNTER_SIZE
);
4226 offset
= offsets
[i
];
4230 set_buffer_multi_binding(ctx
, buffers
, i
, caller
,
4231 binding
, offset
, size
, range
,
4232 USAGE_ATOMIC_COUNTER_BUFFER
);
4235 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
4238 static ALWAYS_INLINE
void
4239 bind_buffer_range(GLenum target
, GLuint index
, GLuint buffer
, GLintptr offset
,
4240 GLsizeiptr size
, bool no_error
)
4242 GET_CURRENT_CONTEXT(ctx
);
4243 struct gl_buffer_object
*bufObj
;
4245 if (MESA_VERBOSE
& VERBOSE_API
) {
4246 _mesa_debug(ctx
, "glBindBufferRange(%s, %u, %u, %lu, %lu)\n",
4247 _mesa_enum_to_string(target
), index
, buffer
,
4248 (unsigned long) offset
, (unsigned long) size
);
4252 bufObj
= ctx
->Shared
->NullBufferObj
;
4254 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
4255 if (!_mesa_handle_bind_buffer_gen(ctx
, buffer
,
4256 &bufObj
, "glBindBufferRange"))
4259 if (!no_error
&& !bufObj
) {
4260 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4261 "glBindBufferRange(invalid buffer=%u)", buffer
);
4268 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4269 _mesa_bind_buffer_range_xfb(ctx
, ctx
->TransformFeedback
.CurrentObject
,
4270 index
, bufObj
, offset
, size
);
4272 case GL_UNIFORM_BUFFER
:
4273 bind_buffer_range_uniform_buffer(ctx
, index
, bufObj
, offset
, size
);
4275 case GL_SHADER_STORAGE_BUFFER
:
4276 bind_buffer_range_shader_storage_buffer(ctx
, index
, bufObj
, offset
,
4279 case GL_ATOMIC_COUNTER_BUFFER
:
4280 bind_buffer_range_atomic_buffer(ctx
, index
, bufObj
, offset
, size
);
4283 unreachable("invalid BindBufferRange target with KHR_no_error");
4288 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferRange(size=%d)",
4295 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4296 if (!_mesa_validate_buffer_range_xfb(ctx
,
4297 ctx
->TransformFeedback
.CurrentObject
,
4298 index
, bufObj
, offset
, size
,
4302 _mesa_bind_buffer_range_xfb(ctx
, ctx
->TransformFeedback
.CurrentObject
,
4303 index
, bufObj
, offset
, size
);
4305 case GL_UNIFORM_BUFFER
:
4306 bind_buffer_range_uniform_buffer_err(ctx
, index
, bufObj
, offset
,
4309 case GL_SHADER_STORAGE_BUFFER
:
4310 bind_buffer_range_shader_storage_buffer_err(ctx
, index
, bufObj
,
4313 case GL_ATOMIC_COUNTER_BUFFER
:
4314 bind_buffer_range_atomic_buffer_err(ctx
, index
, bufObj
,
4318 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBufferRange(target)");
4325 _mesa_BindBufferRange_no_error(GLenum target
, GLuint index
, GLuint buffer
,
4326 GLintptr offset
, GLsizeiptr size
)
4328 bind_buffer_range(target
, index
, buffer
, offset
, size
, true);
4332 _mesa_BindBufferRange(GLenum target
, GLuint index
,
4333 GLuint buffer
, GLintptr offset
, GLsizeiptr size
)
4335 bind_buffer_range(target
, index
, buffer
, offset
, size
, false);
4339 _mesa_BindBufferBase(GLenum target
, GLuint index
, GLuint buffer
)
4341 GET_CURRENT_CONTEXT(ctx
);
4342 struct gl_buffer_object
*bufObj
;
4344 if (MESA_VERBOSE
& VERBOSE_API
) {
4345 _mesa_debug(ctx
, "glBindBufferBase(%s, %u, %u)\n",
4346 _mesa_enum_to_string(target
), index
, buffer
);
4350 bufObj
= ctx
->Shared
->NullBufferObj
;
4352 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
4353 if (!_mesa_handle_bind_buffer_gen(ctx
, buffer
,
4354 &bufObj
, "glBindBufferBase"))
4358 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4359 "glBindBufferBase(invalid buffer=%u)", buffer
);
4364 /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with
4365 * regards to BindBufferBase. It says (GL 3.1 core spec, page 63):
4367 * "BindBufferBase is equivalent to calling BindBufferRange with offset
4368 * zero and size equal to the size of buffer."
4370 * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230):
4372 * "If the parameter (starting offset or size) was not specified when the
4373 * buffer object was bound, zero is returned."
4375 * What happens if the size of the buffer changes? Does the size of the
4376 * buffer at the moment glBindBufferBase was called still play a role, like
4377 * the first quote would imply, or is the size meaningless in the
4378 * glBindBufferBase case like the second quote would suggest? The GL 4.1
4379 * core spec page 45 says:
4381 * "It is equivalent to calling BindBufferRange with offset zero, while
4382 * size is determined by the size of the bound buffer at the time the
4385 * My interpretation is that the GL 4.1 spec was a clarification of the
4386 * behavior, not a change. In particular, this choice will only make
4387 * rendering work in cases where it would have had undefined results.
4391 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4392 _mesa_bind_buffer_base_transform_feedback(ctx
,
4393 ctx
->TransformFeedback
.CurrentObject
,
4394 index
, bufObj
, false);
4396 case GL_UNIFORM_BUFFER
:
4397 bind_buffer_base_uniform_buffer(ctx
, index
, bufObj
);
4399 case GL_SHADER_STORAGE_BUFFER
:
4400 bind_buffer_base_shader_storage_buffer(ctx
, index
, bufObj
);
4402 case GL_ATOMIC_COUNTER_BUFFER
:
4403 bind_buffer_base_atomic_buffer(ctx
, index
, bufObj
);
4406 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBufferBase(target)");
4412 _mesa_BindBuffersRange(GLenum target
, GLuint first
, GLsizei count
,
4413 const GLuint
*buffers
,
4414 const GLintptr
*offsets
, const GLsizeiptr
*sizes
)
4416 GET_CURRENT_CONTEXT(ctx
);
4418 if (MESA_VERBOSE
& VERBOSE_API
) {
4419 _mesa_debug(ctx
, "glBindBuffersRange(%s, %u, %d, %p, %p, %p)\n",
4420 _mesa_enum_to_string(target
), first
, count
,
4421 buffers
, offsets
, sizes
);
4425 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4426 bind_xfb_buffers(ctx
, first
, count
, buffers
, true, offsets
, sizes
,
4427 "glBindBuffersRange");
4429 case GL_UNIFORM_BUFFER
:
4430 bind_uniform_buffers(ctx
, first
, count
, buffers
, true, offsets
, sizes
,
4431 "glBindBuffersRange");
4433 case GL_SHADER_STORAGE_BUFFER
:
4434 bind_shader_storage_buffers(ctx
, first
, count
, buffers
, true, offsets
, sizes
,
4435 "glBindBuffersRange");
4437 case GL_ATOMIC_COUNTER_BUFFER
:
4438 bind_atomic_buffers(ctx
, first
, count
, buffers
, true, offsets
, sizes
,
4439 "glBindBuffersRange");
4442 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBuffersRange(target=%s)",
4443 _mesa_enum_to_string(target
));
4449 _mesa_BindBuffersBase(GLenum target
, GLuint first
, GLsizei count
,
4450 const GLuint
*buffers
)
4452 GET_CURRENT_CONTEXT(ctx
);
4454 if (MESA_VERBOSE
& VERBOSE_API
) {
4455 _mesa_debug(ctx
, "glBindBuffersBase(%s, %u, %d, %p)\n",
4456 _mesa_enum_to_string(target
), first
, count
, buffers
);
4460 case GL_TRANSFORM_FEEDBACK_BUFFER
:
4461 bind_xfb_buffers(ctx
, first
, count
, buffers
, false, NULL
, NULL
,
4462 "glBindBuffersBase");
4464 case GL_UNIFORM_BUFFER
:
4465 bind_uniform_buffers(ctx
, first
, count
, buffers
, false, NULL
, NULL
,
4466 "glBindBuffersBase");
4468 case GL_SHADER_STORAGE_BUFFER
:
4469 bind_shader_storage_buffers(ctx
, first
, count
, buffers
, false, NULL
, NULL
,
4470 "glBindBuffersBase");
4472 case GL_ATOMIC_COUNTER_BUFFER
:
4473 bind_atomic_buffers(ctx
, first
, count
, buffers
, false, NULL
, NULL
,
4474 "glBindBuffersBase");
4477 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBuffersBase(target=%s)",
4478 _mesa_enum_to_string(target
));
4483 static ALWAYS_INLINE
void
4484 invalidate_buffer_subdata(struct gl_context
*ctx
,
4485 struct gl_buffer_object
*bufObj
, GLintptr offset
,
4488 if (ctx
->Driver
.InvalidateBufferSubData
)
4489 ctx
->Driver
.InvalidateBufferSubData(ctx
, bufObj
, offset
, length
);
4493 _mesa_InvalidateBufferSubData_no_error(GLuint buffer
, GLintptr offset
,
4496 GET_CURRENT_CONTEXT(ctx
);
4498 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
4499 invalidate_buffer_subdata(ctx
, bufObj
, offset
, length
);
4503 _mesa_InvalidateBufferSubData(GLuint buffer
, GLintptr offset
,
4506 GET_CURRENT_CONTEXT(ctx
);
4507 struct gl_buffer_object
*bufObj
;
4508 const GLintptr end
= offset
+ length
;
4510 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
4511 * Profile) spec says:
4513 * "An INVALID_VALUE error is generated if buffer is zero or is not the
4514 * name of an existing buffer object."
4516 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
4517 if (!bufObj
|| bufObj
== &DummyBufferObject
) {
4518 _mesa_error(ctx
, GL_INVALID_VALUE
,
4519 "glInvalidateBufferSubData(name = %u) invalid object",
4524 /* The GL_ARB_invalidate_subdata spec says:
4526 * "An INVALID_VALUE error is generated if <offset> or <length> is
4527 * negative, or if <offset> + <length> is greater than the value of
4530 if (offset
< 0 || length
< 0 || end
> bufObj
->Size
) {
4531 _mesa_error(ctx
, GL_INVALID_VALUE
,
4532 "glInvalidateBufferSubData(invalid offset or length)");
4536 /* The OpenGL 4.4 (Core Profile) spec says:
4538 * "An INVALID_OPERATION error is generated if buffer is currently
4539 * mapped by MapBuffer or if the invalidate range intersects the range
4540 * currently mapped by MapBufferRange, unless it was mapped
4541 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
4543 if (!(bufObj
->Mappings
[MAP_USER
].AccessFlags
& GL_MAP_PERSISTENT_BIT
) &&
4544 bufferobj_range_mapped(bufObj
, offset
, length
)) {
4545 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4546 "glInvalidateBufferSubData(intersection with mapped "
4551 invalidate_buffer_subdata(ctx
, bufObj
, offset
, length
);
4555 _mesa_InvalidateBufferData_no_error(GLuint buffer
)
4557 GET_CURRENT_CONTEXT(ctx
);
4559 struct gl_buffer_object
*bufObj
=_mesa_lookup_bufferobj(ctx
, buffer
);
4560 invalidate_buffer_subdata(ctx
, bufObj
, 0, bufObj
->Size
);
4564 _mesa_InvalidateBufferData(GLuint buffer
)
4566 GET_CURRENT_CONTEXT(ctx
);
4567 struct gl_buffer_object
*bufObj
;
4569 /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
4570 * Profile) spec says:
4572 * "An INVALID_VALUE error is generated if buffer is zero or is not the
4573 * name of an existing buffer object."
4575 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
4576 if (!bufObj
|| bufObj
== &DummyBufferObject
) {
4577 _mesa_error(ctx
, GL_INVALID_VALUE
,
4578 "glInvalidateBufferData(name = %u) invalid object",
4583 /* The OpenGL 4.4 (Core Profile) spec says:
4585 * "An INVALID_OPERATION error is generated if buffer is currently
4586 * mapped by MapBuffer or if the invalidate range intersects the range
4587 * currently mapped by MapBufferRange, unless it was mapped
4588 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
4590 if (_mesa_check_disallowed_mapping(bufObj
)) {
4591 _mesa_error(ctx
, GL_INVALID_OPERATION
,
4592 "glInvalidateBufferData(intersection with mapped "
4597 invalidate_buffer_subdata(ctx
, bufObj
, 0, bufObj
->Size
);
4601 buffer_page_commitment(struct gl_context
*ctx
,
4602 struct gl_buffer_object
*bufferObj
,
4603 GLintptr offset
, GLsizeiptr size
,
4604 GLboolean commit
, const char *func
)
4606 if (!(bufferObj
->StorageFlags
& GL_SPARSE_STORAGE_BIT_ARB
)) {
4607 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(not a sparse buffer object)",
4612 if (size
< 0 || size
> bufferObj
->Size
||
4613 offset
< 0 || offset
> bufferObj
->Size
- size
) {
4614 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(out of bounds)",
4619 /* The GL_ARB_sparse_buffer extension specification says:
4621 * "INVALID_VALUE is generated by BufferPageCommitmentARB if <offset> is
4622 * not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB, or if <size>
4623 * is not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB and does
4624 * not extend to the end of the buffer's data store."
4626 if (offset
% ctx
->Const
.SparseBufferPageSize
!= 0) {
4627 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(offset not aligned to page size)",
4632 if (size
% ctx
->Const
.SparseBufferPageSize
!= 0 &&
4633 offset
+ size
!= bufferObj
->Size
) {
4634 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(size not aligned to page size)",
4639 ctx
->Driver
.BufferPageCommitment(ctx
, bufferObj
, offset
, size
, commit
);
4643 _mesa_BufferPageCommitmentARB(GLenum target
, GLintptr offset
, GLsizeiptr size
,
4646 GET_CURRENT_CONTEXT(ctx
);
4647 struct gl_buffer_object
*bufferObj
;
4649 bufferObj
= get_buffer(ctx
, "glBufferPageCommitmentARB", target
,
4654 buffer_page_commitment(ctx
, bufferObj
, offset
, size
, commit
,
4655 "glBufferPageCommitmentARB");
4659 _mesa_NamedBufferPageCommitmentARB(GLuint buffer
, GLintptr offset
,
4660 GLsizeiptr size
, GLboolean commit
)
4662 GET_CURRENT_CONTEXT(ctx
);
4663 struct gl_buffer_object
*bufferObj
;
4665 bufferObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
4666 if (!bufferObj
|| bufferObj
== &DummyBufferObject
) {
4667 /* Note: the extension spec is not clear about the excpected error value. */
4668 _mesa_error(ctx
, GL_INVALID_VALUE
,
4669 "glNamedBufferPageCommitmentARB(name = %u) invalid object",
4674 buffer_page_commitment(ctx
, bufferObj
, offset
, size
, commit
,
4675 "glNamedBufferPageCommitmentARB");