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
40 #include "bufferobj.h"
45 #include "glformats.h"
47 #include "transformfeedback.h"
53 /*#define BOUNDS_CHECK*/
57 * Used as a placeholder for buffer objects between glGenBuffers() and
58 * glBindBuffer() so that glIsBuffer() can work correctly.
60 static struct gl_buffer_object DummyBufferObject
;
64 * Return pointer to address of a buffer object target.
65 * \param ctx the GL context
66 * \param target the buffer object target to be retrieved.
67 * \return pointer to pointer to the buffer object bound to \c target in the
68 * specified context or \c NULL if \c target is invalid.
70 static inline struct gl_buffer_object
**
71 get_buffer_target(struct gl_context
*ctx
, GLenum target
)
73 /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0.
75 if (!_mesa_is_desktop_gl(ctx
) && !_mesa_is_gles3(ctx
)
76 && target
!= GL_ARRAY_BUFFER
&& target
!= GL_ELEMENT_ARRAY_BUFFER
)
80 case GL_ARRAY_BUFFER_ARB
:
81 return &ctx
->Array
.ArrayBufferObj
;
82 case GL_ELEMENT_ARRAY_BUFFER_ARB
:
83 return &ctx
->Array
.VAO
->IndexBufferObj
;
84 case GL_PIXEL_PACK_BUFFER_EXT
:
85 return &ctx
->Pack
.BufferObj
;
86 case GL_PIXEL_UNPACK_BUFFER_EXT
:
87 return &ctx
->Unpack
.BufferObj
;
88 case GL_COPY_READ_BUFFER
:
89 return &ctx
->CopyReadBuffer
;
90 case GL_COPY_WRITE_BUFFER
:
91 return &ctx
->CopyWriteBuffer
;
92 case GL_DRAW_INDIRECT_BUFFER
:
93 if (ctx
->API
== API_OPENGL_CORE
&&
94 ctx
->Extensions
.ARB_draw_indirect
) {
95 return &ctx
->DrawIndirectBuffer
;
98 case GL_TRANSFORM_FEEDBACK_BUFFER
:
99 if (ctx
->Extensions
.EXT_transform_feedback
) {
100 return &ctx
->TransformFeedback
.CurrentBuffer
;
103 case GL_TEXTURE_BUFFER
:
104 if (ctx
->API
== API_OPENGL_CORE
&&
105 ctx
->Extensions
.ARB_texture_buffer_object
) {
106 return &ctx
->Texture
.BufferObject
;
109 case GL_UNIFORM_BUFFER
:
110 if (ctx
->Extensions
.ARB_uniform_buffer_object
) {
111 return &ctx
->UniformBuffer
;
114 case GL_ATOMIC_COUNTER_BUFFER
:
115 if (ctx
->Extensions
.ARB_shader_atomic_counters
) {
116 return &ctx
->AtomicBuffer
;
127 * Get the buffer object bound to the specified target in a GL context.
128 * \param ctx the GL context
129 * \param target the buffer object target to be retrieved.
130 * \param error the GL error to record if target is illegal.
131 * \return pointer to the buffer object bound to \c target in the
132 * specified context or \c NULL if \c target is invalid.
134 static inline struct gl_buffer_object
*
135 get_buffer(struct gl_context
*ctx
, const char *func
, GLenum target
,
138 struct gl_buffer_object
**bufObj
= get_buffer_target(ctx
, target
);
141 _mesa_error(ctx
, GL_INVALID_ENUM
, "%s(target)", func
);
145 if (!_mesa_is_bufferobj(*bufObj
)) {
146 _mesa_error(ctx
, error
, "%s(no buffer bound)", func
);
155 * Convert a GLbitfield describing the mapped buffer access flags
156 * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
159 simplified_access_mode(struct gl_context
*ctx
, GLbitfield access
)
161 const GLbitfield rwFlags
= GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
;
162 if ((access
& rwFlags
) == rwFlags
)
163 return GL_READ_WRITE
;
164 if ((access
& GL_MAP_READ_BIT
) == GL_MAP_READ_BIT
)
166 if ((access
& GL_MAP_WRITE_BIT
) == GL_MAP_WRITE_BIT
)
167 return GL_WRITE_ONLY
;
169 /* Otherwise, AccessFlags is zero (the default state).
171 * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says:
173 * Name Type Initial Value Legal Values
175 * BUFFER_ACCESS enum READ_WRITE READ_ONLY, WRITE_ONLY
178 * However, table 6.8 in the GL_OES_mapbuffer extension says:
180 * Get Value Type Get Command Value Description
181 * --------- ---- ----------- ----- -----------
182 * BUFFER_ACCESS_OES Z1 GetBufferParameteriv WRITE_ONLY_OES buffer map flag
184 * The difference is because GL_OES_mapbuffer only supports mapping buffers
189 return _mesa_is_gles(ctx
) ? GL_WRITE_ONLY
: GL_READ_WRITE
;
194 * Test if the buffer is mapped, and if so, if the mapped range overlaps the
196 * The regions do not overlap if and only if the end of the given
197 * region is before the mapped region or the start of the given region
198 * is after the mapped region.
200 * \param obj Buffer object target on which to operate.
201 * \param offset Offset of the first byte of the subdata range.
202 * \param size Size, in bytes, of the subdata range.
203 * \return true if ranges overlap, false otherwise
207 bufferobj_range_mapped(const struct gl_buffer_object
*obj
,
208 GLintptr offset
, GLsizeiptr size
)
210 if (_mesa_bufferobj_mapped(obj
, MAP_USER
)) {
211 const GLintptr end
= offset
+ size
;
212 const GLintptr mapEnd
= obj
->Mappings
[MAP_USER
].Offset
+
213 obj
->Mappings
[MAP_USER
].Length
;
215 if (!(end
<= obj
->Mappings
[MAP_USER
].Offset
|| offset
>= mapEnd
)) {
224 * Tests the subdata range parameters and sets the GL error code for
225 * \c glBufferSubDataARB, \c glGetBufferSubDataARB and
226 * \c glClearBufferSubData.
228 * \param ctx GL context.
229 * \param target Buffer object target on which to operate.
230 * \param offset Offset of the first byte of the subdata range.
231 * \param size Size, in bytes, of the subdata range.
232 * \param mappedRange If true, checks if an overlapping range is mapped.
233 * If false, checks if buffer is mapped.
234 * \param errorNoBuffer Error code if no buffer is bound to target.
235 * \param caller Name of calling function for recording errors.
236 * \return A pointer to the buffer object bound to \c target in the
237 * specified context or \c NULL if any of the parameter or state
238 * conditions are invalid.
240 * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData
242 static struct gl_buffer_object
*
243 buffer_object_subdata_range_good(struct gl_context
* ctx
, GLenum target
,
244 GLintptrARB offset
, GLsizeiptrARB size
,
245 bool mappedRange
, GLenum errorNoBuffer
,
248 struct gl_buffer_object
*bufObj
;
251 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(size < 0)", caller
);
256 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(offset < 0)", caller
);
260 bufObj
= get_buffer(ctx
, caller
, target
, errorNoBuffer
);
264 if (offset
+ size
> bufObj
->Size
) {
265 _mesa_error(ctx
, GL_INVALID_VALUE
,
266 "%s(offset %lu + size %lu > buffer size %lu)", caller
,
267 (unsigned long) offset
,
268 (unsigned long) size
,
269 (unsigned long) bufObj
->Size
);
273 if (bufObj
->Mappings
[MAP_USER
].AccessFlags
& GL_MAP_PERSISTENT_BIT
)
277 if (bufferobj_range_mapped(bufObj
, offset
, size
)) {
278 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s", caller
);
283 if (_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
284 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s", caller
);
294 * Test the format and type parameters and set the GL error code for
295 * \c glClearBufferData and \c glClearBufferSubData.
297 * \param ctx GL context.
298 * \param internalformat Format to which the data is to be converted.
299 * \param format Format of the supplied data.
300 * \param type Type of the supplied data.
301 * \param caller Name of calling function for recording errors.
302 * \return If internalformat, format and type are legal the mesa_format
303 * corresponding to internalformat, otherwise MESA_FORMAT_NONE.
305 * \sa glClearBufferData and glClearBufferSubData
308 validate_clear_buffer_format(struct gl_context
*ctx
,
309 GLenum internalformat
,
310 GLenum format
, GLenum type
,
313 mesa_format mesaFormat
;
314 GLenum errorFormatType
;
316 mesaFormat
= _mesa_validate_texbuffer_format(ctx
, internalformat
);
317 if (mesaFormat
== MESA_FORMAT_NONE
) {
318 _mesa_error(ctx
, GL_INVALID_ENUM
,
319 "%s(invalid internalformat)", caller
);
320 return MESA_FORMAT_NONE
;
323 /* NOTE: not mentioned in ARB_clear_buffer_object but according to
324 * EXT_texture_integer there is no conversion between integer and
325 * non-integer formats
327 if (_mesa_is_enum_format_signed_int(format
) !=
328 _mesa_is_format_integer_color(mesaFormat
)) {
329 _mesa_error(ctx
, GL_INVALID_OPERATION
,
330 "%s(integer vs non-integer)", caller
);
331 return MESA_FORMAT_NONE
;
334 if (!_mesa_is_color_format(format
)) {
335 _mesa_error(ctx
, GL_INVALID_ENUM
,
336 "%s(format is not a color format)", caller
);
337 return MESA_FORMAT_NONE
;
340 errorFormatType
= _mesa_error_check_format_and_type(ctx
, format
, type
);
341 if (errorFormatType
!= GL_NO_ERROR
) {
342 _mesa_error(ctx
, GL_INVALID_ENUM
,
343 "%s(invalid format or type)", caller
);
344 return MESA_FORMAT_NONE
;
352 * Convert user-specified clear value to the specified internal format.
354 * \param ctx GL context.
355 * \param internalformat Format to which the data is converted.
356 * \param clearValue Points to the converted clear value.
357 * \param format Format of the supplied data.
358 * \param type Type of the supplied data.
359 * \param data Data which is to be converted to internalformat.
360 * \param caller Name of calling function for recording errors.
361 * \return true if data could be converted, false otherwise.
363 * \sa glClearBufferData, glClearBufferSubData
366 convert_clear_buffer_data(struct gl_context
*ctx
,
367 mesa_format internalformat
,
368 GLubyte
*clearValue
, GLenum format
, GLenum type
,
369 const GLvoid
*data
, const char *caller
)
371 GLenum internalformatBase
= _mesa_get_format_base_format(internalformat
);
373 if (_mesa_texstore(ctx
, 1, internalformatBase
, internalformat
,
374 0, &clearValue
, 1, 1, 1,
375 format
, type
, data
, &ctx
->Unpack
)) {
379 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s", caller
);
386 * Allocate and initialize a new buffer object.
388 * Default callback for the \c dd_function_table::NewBufferObject() hook.
390 static struct gl_buffer_object
*
391 _mesa_new_buffer_object( struct gl_context
*ctx
, GLuint name
, GLenum target
)
393 struct gl_buffer_object
*obj
;
397 obj
= MALLOC_STRUCT(gl_buffer_object
);
398 _mesa_initialize_buffer_object(ctx
, obj
, name
, target
);
404 * Delete a buffer object.
406 * Default callback for the \c dd_function_table::DeleteBuffer() hook.
409 _mesa_delete_buffer_object(struct gl_context
*ctx
,
410 struct gl_buffer_object
*bufObj
)
414 _mesa_align_free(bufObj
->Data
);
416 /* assign strange values here to help w/ debugging */
417 bufObj
->RefCount
= -1000;
420 mtx_destroy(&bufObj
->Mutex
);
428 * Set ptr to bufObj w/ reference counting.
429 * This is normally only called from the _mesa_reference_buffer_object() macro
430 * when there's a real pointer change.
433 _mesa_reference_buffer_object_(struct gl_context
*ctx
,
434 struct gl_buffer_object
**ptr
,
435 struct gl_buffer_object
*bufObj
)
438 /* Unreference the old buffer */
439 GLboolean deleteFlag
= GL_FALSE
;
440 struct gl_buffer_object
*oldObj
= *ptr
;
442 mtx_lock(&oldObj
->Mutex
);
443 ASSERT(oldObj
->RefCount
> 0);
446 printf("BufferObj %p %d DECR to %d\n",
447 (void *) oldObj
, oldObj
->Name
, oldObj
->RefCount
);
449 deleteFlag
= (oldObj
->RefCount
== 0);
450 mtx_unlock(&oldObj
->Mutex
);
454 /* some sanity checking: don't delete a buffer still in use */
456 /* unfortunately, these tests are invalid during context tear-down */
457 ASSERT(ctx
->Array
.ArrayBufferObj
!= bufObj
);
458 ASSERT(ctx
->Array
.VAO
->IndexBufferObj
!= bufObj
);
459 ASSERT(ctx
->Array
.VAO
->Vertex
.BufferObj
!= bufObj
);
462 ASSERT(ctx
->Driver
.DeleteBuffer
);
463 ctx
->Driver
.DeleteBuffer(ctx
, oldObj
);
471 /* reference new buffer */
472 mtx_lock(&bufObj
->Mutex
);
473 if (bufObj
->RefCount
== 0) {
474 /* this buffer's being deleted (look just above) */
475 /* Not sure this can every really happen. Warn if it does. */
476 _mesa_problem(NULL
, "referencing deleted buffer object");
482 printf("BufferObj %p %d INCR to %d\n",
483 (void *) bufObj
, bufObj
->Name
, bufObj
->RefCount
);
487 mtx_unlock(&bufObj
->Mutex
);
493 * Initialize a buffer object to default values.
496 _mesa_initialize_buffer_object( struct gl_context
*ctx
,
497 struct gl_buffer_object
*obj
,
498 GLuint name
, GLenum target
)
502 memset(obj
, 0, sizeof(struct gl_buffer_object
));
503 mtx_init(&obj
->Mutex
, mtx_plain
);
506 obj
->Usage
= GL_STATIC_DRAW_ARB
;
512 * Callback called from _mesa_HashWalk()
515 count_buffer_size(GLuint key
, void *data
, void *userData
)
517 const struct gl_buffer_object
*bufObj
=
518 (const struct gl_buffer_object
*) data
;
519 GLuint
*total
= (GLuint
*) userData
;
521 *total
= *total
+ bufObj
->Size
;
526 * Compute total size (in bytes) of all buffer objects for the given context.
527 * For debugging purposes.
530 _mesa_total_buffer_object_memory(struct gl_context
*ctx
)
534 _mesa_HashWalk(ctx
->Shared
->BufferObjects
, count_buffer_size
, &total
);
541 * Allocate space for and store data in a buffer object. Any data that was
542 * previously stored in the buffer object is lost. If \c data is \c NULL,
543 * memory will be allocated, but no copy will occur.
545 * This is the default callback for \c dd_function_table::BufferData()
546 * Note that all GL error checking will have been done already.
548 * \param ctx GL context.
549 * \param target Buffer object target on which to operate.
550 * \param size Size, in bytes, of the new data store.
551 * \param data Pointer to the data to store in the buffer object. This
552 * pointer may be \c NULL.
553 * \param usage Hints about how the data will be used.
554 * \param bufObj Object to be used.
556 * \return GL_TRUE for success, GL_FALSE for failure
557 * \sa glBufferDataARB, dd_function_table::BufferData.
560 _mesa_buffer_data( struct gl_context
*ctx
, GLenum target
, GLsizeiptrARB size
,
561 const GLvoid
* data
, GLenum usage
, GLenum storageFlags
,
562 struct gl_buffer_object
* bufObj
)
568 _mesa_align_free( bufObj
->Data
);
570 new_data
= _mesa_align_malloc( size
, ctx
->Const
.MinMapBufferAlignment
);
572 bufObj
->Data
= (GLubyte
*) new_data
;
574 bufObj
->Usage
= usage
;
575 bufObj
->StorageFlags
= storageFlags
;
578 memcpy( bufObj
->Data
, data
, size
);
590 * Replace data in a subrange of buffer object. If the data range
591 * specified by \c size + \c offset extends beyond the end of the buffer or
592 * if \c data is \c NULL, no copy is performed.
594 * This is the default callback for \c dd_function_table::BufferSubData()
595 * Note that all GL error checking will have been done already.
597 * \param ctx GL context.
598 * \param offset Offset of the first byte to be modified.
599 * \param size Size, in bytes, of the data range.
600 * \param data Pointer to the data to store in the buffer object.
601 * \param bufObj Object to be used.
603 * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
606 _mesa_buffer_subdata( struct gl_context
*ctx
, GLintptrARB offset
,
607 GLsizeiptrARB size
, const GLvoid
* data
,
608 struct gl_buffer_object
* bufObj
)
612 /* this should have been caught in _mesa_BufferSubData() */
613 ASSERT(size
+ offset
<= bufObj
->Size
);
616 memcpy( (GLubyte
*) bufObj
->Data
+ offset
, data
, size
);
622 * Retrieve data from a subrange of buffer object. If the data range
623 * specified by \c size + \c offset extends beyond the end of the buffer or
624 * if \c data is \c NULL, no copy is performed.
626 * This is the default callback for \c dd_function_table::GetBufferSubData()
627 * Note that all GL error checking will have been done already.
629 * \param ctx GL context.
630 * \param target Buffer object target on which to operate.
631 * \param offset Offset of the first byte to be fetched.
632 * \param size Size, in bytes, of the data range.
633 * \param data Destination for data
634 * \param bufObj Object to be used.
636 * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
639 _mesa_buffer_get_subdata( struct gl_context
*ctx
, GLintptrARB offset
,
640 GLsizeiptrARB size
, GLvoid
* data
,
641 struct gl_buffer_object
* bufObj
)
645 if (bufObj
->Data
&& ((GLsizeiptrARB
) (size
+ offset
) <= bufObj
->Size
)) {
646 memcpy( data
, (GLubyte
*) bufObj
->Data
+ offset
, size
);
652 * Clear a subrange of the buffer object with copies of the supplied data.
653 * If data is NULL the buffer is filled with zeros.
655 * This is the default callback for \c dd_function_table::ClearBufferSubData()
656 * Note that all GL error checking will have been done already.
658 * \param ctx GL context.
659 * \param offset Offset of the first byte to be cleared.
660 * \param size Size, in bytes, of the to be cleared range.
661 * \param clearValue Source of the data.
662 * \param clearValueSize Size, in bytes, of the supplied data.
663 * \param bufObj Object to be cleared.
665 * \sa glClearBufferSubData, glClearBufferData and
666 * dd_function_table::ClearBufferSubData.
669 _mesa_buffer_clear_subdata(struct gl_context
*ctx
,
670 GLintptr offset
, GLsizeiptr size
,
671 const GLvoid
*clearValue
,
672 GLsizeiptr clearValueSize
,
673 struct gl_buffer_object
*bufObj
)
678 ASSERT(ctx
->Driver
.MapBufferRange
);
679 dest
= ctx
->Driver
.MapBufferRange(ctx
, offset
, size
,
681 GL_MAP_INVALIDATE_RANGE_BIT
,
682 bufObj
, MAP_INTERNAL
);
685 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glClearBuffer[Sub]Data");
689 if (clearValue
== NULL
) {
690 /* Clear with zeros, per the spec */
691 memset(dest
, 0, size
);
692 ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, MAP_INTERNAL
);
696 for (i
= 0; i
< size
/clearValueSize
; ++i
) {
697 memcpy(dest
, clearValue
, clearValueSize
);
698 dest
+= clearValueSize
;
701 ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, MAP_INTERNAL
);
706 * Default fallback for \c dd_function_table::MapBufferRange().
707 * Called via glMapBufferRange().
710 _mesa_buffer_map_range( struct gl_context
*ctx
, GLintptr offset
,
711 GLsizeiptr length
, GLbitfield access
,
712 struct gl_buffer_object
*bufObj
,
713 gl_map_buffer_index index
)
716 assert(!_mesa_bufferobj_mapped(bufObj
, index
));
717 /* Just return a direct pointer to the data */
718 bufObj
->Mappings
[index
].Pointer
= bufObj
->Data
+ offset
;
719 bufObj
->Mappings
[index
].Length
= length
;
720 bufObj
->Mappings
[index
].Offset
= offset
;
721 bufObj
->Mappings
[index
].AccessFlags
= access
;
722 return bufObj
->Mappings
[index
].Pointer
;
727 * Default fallback for \c dd_function_table::FlushMappedBufferRange().
728 * Called via glFlushMappedBufferRange().
731 _mesa_buffer_flush_mapped_range( struct gl_context
*ctx
,
732 GLintptr offset
, GLsizeiptr length
,
733 struct gl_buffer_object
*obj
,
734 gl_map_buffer_index index
)
745 * Default callback for \c dd_function_table::MapBuffer().
747 * The input parameters will have been already tested for errors.
749 * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
752 _mesa_buffer_unmap(struct gl_context
*ctx
, struct gl_buffer_object
*bufObj
,
753 gl_map_buffer_index index
)
756 /* XXX we might assert here that bufObj->Pointer is non-null */
757 bufObj
->Mappings
[index
].Pointer
= NULL
;
758 bufObj
->Mappings
[index
].Length
= 0;
759 bufObj
->Mappings
[index
].Offset
= 0;
760 bufObj
->Mappings
[index
].AccessFlags
= 0x0;
766 * Default fallback for \c dd_function_table::CopyBufferSubData().
767 * Called via glCopyBufferSubData().
770 _mesa_copy_buffer_subdata(struct gl_context
*ctx
,
771 struct gl_buffer_object
*src
,
772 struct gl_buffer_object
*dst
,
773 GLintptr readOffset
, GLintptr writeOffset
,
776 GLubyte
*srcPtr
, *dstPtr
;
779 srcPtr
= dstPtr
= ctx
->Driver
.MapBufferRange(ctx
, 0, src
->Size
,
781 GL_MAP_WRITE_BIT
, src
,
787 srcPtr
+= readOffset
;
788 dstPtr
+= writeOffset
;
790 srcPtr
= ctx
->Driver
.MapBufferRange(ctx
, readOffset
, size
,
791 GL_MAP_READ_BIT
, src
,
793 dstPtr
= ctx
->Driver
.MapBufferRange(ctx
, writeOffset
, size
,
795 GL_MAP_INVALIDATE_RANGE_BIT
), dst
,
799 /* Note: the src and dst regions will never overlap. Trying to do so
800 * would generate GL_INVALID_VALUE earlier.
802 if (srcPtr
&& dstPtr
)
803 memcpy(dstPtr
, srcPtr
, size
);
805 ctx
->Driver
.UnmapBuffer(ctx
, src
, MAP_INTERNAL
);
807 ctx
->Driver
.UnmapBuffer(ctx
, dst
, MAP_INTERNAL
);
813 * Initialize the state associated with buffer objects
816 _mesa_init_buffer_objects( struct gl_context
*ctx
)
820 memset(&DummyBufferObject
, 0, sizeof(DummyBufferObject
));
821 mtx_init(&DummyBufferObject
.Mutex
, mtx_plain
);
822 DummyBufferObject
.RefCount
= 1000*1000*1000; /* never delete */
824 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
,
825 ctx
->Shared
->NullBufferObj
);
827 _mesa_reference_buffer_object(ctx
, &ctx
->CopyReadBuffer
,
828 ctx
->Shared
->NullBufferObj
);
829 _mesa_reference_buffer_object(ctx
, &ctx
->CopyWriteBuffer
,
830 ctx
->Shared
->NullBufferObj
);
832 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
,
833 ctx
->Shared
->NullBufferObj
);
835 _mesa_reference_buffer_object(ctx
, &ctx
->DrawIndirectBuffer
,
836 ctx
->Shared
->NullBufferObj
);
838 for (i
= 0; i
< MAX_COMBINED_UNIFORM_BUFFERS
; i
++) {
839 _mesa_reference_buffer_object(ctx
,
840 &ctx
->UniformBufferBindings
[i
].BufferObject
,
841 ctx
->Shared
->NullBufferObj
);
842 ctx
->UniformBufferBindings
[i
].Offset
= -1;
843 ctx
->UniformBufferBindings
[i
].Size
= -1;
849 _mesa_free_buffer_objects( struct gl_context
*ctx
)
853 _mesa_reference_buffer_object(ctx
, &ctx
->Array
.ArrayBufferObj
, NULL
);
855 _mesa_reference_buffer_object(ctx
, &ctx
->CopyReadBuffer
, NULL
);
856 _mesa_reference_buffer_object(ctx
, &ctx
->CopyWriteBuffer
, NULL
);
858 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
, NULL
);
860 _mesa_reference_buffer_object(ctx
, &ctx
->DrawIndirectBuffer
, NULL
);
862 for (i
= 0; i
< MAX_COMBINED_UNIFORM_BUFFERS
; i
++) {
863 _mesa_reference_buffer_object(ctx
,
864 &ctx
->UniformBufferBindings
[i
].BufferObject
,
870 _mesa_handle_bind_buffer_gen(struct gl_context
*ctx
,
873 struct gl_buffer_object
**buf_handle
,
876 struct gl_buffer_object
*buf
= *buf_handle
;
878 if (!buf
&& ctx
->API
== API_OPENGL_CORE
) {
879 _mesa_error(ctx
, GL_INVALID_OPERATION
, "%s(non-gen name)", caller
);
883 if (!buf
|| buf
== &DummyBufferObject
) {
884 /* If this is a new buffer object id, or one which was generated but
885 * never used before, allocate a buffer object now.
887 ASSERT(ctx
->Driver
.NewBufferObject
);
888 buf
= ctx
->Driver
.NewBufferObject(ctx
, buffer
, target
);
890 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s", caller
);
893 _mesa_HashInsert(ctx
->Shared
->BufferObjects
, buffer
, buf
);
901 * Bind the specified target to buffer for the specified context.
902 * Called by glBindBuffer() and other functions.
905 bind_buffer_object(struct gl_context
*ctx
, GLenum target
, GLuint buffer
)
907 struct gl_buffer_object
*oldBufObj
;
908 struct gl_buffer_object
*newBufObj
= NULL
;
909 struct gl_buffer_object
**bindTarget
= NULL
;
911 bindTarget
= get_buffer_target(ctx
, target
);
913 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBufferARB(target 0x%x)", target
);
917 /* Get pointer to old buffer object (to be unbound) */
918 oldBufObj
= *bindTarget
;
919 if (oldBufObj
&& oldBufObj
->Name
== buffer
&& !oldBufObj
->DeletePending
)
920 return; /* rebinding the same buffer object- no change */
923 * Get pointer to new buffer object (newBufObj)
926 /* The spec says there's not a buffer object named 0, but we use
927 * one internally because it simplifies things.
929 newBufObj
= ctx
->Shared
->NullBufferObj
;
932 /* non-default buffer object */
933 newBufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
934 if (!_mesa_handle_bind_buffer_gen(ctx
, target
, buffer
,
935 &newBufObj
, "glBindBuffer"))
939 /* bind new buffer */
940 _mesa_reference_buffer_object(ctx
, bindTarget
, newBufObj
);
945 * Update the default buffer objects in the given context to reference those
946 * specified in the shared state and release those referencing the old
950 _mesa_update_default_objects_buffer_objects(struct gl_context
*ctx
)
952 /* Bind the NullBufferObj to remove references to those
953 * in the shared context hash table.
955 bind_buffer_object( ctx
, GL_ARRAY_BUFFER_ARB
, 0);
956 bind_buffer_object( ctx
, GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
957 bind_buffer_object( ctx
, GL_PIXEL_PACK_BUFFER_ARB
, 0);
958 bind_buffer_object( ctx
, GL_PIXEL_UNPACK_BUFFER_ARB
, 0);
964 * Return the gl_buffer_object for the given ID.
965 * Always return NULL for ID 0.
967 struct gl_buffer_object
*
968 _mesa_lookup_bufferobj(struct gl_context
*ctx
, GLuint buffer
)
973 return (struct gl_buffer_object
*)
974 _mesa_HashLookup(ctx
->Shared
->BufferObjects
, buffer
);
978 struct gl_buffer_object
*
979 _mesa_lookup_bufferobj_locked(struct gl_context
*ctx
, GLuint buffer
)
981 return (struct gl_buffer_object
*)
982 _mesa_HashLookupLocked(ctx
->Shared
->BufferObjects
, buffer
);
987 _mesa_begin_bufferobj_lookups(struct gl_context
*ctx
)
989 _mesa_HashLockMutex(ctx
->Shared
->BufferObjects
);
994 _mesa_end_bufferobj_lookups(struct gl_context
*ctx
)
996 _mesa_HashUnlockMutex(ctx
->Shared
->BufferObjects
);
1001 * Look up a buffer object for a multi-bind function.
1003 * Unlike _mesa_lookup_bufferobj(), this function also takes care
1004 * of generating an error if the buffer ID is not zero or the name
1005 * of an existing buffer object.
1007 * If the buffer ID refers to an existing buffer object, a pointer
1008 * to the buffer object is returned. If the ID is zero, a pointer
1009 * to the shared NullBufferObj is returned. If the ID is not zero
1010 * and does not refer to a valid buffer object, this function
1013 * This function assumes that the caller has already locked the
1014 * hash table mutex by calling _mesa_begin_bufferobj_lookups().
1016 struct gl_buffer_object
*
1017 _mesa_multi_bind_lookup_bufferobj(struct gl_context
*ctx
,
1018 const GLuint
*buffers
,
1019 GLuint index
, const char *caller
)
1021 struct gl_buffer_object
*bufObj
;
1023 if (buffers
[index
] != 0) {
1024 bufObj
= _mesa_lookup_bufferobj_locked(ctx
, buffers
[index
]);
1026 /* The multi-bind functions don't create the buffer objects
1027 when they don't exist. */
1028 if (bufObj
== &DummyBufferObject
)
1031 bufObj
= ctx
->Shared
->NullBufferObj
;
1034 /* The ARB_multi_bind spec says:
1036 * "An INVALID_OPERATION error is generated if any value
1037 * in <buffers> is not zero or the name of an existing
1038 * buffer object (per binding)."
1040 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1041 "%s(buffers[%u]=%u is not zero or the name "
1042 "of an existing buffer object)",
1043 caller
, index
, buffers
[index
]);
1051 * If *ptr points to obj, set ptr = the Null/default buffer object.
1052 * This is a helper for buffer object deletion.
1053 * The GL spec says that deleting a buffer object causes it to get
1054 * unbound from all arrays in the current context.
1057 unbind(struct gl_context
*ctx
,
1058 struct gl_buffer_object
**ptr
,
1059 struct gl_buffer_object
*obj
)
1062 _mesa_reference_buffer_object(ctx
, ptr
, ctx
->Shared
->NullBufferObj
);
1068 * Plug default/fallback buffer object functions into the device
1072 _mesa_init_buffer_object_functions(struct dd_function_table
*driver
)
1074 /* GL_ARB_vertex/pixel_buffer_object */
1075 driver
->NewBufferObject
= _mesa_new_buffer_object
;
1076 driver
->DeleteBuffer
= _mesa_delete_buffer_object
;
1077 driver
->BufferData
= _mesa_buffer_data
;
1078 driver
->BufferSubData
= _mesa_buffer_subdata
;
1079 driver
->GetBufferSubData
= _mesa_buffer_get_subdata
;
1080 driver
->UnmapBuffer
= _mesa_buffer_unmap
;
1082 /* GL_ARB_clear_buffer_object */
1083 driver
->ClearBufferSubData
= _mesa_buffer_clear_subdata
;
1085 /* GL_ARB_map_buffer_range */
1086 driver
->MapBufferRange
= _mesa_buffer_map_range
;
1087 driver
->FlushMappedBufferRange
= _mesa_buffer_flush_mapped_range
;
1089 /* GL_ARB_copy_buffer */
1090 driver
->CopyBufferSubData
= _mesa_copy_buffer_subdata
;
1095 _mesa_buffer_unmap_all_mappings(struct gl_context
*ctx
,
1096 struct gl_buffer_object
*bufObj
)
1100 for (i
= 0; i
< MAP_COUNT
; i
++) {
1101 if (_mesa_bufferobj_mapped(bufObj
, i
)) {
1102 ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, i
);
1103 ASSERT(bufObj
->Mappings
[i
].Pointer
== NULL
);
1104 bufObj
->Mappings
[i
].AccessFlags
= 0;
1110 /**********************************************************************/
1112 /**********************************************************************/
1115 _mesa_BindBuffer(GLenum target
, GLuint buffer
)
1117 GET_CURRENT_CONTEXT(ctx
);
1119 if (MESA_VERBOSE
& VERBOSE_API
)
1120 _mesa_debug(ctx
, "glBindBuffer(%s, %u)\n",
1121 _mesa_lookup_enum_by_nr(target
), buffer
);
1123 bind_buffer_object(ctx
, target
, buffer
);
1128 * Delete a set of buffer objects.
1130 * \param n Number of buffer objects to delete.
1131 * \param ids Array of \c n buffer object IDs.
1134 _mesa_DeleteBuffers(GLsizei n
, const GLuint
*ids
)
1136 GET_CURRENT_CONTEXT(ctx
);
1138 FLUSH_VERTICES(ctx
, 0);
1141 _mesa_error(ctx
, GL_INVALID_VALUE
, "glDeleteBuffersARB(n)");
1145 mtx_lock(&ctx
->Shared
->Mutex
);
1147 for (i
= 0; i
< n
; i
++) {
1148 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, ids
[i
]);
1150 struct gl_vertex_array_object
*vao
= ctx
->Array
.VAO
;
1153 ASSERT(bufObj
->Name
== ids
[i
] || bufObj
== &DummyBufferObject
);
1155 _mesa_buffer_unmap_all_mappings(ctx
, bufObj
);
1157 /* unbind any vertex pointers bound to this buffer */
1158 for (j
= 0; j
< Elements(vao
->VertexBinding
); j
++) {
1159 unbind(ctx
, &vao
->VertexBinding
[j
].BufferObj
, bufObj
);
1162 if (ctx
->Array
.ArrayBufferObj
== bufObj
) {
1163 _mesa_BindBuffer( GL_ARRAY_BUFFER_ARB
, 0 );
1165 if (vao
->IndexBufferObj
== bufObj
) {
1166 _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB
, 0 );
1169 /* unbind ARB_draw_indirect binding point */
1170 if (ctx
->DrawIndirectBuffer
== bufObj
) {
1171 _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER
, 0 );
1174 /* unbind ARB_copy_buffer binding points */
1175 if (ctx
->CopyReadBuffer
== bufObj
) {
1176 _mesa_BindBuffer( GL_COPY_READ_BUFFER
, 0 );
1178 if (ctx
->CopyWriteBuffer
== bufObj
) {
1179 _mesa_BindBuffer( GL_COPY_WRITE_BUFFER
, 0 );
1182 /* unbind transform feedback binding points */
1183 if (ctx
->TransformFeedback
.CurrentBuffer
== bufObj
) {
1184 _mesa_BindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER
, 0 );
1186 for (j
= 0; j
< MAX_FEEDBACK_BUFFERS
; j
++) {
1187 if (ctx
->TransformFeedback
.CurrentObject
->Buffers
[j
] == bufObj
) {
1188 _mesa_BindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER
, j
, 0 );
1192 /* unbind UBO binding points */
1193 for (j
= 0; j
< ctx
->Const
.MaxUniformBufferBindings
; j
++) {
1194 if (ctx
->UniformBufferBindings
[j
].BufferObject
== bufObj
) {
1195 _mesa_BindBufferBase( GL_UNIFORM_BUFFER
, j
, 0 );
1199 if (ctx
->UniformBuffer
== bufObj
) {
1200 _mesa_BindBuffer( GL_UNIFORM_BUFFER
, 0 );
1203 /* unbind any pixel pack/unpack pointers bound to this buffer */
1204 if (ctx
->Pack
.BufferObj
== bufObj
) {
1205 _mesa_BindBuffer( GL_PIXEL_PACK_BUFFER_EXT
, 0 );
1207 if (ctx
->Unpack
.BufferObj
== bufObj
) {
1208 _mesa_BindBuffer( GL_PIXEL_UNPACK_BUFFER_EXT
, 0 );
1211 if (ctx
->Texture
.BufferObject
== bufObj
) {
1212 _mesa_BindBuffer( GL_TEXTURE_BUFFER
, 0 );
1215 /* The ID is immediately freed for re-use */
1216 _mesa_HashRemove(ctx
->Shared
->BufferObjects
, ids
[i
]);
1217 /* Make sure we do not run into the classic ABA problem on bind.
1218 * We don't want to allow re-binding a buffer object that's been
1219 * "deleted" by glDeleteBuffers().
1221 * The explicit rebinding to the default object in the current context
1222 * prevents the above in the current context, but another context
1223 * sharing the same objects might suffer from this problem.
1224 * The alternative would be to do the hash lookup in any case on bind
1225 * which would introduce more runtime overhead than this.
1227 bufObj
->DeletePending
= GL_TRUE
;
1228 _mesa_reference_buffer_object(ctx
, &bufObj
, NULL
);
1232 mtx_unlock(&ctx
->Shared
->Mutex
);
1237 * Generate a set of unique buffer object IDs and store them in \c buffer.
1239 * \param n Number of IDs to generate.
1240 * \param buffer Array of \c n locations to store the IDs.
1243 _mesa_GenBuffers(GLsizei n
, GLuint
*buffer
)
1245 GET_CURRENT_CONTEXT(ctx
);
1249 if (MESA_VERBOSE
& VERBOSE_API
)
1250 _mesa_debug(ctx
, "glGenBuffers(%d)\n", n
);
1253 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenBuffersARB");
1262 * This must be atomic (generation and allocation of buffer object IDs)
1264 mtx_lock(&ctx
->Shared
->Mutex
);
1266 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->BufferObjects
, n
);
1268 /* Insert the ID and pointer to dummy buffer object into hash table */
1269 for (i
= 0; i
< n
; i
++) {
1270 _mesa_HashInsert(ctx
->Shared
->BufferObjects
, first
+ i
,
1271 &DummyBufferObject
);
1272 buffer
[i
] = first
+ i
;
1275 mtx_unlock(&ctx
->Shared
->Mutex
);
1280 * Determine if ID is the name of a buffer object.
1282 * \param id ID of the potential buffer object.
1283 * \return \c GL_TRUE if \c id is the name of a buffer object,
1284 * \c GL_FALSE otherwise.
1286 GLboolean GLAPIENTRY
1287 _mesa_IsBuffer(GLuint id
)
1289 struct gl_buffer_object
*bufObj
;
1290 GET_CURRENT_CONTEXT(ctx
);
1291 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
1293 mtx_lock(&ctx
->Shared
->Mutex
);
1294 bufObj
= _mesa_lookup_bufferobj(ctx
, id
);
1295 mtx_unlock(&ctx
->Shared
->Mutex
);
1297 return bufObj
&& bufObj
!= &DummyBufferObject
;
1302 _mesa_BufferStorage(GLenum target
, GLsizeiptr size
, const GLvoid
*data
,
1305 GET_CURRENT_CONTEXT(ctx
);
1306 struct gl_buffer_object
*bufObj
;
1309 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBufferStorage(size <= 0)");
1313 if (flags
& ~(GL_MAP_READ_BIT
|
1315 GL_MAP_PERSISTENT_BIT
|
1316 GL_MAP_COHERENT_BIT
|
1317 GL_DYNAMIC_STORAGE_BIT
|
1318 GL_CLIENT_STORAGE_BIT
)) {
1319 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBufferStorage(flags)");
1323 if (flags
& GL_MAP_PERSISTENT_BIT
&&
1324 !(flags
& (GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
))) {
1325 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBufferStorage(flags!=READ/WRITE)");
1329 if (flags
& GL_MAP_COHERENT_BIT
&& !(flags
& GL_MAP_PERSISTENT_BIT
)) {
1330 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBufferStorage(flags!=PERSISTENT)");
1334 bufObj
= get_buffer(ctx
, "glBufferStorage", target
, GL_INVALID_OPERATION
);
1338 if (bufObj
->Immutable
) {
1339 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBufferStorage(immutable)");
1343 /* Unmap the existing buffer. We'll replace it now. Not an error. */
1344 _mesa_buffer_unmap_all_mappings(ctx
, bufObj
);
1346 FLUSH_VERTICES(ctx
, _NEW_BUFFER_OBJECT
);
1348 bufObj
->Written
= GL_TRUE
;
1349 bufObj
->Immutable
= GL_TRUE
;
1351 ASSERT(ctx
->Driver
.BufferData
);
1352 if (!ctx
->Driver
.BufferData(ctx
, target
, size
, data
, GL_DYNAMIC_DRAW
,
1354 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBufferStorage()");
1360 _mesa_BufferData(GLenum target
, GLsizeiptrARB size
,
1361 const GLvoid
* data
, GLenum usage
)
1363 GET_CURRENT_CONTEXT(ctx
);
1364 struct gl_buffer_object
*bufObj
;
1367 if (MESA_VERBOSE
& VERBOSE_API
)
1368 _mesa_debug(ctx
, "glBufferData(%s, %ld, %p, %s)\n",
1369 _mesa_lookup_enum_by_nr(target
),
1370 (long int) size
, data
,
1371 _mesa_lookup_enum_by_nr(usage
));
1374 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBufferDataARB(size < 0)");
1379 case GL_STREAM_DRAW_ARB
:
1380 valid_usage
= (ctx
->API
!= API_OPENGLES
);
1383 case GL_STATIC_DRAW_ARB
:
1384 case GL_DYNAMIC_DRAW_ARB
:
1388 case GL_STREAM_READ_ARB
:
1389 case GL_STREAM_COPY_ARB
:
1390 case GL_STATIC_READ_ARB
:
1391 case GL_STATIC_COPY_ARB
:
1392 case GL_DYNAMIC_READ_ARB
:
1393 case GL_DYNAMIC_COPY_ARB
:
1394 valid_usage
= _mesa_is_desktop_gl(ctx
) || _mesa_is_gles3(ctx
);
1398 valid_usage
= false;
1403 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBufferData(usage)");
1407 bufObj
= get_buffer(ctx
, "glBufferDataARB", target
, GL_INVALID_OPERATION
);
1411 if (bufObj
->Immutable
) {
1412 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBufferData(immutable)");
1416 /* Unmap the existing buffer. We'll replace it now. Not an error. */
1417 _mesa_buffer_unmap_all_mappings(ctx
, bufObj
);
1419 FLUSH_VERTICES(ctx
, _NEW_BUFFER_OBJECT
);
1421 bufObj
->Written
= GL_TRUE
;
1424 printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
1425 bufObj
->Name
, size
, data
, usage
);
1432 ASSERT(ctx
->Driver
.BufferData
);
1433 if (!ctx
->Driver
.BufferData(ctx
, target
, size
, data
, usage
,
1436 GL_DYNAMIC_STORAGE_BIT
,
1438 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBufferDataARB()");
1444 _mesa_BufferSubData(GLenum target
, GLintptrARB offset
,
1445 GLsizeiptrARB size
, const GLvoid
* data
)
1447 GET_CURRENT_CONTEXT(ctx
);
1448 struct gl_buffer_object
*bufObj
;
1450 bufObj
= buffer_object_subdata_range_good( ctx
, target
, offset
, size
,
1451 false, GL_INVALID_OPERATION
,
1452 "glBufferSubDataARB" );
1454 /* error already recorded */
1458 if (bufObj
->Immutable
&&
1459 !(bufObj
->StorageFlags
& GL_DYNAMIC_STORAGE_BIT
)) {
1460 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glBufferSubData");
1467 bufObj
->Written
= GL_TRUE
;
1469 ASSERT(ctx
->Driver
.BufferSubData
);
1470 ctx
->Driver
.BufferSubData( ctx
, offset
, size
, data
, bufObj
);
1475 _mesa_GetBufferSubData(GLenum target
, GLintptrARB offset
,
1476 GLsizeiptrARB size
, void * data
)
1478 GET_CURRENT_CONTEXT(ctx
);
1479 struct gl_buffer_object
*bufObj
;
1481 bufObj
= buffer_object_subdata_range_good(ctx
, target
, offset
, size
,
1482 false, GL_INVALID_OPERATION
,
1483 "glGetBufferSubDataARB");
1485 /* error already recorded */
1489 ASSERT(ctx
->Driver
.GetBufferSubData
);
1490 ctx
->Driver
.GetBufferSubData( ctx
, offset
, size
, data
, bufObj
);
1495 _mesa_ClearBufferData(GLenum target
, GLenum internalformat
, GLenum format
,
1496 GLenum type
, const GLvoid
* data
)
1498 GET_CURRENT_CONTEXT(ctx
);
1499 struct gl_buffer_object
* bufObj
;
1500 mesa_format mesaFormat
;
1501 GLubyte clearValue
[MAX_PIXEL_BYTES
];
1502 GLsizeiptr clearValueSize
;
1504 bufObj
= get_buffer(ctx
, "glClearBufferData", target
, GL_INVALID_VALUE
);
1509 if (_mesa_check_disallowed_mapping(bufObj
)) {
1510 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1511 "glClearBufferData(buffer currently mapped)");
1515 mesaFormat
= validate_clear_buffer_format(ctx
, internalformat
,
1517 "glClearBufferData");
1518 if (mesaFormat
== MESA_FORMAT_NONE
) {
1522 clearValueSize
= _mesa_get_format_bytes(mesaFormat
);
1523 if (bufObj
->Size
% clearValueSize
!= 0) {
1524 _mesa_error(ctx
, GL_INVALID_VALUE
,
1525 "glClearBufferData(size is not a multiple of "
1526 "internalformat size)");
1531 /* clear to zeros, per the spec */
1532 ctx
->Driver
.ClearBufferSubData(ctx
, 0, bufObj
->Size
,
1533 NULL
, clearValueSize
, bufObj
);
1537 if (!convert_clear_buffer_data(ctx
, mesaFormat
, clearValue
,
1538 format
, type
, data
, "glClearBufferData")) {
1542 ctx
->Driver
.ClearBufferSubData(ctx
, 0, bufObj
->Size
,
1543 clearValue
, clearValueSize
, bufObj
);
1548 _mesa_ClearBufferSubData(GLenum target
, GLenum internalformat
,
1549 GLintptr offset
, GLsizeiptr size
,
1550 GLenum format
, GLenum type
,
1553 GET_CURRENT_CONTEXT(ctx
);
1554 struct gl_buffer_object
* bufObj
;
1555 mesa_format mesaFormat
;
1556 GLubyte clearValue
[MAX_PIXEL_BYTES
];
1557 GLsizeiptr clearValueSize
;
1559 bufObj
= buffer_object_subdata_range_good(ctx
, target
, offset
, size
,
1560 true, GL_INVALID_VALUE
,
1561 "glClearBufferSubData");
1566 mesaFormat
= validate_clear_buffer_format(ctx
, internalformat
,
1568 "glClearBufferSubData");
1569 if (mesaFormat
== MESA_FORMAT_NONE
) {
1573 clearValueSize
= _mesa_get_format_bytes(mesaFormat
);
1574 if (offset
% clearValueSize
!= 0 || size
% clearValueSize
!= 0) {
1575 _mesa_error(ctx
, GL_INVALID_VALUE
,
1576 "glClearBufferSubData(offset or size is not a multiple of "
1577 "internalformat size)");
1582 /* clear to zeros, per the spec */
1584 ctx
->Driver
.ClearBufferSubData(ctx
, offset
, size
,
1585 NULL
, clearValueSize
, bufObj
);
1590 if (!convert_clear_buffer_data(ctx
, mesaFormat
, clearValue
,
1592 "glClearBufferSubData")) {
1597 ctx
->Driver
.ClearBufferSubData(ctx
, offset
, size
,
1598 clearValue
, clearValueSize
, bufObj
);
1604 _mesa_MapBuffer(GLenum target
, GLenum access
)
1606 GET_CURRENT_CONTEXT(ctx
);
1607 struct gl_buffer_object
* bufObj
;
1608 GLbitfield accessFlags
;
1612 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, NULL
);
1615 case GL_READ_ONLY_ARB
:
1616 accessFlags
= GL_MAP_READ_BIT
;
1617 valid_access
= _mesa_is_desktop_gl(ctx
);
1619 case GL_WRITE_ONLY_ARB
:
1620 accessFlags
= GL_MAP_WRITE_BIT
;
1621 valid_access
= true;
1623 case GL_READ_WRITE_ARB
:
1624 accessFlags
= GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
;
1625 valid_access
= _mesa_is_desktop_gl(ctx
);
1628 valid_access
= false;
1632 if (!valid_access
) {
1633 _mesa_error(ctx
, GL_INVALID_ENUM
, "glMapBufferARB(access)");
1637 bufObj
= get_buffer(ctx
, "glMapBufferARB", target
, GL_INVALID_OPERATION
);
1641 if (accessFlags
& GL_MAP_READ_BIT
&&
1642 !(bufObj
->StorageFlags
& GL_MAP_READ_BIT
)) {
1643 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1644 "glMapBuffer(invalid read flag)");
1648 if (accessFlags
& GL_MAP_WRITE_BIT
&&
1649 !(bufObj
->StorageFlags
& GL_MAP_WRITE_BIT
)) {
1650 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1651 "glMapBuffer(invalid write flag)");
1655 if (_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
1656 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glMapBufferARB(already mapped)");
1660 if (!bufObj
->Size
) {
1661 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
1662 "glMapBuffer(buffer size = 0)");
1666 ASSERT(ctx
->Driver
.MapBufferRange
);
1667 map
= ctx
->Driver
.MapBufferRange(ctx
, 0, bufObj
->Size
, accessFlags
, bufObj
,
1670 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glMapBufferARB(map failed)");
1674 /* The driver callback should have set these fields.
1675 * This is important because other modules (like VBO) might call
1676 * the driver function directly.
1678 ASSERT(bufObj
->Mappings
[MAP_USER
].Pointer
== map
);
1679 ASSERT(bufObj
->Mappings
[MAP_USER
].Length
== bufObj
->Size
);
1680 ASSERT(bufObj
->Mappings
[MAP_USER
].Offset
== 0);
1681 bufObj
->Mappings
[MAP_USER
].AccessFlags
= accessFlags
;
1684 if (access
== GL_WRITE_ONLY_ARB
|| access
== GL_READ_WRITE_ARB
)
1685 bufObj
->Written
= GL_TRUE
;
1688 printf("glMapBufferARB(%u, sz %ld, access 0x%x)\n",
1689 bufObj
->Name
, bufObj
->Size
, access
);
1690 if (access
== GL_WRITE_ONLY_ARB
) {
1692 GLubyte
*b
= (GLubyte
*) bufObj
->Pointer
;
1693 for (i
= 0; i
< bufObj
->Size
; i
++)
1700 GLubyte
*buf
= (GLubyte
*) bufObj
->Pointer
;
1702 /* buffer is 100 bytes larger than requested, fill with magic value */
1703 for (i
= 0; i
< 100; i
++) {
1704 buf
[bufObj
->Size
- i
- 1] = 123;
1709 return bufObj
->Mappings
[MAP_USER
].Pointer
;
1713 GLboolean GLAPIENTRY
1714 _mesa_UnmapBuffer(GLenum target
)
1716 GET_CURRENT_CONTEXT(ctx
);
1717 struct gl_buffer_object
*bufObj
;
1718 GLboolean status
= GL_TRUE
;
1719 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
1721 bufObj
= get_buffer(ctx
, "glUnmapBufferARB", target
, GL_INVALID_OPERATION
);
1725 if (!_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
1726 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glUnmapBufferARB");
1731 if (bufObj
->Access
!= GL_READ_ONLY_ARB
) {
1732 GLubyte
*buf
= (GLubyte
*) bufObj
->Pointer
;
1734 /* check that last 100 bytes are still = magic value */
1735 for (i
= 0; i
< 100; i
++) {
1736 GLuint pos
= bufObj
->Size
- i
- 1;
1737 if (buf
[pos
] != 123) {
1738 _mesa_warning(ctx
, "Out of bounds buffer object write detected"
1739 " at position %d (value = %u)\n",
1747 if (bufObj
->AccessFlags
& GL_MAP_WRITE_BIT
) {
1748 GLuint i
, unchanged
= 0;
1749 GLubyte
*b
= (GLubyte
*) bufObj
->Pointer
;
1751 /* check which bytes changed */
1752 for (i
= 0; i
< bufObj
->Size
- 1; i
++) {
1753 if (b
[i
] == (i
& 0xff) && b
[i
+1] == ((i
+1) & 0xff)) {
1760 printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
1761 bufObj
->Name
, unchanged
, bufObj
->Size
, pos
);
1766 status
= ctx
->Driver
.UnmapBuffer(ctx
, bufObj
, MAP_USER
);
1767 bufObj
->Mappings
[MAP_USER
].AccessFlags
= 0;
1768 ASSERT(bufObj
->Mappings
[MAP_USER
].Pointer
== NULL
);
1769 ASSERT(bufObj
->Mappings
[MAP_USER
].Offset
== 0);
1770 ASSERT(bufObj
->Mappings
[MAP_USER
].Length
== 0);
1777 _mesa_GetBufferParameteriv(GLenum target
, GLenum pname
, GLint
*params
)
1779 GET_CURRENT_CONTEXT(ctx
);
1780 struct gl_buffer_object
*bufObj
;
1782 bufObj
= get_buffer(ctx
, "glGetBufferParameterivARB", target
,
1783 GL_INVALID_OPERATION
);
1788 case GL_BUFFER_SIZE_ARB
:
1789 *params
= (GLint
) bufObj
->Size
;
1791 case GL_BUFFER_USAGE_ARB
:
1792 *params
= bufObj
->Usage
;
1794 case GL_BUFFER_ACCESS_ARB
:
1795 *params
= simplified_access_mode(ctx
,
1796 bufObj
->Mappings
[MAP_USER
].AccessFlags
);
1798 case GL_BUFFER_MAPPED_ARB
:
1799 *params
= _mesa_bufferobj_mapped(bufObj
, MAP_USER
);
1801 case GL_BUFFER_ACCESS_FLAGS
:
1802 if (!ctx
->Extensions
.ARB_map_buffer_range
)
1804 *params
= bufObj
->Mappings
[MAP_USER
].AccessFlags
;
1806 case GL_BUFFER_MAP_OFFSET
:
1807 if (!ctx
->Extensions
.ARB_map_buffer_range
)
1809 *params
= (GLint
) bufObj
->Mappings
[MAP_USER
].Offset
;
1811 case GL_BUFFER_MAP_LENGTH
:
1812 if (!ctx
->Extensions
.ARB_map_buffer_range
)
1814 *params
= (GLint
) bufObj
->Mappings
[MAP_USER
].Length
;
1816 case GL_BUFFER_IMMUTABLE_STORAGE
:
1817 if (!ctx
->Extensions
.ARB_buffer_storage
)
1819 *params
= bufObj
->Immutable
;
1821 case GL_BUFFER_STORAGE_FLAGS
:
1822 if (!ctx
->Extensions
.ARB_buffer_storage
)
1824 *params
= bufObj
->StorageFlags
;
1827 ; /* fall-through */
1831 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetBufferParameterivARB(pname=%s)",
1832 _mesa_lookup_enum_by_nr(pname
));
1838 * This is pretty much a duplicate of GetBufferParameteriv() but the
1839 * GL_BUFFER_SIZE_ARB attribute will be 64-bits on a 64-bit system.
1842 _mesa_GetBufferParameteri64v(GLenum target
, GLenum pname
, GLint64
*params
)
1844 GET_CURRENT_CONTEXT(ctx
);
1845 struct gl_buffer_object
*bufObj
;
1847 bufObj
= get_buffer(ctx
, "glGetBufferParameteri64v", target
,
1848 GL_INVALID_OPERATION
);
1853 case GL_BUFFER_SIZE_ARB
:
1854 *params
= bufObj
->Size
;
1856 case GL_BUFFER_USAGE_ARB
:
1857 *params
= bufObj
->Usage
;
1859 case GL_BUFFER_ACCESS_ARB
:
1860 *params
= simplified_access_mode(ctx
,
1861 bufObj
->Mappings
[MAP_USER
].AccessFlags
);
1863 case GL_BUFFER_ACCESS_FLAGS
:
1864 if (!ctx
->Extensions
.ARB_map_buffer_range
)
1866 *params
= bufObj
->Mappings
[MAP_USER
].AccessFlags
;
1868 case GL_BUFFER_MAPPED_ARB
:
1869 *params
= _mesa_bufferobj_mapped(bufObj
, MAP_USER
);
1871 case GL_BUFFER_MAP_OFFSET
:
1872 if (!ctx
->Extensions
.ARB_map_buffer_range
)
1874 *params
= bufObj
->Mappings
[MAP_USER
].Offset
;
1876 case GL_BUFFER_MAP_LENGTH
:
1877 if (!ctx
->Extensions
.ARB_map_buffer_range
)
1879 *params
= bufObj
->Mappings
[MAP_USER
].Length
;
1881 case GL_BUFFER_IMMUTABLE_STORAGE
:
1882 if (!ctx
->Extensions
.ARB_buffer_storage
)
1884 *params
= bufObj
->Immutable
;
1886 case GL_BUFFER_STORAGE_FLAGS
:
1887 if (!ctx
->Extensions
.ARB_buffer_storage
)
1889 *params
= bufObj
->StorageFlags
;
1892 ; /* fall-through */
1896 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetBufferParameteri64v(pname=%s)",
1897 _mesa_lookup_enum_by_nr(pname
));
1902 _mesa_GetBufferPointerv(GLenum target
, GLenum pname
, GLvoid
**params
)
1904 GET_CURRENT_CONTEXT(ctx
);
1905 struct gl_buffer_object
* bufObj
;
1907 if (pname
!= GL_BUFFER_MAP_POINTER_ARB
) {
1908 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetBufferPointervARB(pname)");
1912 bufObj
= get_buffer(ctx
, "glGetBufferPointervARB", target
,
1913 GL_INVALID_OPERATION
);
1917 *params
= bufObj
->Mappings
[MAP_USER
].Pointer
;
1922 _mesa_CopyBufferSubData(GLenum readTarget
, GLenum writeTarget
,
1923 GLintptr readOffset
, GLintptr writeOffset
,
1926 GET_CURRENT_CONTEXT(ctx
);
1927 struct gl_buffer_object
*src
, *dst
;
1929 src
= get_buffer(ctx
, "glCopyBufferSubData", readTarget
,
1930 GL_INVALID_OPERATION
);
1934 dst
= get_buffer(ctx
, "glCopyBufferSubData", writeTarget
,
1935 GL_INVALID_OPERATION
);
1939 if (_mesa_check_disallowed_mapping(src
)) {
1940 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1941 "glCopyBufferSubData(readBuffer is mapped)");
1945 if (_mesa_check_disallowed_mapping(dst
)) {
1946 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1947 "glCopyBufferSubData(writeBuffer is mapped)");
1951 if (readOffset
< 0) {
1952 _mesa_error(ctx
, GL_INVALID_VALUE
,
1953 "glCopyBufferSubData(readOffset = %d)", (int) readOffset
);
1957 if (writeOffset
< 0) {
1958 _mesa_error(ctx
, GL_INVALID_VALUE
,
1959 "glCopyBufferSubData(writeOffset = %d)", (int) writeOffset
);
1964 _mesa_error(ctx
, GL_INVALID_VALUE
,
1965 "glCopyBufferSubData(writeOffset = %d)", (int) size
);
1969 if (readOffset
+ size
> src
->Size
) {
1970 _mesa_error(ctx
, GL_INVALID_VALUE
,
1971 "glCopyBufferSubData(readOffset + size = %d)",
1972 (int) (readOffset
+ size
));
1976 if (writeOffset
+ size
> dst
->Size
) {
1977 _mesa_error(ctx
, GL_INVALID_VALUE
,
1978 "glCopyBufferSubData(writeOffset + size = %d)",
1979 (int) (writeOffset
+ size
));
1984 if (readOffset
+ size
<= writeOffset
) {
1987 else if (writeOffset
+ size
<= readOffset
) {
1991 /* overlapping src/dst is illegal */
1992 _mesa_error(ctx
, GL_INVALID_VALUE
,
1993 "glCopyBufferSubData(overlapping src/dst)");
1998 ctx
->Driver
.CopyBufferSubData(ctx
, src
, dst
, readOffset
, writeOffset
, size
);
2003 * See GL_ARB_map_buffer_range spec
2006 _mesa_MapBufferRange(GLenum target
, GLintptr offset
, GLsizeiptr length
,
2009 GET_CURRENT_CONTEXT(ctx
);
2010 struct gl_buffer_object
*bufObj
;
2012 GLbitfield allowed_access
;
2014 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, NULL
);
2016 if (!ctx
->Extensions
.ARB_map_buffer_range
) {
2017 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2018 "glMapBufferRange(extension not supported)");
2023 _mesa_error(ctx
, GL_INVALID_VALUE
,
2024 "glMapBufferRange(offset = %ld)", (long)offset
);
2029 _mesa_error(ctx
, GL_INVALID_VALUE
,
2030 "glMapBufferRange(length = %ld)", (long)length
);
2034 /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
2036 * "An INVALID_OPERATION error is generated for any of the following
2039 * * <length> is zero."
2041 if (_mesa_is_gles(ctx
) && length
== 0) {
2042 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2043 "glMapBufferRange(length = 0)");
2047 allowed_access
= GL_MAP_READ_BIT
|
2049 GL_MAP_INVALIDATE_RANGE_BIT
|
2050 GL_MAP_INVALIDATE_BUFFER_BIT
|
2051 GL_MAP_FLUSH_EXPLICIT_BIT
|
2052 GL_MAP_UNSYNCHRONIZED_BIT
;
2054 if (ctx
->Extensions
.ARB_buffer_storage
) {
2055 allowed_access
|= GL_MAP_PERSISTENT_BIT
|
2056 GL_MAP_COHERENT_BIT
;
2059 if (access
& ~allowed_access
) {
2060 /* generate an error if any other than allowed bit is set */
2061 _mesa_error(ctx
, GL_INVALID_VALUE
, "glMapBufferRange(access)");
2065 if ((access
& (GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
)) == 0) {
2066 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2067 "glMapBufferRange(access indicates neither read or write)");
2071 if ((access
& GL_MAP_READ_BIT
) &&
2072 (access
& (GL_MAP_INVALIDATE_RANGE_BIT
|
2073 GL_MAP_INVALIDATE_BUFFER_BIT
|
2074 GL_MAP_UNSYNCHRONIZED_BIT
))) {
2075 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2076 "glMapBufferRange(invalid access flags)");
2080 if ((access
& GL_MAP_FLUSH_EXPLICIT_BIT
) &&
2081 ((access
& GL_MAP_WRITE_BIT
) == 0)) {
2082 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2083 "glMapBufferRange(invalid access flags)");
2087 bufObj
= get_buffer(ctx
, "glMapBufferRange", target
, GL_INVALID_OPERATION
);
2091 if (access
& GL_MAP_READ_BIT
&&
2092 !(bufObj
->StorageFlags
& GL_MAP_READ_BIT
)) {
2093 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2094 "glMapBufferRange(invalid read flag)");
2098 if (access
& GL_MAP_WRITE_BIT
&&
2099 !(bufObj
->StorageFlags
& GL_MAP_WRITE_BIT
)) {
2100 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2101 "glMapBufferRange(invalid write flag)");
2105 if (access
& GL_MAP_COHERENT_BIT
&&
2106 !(bufObj
->StorageFlags
& GL_MAP_COHERENT_BIT
)) {
2107 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2108 "glMapBufferRange(invalid coherent flag)");
2112 if (access
& GL_MAP_PERSISTENT_BIT
&&
2113 !(bufObj
->StorageFlags
& GL_MAP_PERSISTENT_BIT
)) {
2114 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2115 "glMapBufferRange(invalid persistent flag)");
2119 if (offset
+ length
> bufObj
->Size
) {
2120 _mesa_error(ctx
, GL_INVALID_VALUE
,
2121 "glMapBufferRange(offset + length > size)");
2125 if (_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
2126 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2127 "glMapBufferRange(buffer already mapped)");
2131 if (!bufObj
->Size
) {
2132 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
2133 "glMapBufferRange(buffer size = 0)");
2137 /* Mapping zero bytes should return a non-null pointer. */
2139 static long dummy
= 0;
2140 bufObj
->Mappings
[MAP_USER
].Pointer
= &dummy
;
2141 bufObj
->Mappings
[MAP_USER
].Length
= length
;
2142 bufObj
->Mappings
[MAP_USER
].Offset
= offset
;
2143 bufObj
->Mappings
[MAP_USER
].AccessFlags
= access
;
2144 return bufObj
->Mappings
[MAP_USER
].Pointer
;
2147 ASSERT(ctx
->Driver
.MapBufferRange
);
2148 map
= ctx
->Driver
.MapBufferRange(ctx
, offset
, length
, access
, bufObj
,
2151 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glMapBufferARB(map failed)");
2154 /* The driver callback should have set all these fields.
2155 * This is important because other modules (like VBO) might call
2156 * the driver function directly.
2158 ASSERT(bufObj
->Mappings
[MAP_USER
].Pointer
== map
);
2159 ASSERT(bufObj
->Mappings
[MAP_USER
].Length
== length
);
2160 ASSERT(bufObj
->Mappings
[MAP_USER
].Offset
== offset
);
2161 ASSERT(bufObj
->Mappings
[MAP_USER
].AccessFlags
== access
);
2169 * See GL_ARB_map_buffer_range spec
2172 _mesa_FlushMappedBufferRange(GLenum target
, GLintptr offset
, GLsizeiptr length
)
2174 GET_CURRENT_CONTEXT(ctx
);
2175 struct gl_buffer_object
*bufObj
;
2177 if (!ctx
->Extensions
.ARB_map_buffer_range
) {
2178 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2179 "glFlushMappedBufferRange(extension not supported)");
2184 _mesa_error(ctx
, GL_INVALID_VALUE
,
2185 "glFlushMappedBufferRange(offset = %ld)", (long)offset
);
2190 _mesa_error(ctx
, GL_INVALID_VALUE
,
2191 "glFlushMappedBufferRange(length = %ld)", (long)length
);
2195 bufObj
= get_buffer(ctx
, "glFlushMappedBufferRange", target
,
2196 GL_INVALID_OPERATION
);
2200 if (!_mesa_bufferobj_mapped(bufObj
, MAP_USER
)) {
2201 /* buffer is not mapped */
2202 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2203 "glFlushMappedBufferRange(buffer is not mapped)");
2207 if ((bufObj
->Mappings
[MAP_USER
].AccessFlags
&
2208 GL_MAP_FLUSH_EXPLICIT_BIT
) == 0) {
2209 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2210 "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
2214 if (offset
+ length
> bufObj
->Mappings
[MAP_USER
].Length
) {
2215 _mesa_error(ctx
, GL_INVALID_VALUE
,
2216 "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)",
2217 (long)offset
, (long)length
,
2218 (long)bufObj
->Mappings
[MAP_USER
].Length
);
2222 ASSERT(bufObj
->Mappings
[MAP_USER
].AccessFlags
& GL_MAP_WRITE_BIT
);
2224 if (ctx
->Driver
.FlushMappedBufferRange
)
2225 ctx
->Driver
.FlushMappedBufferRange(ctx
, offset
, length
, bufObj
,
2231 buffer_object_purgeable(struct gl_context
*ctx
, GLuint name
, GLenum option
)
2233 struct gl_buffer_object
*bufObj
;
2236 bufObj
= _mesa_lookup_bufferobj(ctx
, name
);
2238 _mesa_error(ctx
, GL_INVALID_VALUE
,
2239 "glObjectPurgeable(name = 0x%x)", name
);
2242 if (!_mesa_is_bufferobj(bufObj
)) {
2243 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glObjectPurgeable(buffer 0)" );
2247 if (bufObj
->Purgeable
) {
2248 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2249 "glObjectPurgeable(name = 0x%x) is already purgeable", name
);
2250 return GL_VOLATILE_APPLE
;
2253 bufObj
->Purgeable
= GL_TRUE
;
2255 retval
= GL_VOLATILE_APPLE
;
2256 if (ctx
->Driver
.BufferObjectPurgeable
)
2257 retval
= ctx
->Driver
.BufferObjectPurgeable(ctx
, bufObj
, option
);
2264 renderbuffer_purgeable(struct gl_context
*ctx
, GLuint name
, GLenum option
)
2266 struct gl_renderbuffer
*bufObj
;
2269 bufObj
= _mesa_lookup_renderbuffer(ctx
, name
);
2271 _mesa_error(ctx
, GL_INVALID_VALUE
,
2272 "glObjectUnpurgeable(name = 0x%x)", name
);
2276 if (bufObj
->Purgeable
) {
2277 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2278 "glObjectPurgeable(name = 0x%x) is already purgeable", name
);
2279 return GL_VOLATILE_APPLE
;
2282 bufObj
->Purgeable
= GL_TRUE
;
2284 retval
= GL_VOLATILE_APPLE
;
2285 if (ctx
->Driver
.RenderObjectPurgeable
)
2286 retval
= ctx
->Driver
.RenderObjectPurgeable(ctx
, bufObj
, option
);
2293 texture_object_purgeable(struct gl_context
*ctx
, GLuint name
, GLenum option
)
2295 struct gl_texture_object
*bufObj
;
2298 bufObj
= _mesa_lookup_texture(ctx
, name
);
2300 _mesa_error(ctx
, GL_INVALID_VALUE
,
2301 "glObjectPurgeable(name = 0x%x)", name
);
2305 if (bufObj
->Purgeable
) {
2306 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2307 "glObjectPurgeable(name = 0x%x) is already purgeable", name
);
2308 return GL_VOLATILE_APPLE
;
2311 bufObj
->Purgeable
= GL_TRUE
;
2313 retval
= GL_VOLATILE_APPLE
;
2314 if (ctx
->Driver
.TextureObjectPurgeable
)
2315 retval
= ctx
->Driver
.TextureObjectPurgeable(ctx
, bufObj
, option
);
2322 _mesa_ObjectPurgeableAPPLE(GLenum objectType
, GLuint name
, GLenum option
)
2326 GET_CURRENT_CONTEXT(ctx
);
2327 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, 0);
2330 _mesa_error(ctx
, GL_INVALID_VALUE
,
2331 "glObjectPurgeable(name = 0x%x)", name
);
2336 case GL_VOLATILE_APPLE
:
2337 case GL_RELEASED_APPLE
:
2341 _mesa_error(ctx
, GL_INVALID_ENUM
,
2342 "glObjectPurgeable(name = 0x%x) invalid option: %d",
2347 switch (objectType
) {
2349 retval
= texture_object_purgeable(ctx
, name
, option
);
2351 case GL_RENDERBUFFER_EXT
:
2352 retval
= renderbuffer_purgeable(ctx
, name
, option
);
2354 case GL_BUFFER_OBJECT_APPLE
:
2355 retval
= buffer_object_purgeable(ctx
, name
, option
);
2358 _mesa_error(ctx
, GL_INVALID_ENUM
,
2359 "glObjectPurgeable(name = 0x%x) invalid type: %d",
2364 /* In strict conformance to the spec, we must only return VOLATILE when
2365 * when passed the VOLATILE option. Madness.
2367 * XXX First fix the spec, then fix me.
2369 return option
== GL_VOLATILE_APPLE
? GL_VOLATILE_APPLE
: retval
;
2374 buffer_object_unpurgeable(struct gl_context
*ctx
, GLuint name
, GLenum option
)
2376 struct gl_buffer_object
*bufObj
;
2379 bufObj
= _mesa_lookup_bufferobj(ctx
, name
);
2381 _mesa_error(ctx
, GL_INVALID_VALUE
,
2382 "glObjectUnpurgeable(name = 0x%x)", name
);
2386 if (! bufObj
->Purgeable
) {
2387 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2388 "glObjectUnpurgeable(name = 0x%x) object is "
2389 " already \"unpurged\"", name
);
2393 bufObj
->Purgeable
= GL_FALSE
;
2396 if (ctx
->Driver
.BufferObjectUnpurgeable
)
2397 retval
= ctx
->Driver
.BufferObjectUnpurgeable(ctx
, bufObj
, option
);
2404 renderbuffer_unpurgeable(struct gl_context
*ctx
, GLuint name
, GLenum option
)
2406 struct gl_renderbuffer
*bufObj
;
2409 bufObj
= _mesa_lookup_renderbuffer(ctx
, name
);
2411 _mesa_error(ctx
, GL_INVALID_VALUE
,
2412 "glObjectUnpurgeable(name = 0x%x)", name
);
2416 if (! bufObj
->Purgeable
) {
2417 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2418 "glObjectUnpurgeable(name = 0x%x) object is "
2419 " already \"unpurged\"", name
);
2423 bufObj
->Purgeable
= GL_FALSE
;
2426 if (ctx
->Driver
.RenderObjectUnpurgeable
)
2427 retval
= ctx
->Driver
.RenderObjectUnpurgeable(ctx
, bufObj
, option
);
2434 texture_object_unpurgeable(struct gl_context
*ctx
, GLuint name
, GLenum option
)
2436 struct gl_texture_object
*bufObj
;
2439 bufObj
= _mesa_lookup_texture(ctx
, name
);
2441 _mesa_error(ctx
, GL_INVALID_VALUE
,
2442 "glObjectUnpurgeable(name = 0x%x)", name
);
2446 if (! bufObj
->Purgeable
) {
2447 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2448 "glObjectUnpurgeable(name = 0x%x) object is"
2449 " already \"unpurged\"", name
);
2453 bufObj
->Purgeable
= GL_FALSE
;
2456 if (ctx
->Driver
.TextureObjectUnpurgeable
)
2457 retval
= ctx
->Driver
.TextureObjectUnpurgeable(ctx
, bufObj
, option
);
2464 _mesa_ObjectUnpurgeableAPPLE(GLenum objectType
, GLuint name
, GLenum option
)
2466 GET_CURRENT_CONTEXT(ctx
);
2467 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, 0);
2470 _mesa_error(ctx
, GL_INVALID_VALUE
,
2471 "glObjectUnpurgeable(name = 0x%x)", name
);
2476 case GL_RETAINED_APPLE
:
2477 case GL_UNDEFINED_APPLE
:
2481 _mesa_error(ctx
, GL_INVALID_ENUM
,
2482 "glObjectUnpurgeable(name = 0x%x) invalid option: %d",
2487 switch (objectType
) {
2488 case GL_BUFFER_OBJECT_APPLE
:
2489 return buffer_object_unpurgeable(ctx
, name
, option
);
2491 return texture_object_unpurgeable(ctx
, name
, option
);
2492 case GL_RENDERBUFFER_EXT
:
2493 return renderbuffer_unpurgeable(ctx
, name
, option
);
2495 _mesa_error(ctx
, GL_INVALID_ENUM
,
2496 "glObjectUnpurgeable(name = 0x%x) invalid type: %d",
2504 get_buffer_object_parameteriv(struct gl_context
*ctx
, GLuint name
,
2505 GLenum pname
, GLint
*params
)
2507 struct gl_buffer_object
*bufObj
= _mesa_lookup_bufferobj(ctx
, name
);
2509 _mesa_error(ctx
, GL_INVALID_VALUE
,
2510 "glGetObjectParameteriv(name = 0x%x) invalid object", name
);
2515 case GL_PURGEABLE_APPLE
:
2516 *params
= bufObj
->Purgeable
;
2519 _mesa_error(ctx
, GL_INVALID_ENUM
,
2520 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
2528 get_renderbuffer_parameteriv(struct gl_context
*ctx
, GLuint name
,
2529 GLenum pname
, GLint
*params
)
2531 struct gl_renderbuffer
*rb
= _mesa_lookup_renderbuffer(ctx
, name
);
2533 _mesa_error(ctx
, GL_INVALID_VALUE
,
2534 "glObjectUnpurgeable(name = 0x%x)", name
);
2539 case GL_PURGEABLE_APPLE
:
2540 *params
= rb
->Purgeable
;
2543 _mesa_error(ctx
, GL_INVALID_ENUM
,
2544 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
2552 get_texture_object_parameteriv(struct gl_context
*ctx
, GLuint name
,
2553 GLenum pname
, GLint
*params
)
2555 struct gl_texture_object
*texObj
= _mesa_lookup_texture(ctx
, name
);
2557 _mesa_error(ctx
, GL_INVALID_VALUE
,
2558 "glObjectUnpurgeable(name = 0x%x)", name
);
2563 case GL_PURGEABLE_APPLE
:
2564 *params
= texObj
->Purgeable
;
2567 _mesa_error(ctx
, GL_INVALID_ENUM
,
2568 "glGetObjectParameteriv(name = 0x%x) invalid enum: %d",
2576 _mesa_GetObjectParameterivAPPLE(GLenum objectType
, GLuint name
, GLenum pname
,
2579 GET_CURRENT_CONTEXT(ctx
);
2582 _mesa_error(ctx
, GL_INVALID_VALUE
,
2583 "glGetObjectParameteriv(name = 0x%x)", name
);
2587 switch (objectType
) {
2589 get_texture_object_parameteriv(ctx
, name
, pname
, params
);
2591 case GL_BUFFER_OBJECT_APPLE
:
2592 get_buffer_object_parameteriv(ctx
, name
, pname
, params
);
2594 case GL_RENDERBUFFER_EXT
:
2595 get_renderbuffer_parameteriv(ctx
, name
, pname
, params
);
2598 _mesa_error(ctx
, GL_INVALID_ENUM
,
2599 "glGetObjectParameteriv(name = 0x%x) invalid type: %d",
2605 * Binds a buffer object to a uniform buffer binding point.
2607 * The caller is responsible for flushing vertices and updating
2611 set_ubo_binding(struct gl_context
*ctx
,
2612 struct gl_uniform_buffer_binding
*binding
,
2613 struct gl_buffer_object
*bufObj
,
2618 _mesa_reference_buffer_object(ctx
, &binding
->BufferObject
, bufObj
);
2620 binding
->Offset
= offset
;
2621 binding
->Size
= size
;
2622 binding
->AutomaticSize
= autoSize
;
2626 * Binds a buffer object to a uniform buffer binding point.
2628 * Unlike set_ubo_binding(), this function also flushes vertices
2629 * and updates NewDriverState. It also checks if the binding
2630 * has actually changed before updating it.
2633 bind_uniform_buffer(struct gl_context
*ctx
,
2635 struct gl_buffer_object
*bufObj
,
2640 struct gl_uniform_buffer_binding
*binding
=
2641 &ctx
->UniformBufferBindings
[index
];
2643 if (binding
->BufferObject
== bufObj
&&
2644 binding
->Offset
== offset
&&
2645 binding
->Size
== size
&&
2646 binding
->AutomaticSize
== autoSize
) {
2650 FLUSH_VERTICES(ctx
, 0);
2651 ctx
->NewDriverState
|= ctx
->DriverFlags
.NewUniformBuffer
;
2653 set_ubo_binding(ctx
, binding
, bufObj
, offset
, size
, autoSize
);
2657 * Bind a region of a buffer object to a uniform block binding point.
2658 * \param index the uniform buffer binding point index
2659 * \param bufObj the buffer object
2660 * \param offset offset to the start of buffer object region
2661 * \param size size of the buffer object region
2664 bind_buffer_range_uniform_buffer(struct gl_context
*ctx
,
2666 struct gl_buffer_object
*bufObj
,
2670 if (index
>= ctx
->Const
.MaxUniformBufferBindings
) {
2671 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferRange(index=%d)", index
);
2675 if (offset
& (ctx
->Const
.UniformBufferOffsetAlignment
- 1)) {
2676 _mesa_error(ctx
, GL_INVALID_VALUE
,
2677 "glBindBufferRange(offset misalgned %d/%d)", (int) offset
,
2678 ctx
->Const
.UniformBufferOffsetAlignment
);
2682 if (bufObj
== ctx
->Shared
->NullBufferObj
) {
2687 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
, bufObj
);
2688 bind_uniform_buffer(ctx
, index
, bufObj
, offset
, size
, GL_FALSE
);
2693 * Bind a buffer object to a uniform block binding point.
2694 * As above, but offset = 0.
2697 bind_buffer_base_uniform_buffer(struct gl_context
*ctx
,
2699 struct gl_buffer_object
*bufObj
)
2701 if (index
>= ctx
->Const
.MaxUniformBufferBindings
) {
2702 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferBase(index=%d)", index
);
2706 _mesa_reference_buffer_object(ctx
, &ctx
->UniformBuffer
, bufObj
);
2708 if (bufObj
== ctx
->Shared
->NullBufferObj
)
2709 bind_uniform_buffer(ctx
, index
, bufObj
, -1, -1, GL_TRUE
);
2711 bind_uniform_buffer(ctx
, index
, bufObj
, 0, 0, GL_TRUE
);
2715 * Binds a buffer object to an atomic buffer binding point.
2717 * The caller is responsible for validating the offset,
2718 * flushing the vertices and updating NewDriverState.
2721 set_atomic_buffer_binding(struct gl_context
*ctx
,
2722 struct gl_atomic_buffer_binding
*binding
,
2723 struct gl_buffer_object
*bufObj
,
2727 _mesa_reference_buffer_object(ctx
, &binding
->BufferObject
, bufObj
);
2729 if (bufObj
== ctx
->Shared
->NullBufferObj
) {
2730 binding
->Offset
= -1;
2733 binding
->Offset
= offset
;
2734 binding
->Size
= size
;
2739 * Binds a buffer object to an atomic buffer binding point.
2741 * Unlike set_atomic_buffer_binding(), this function also validates the
2742 * index and offset, flushes vertices, and updates NewDriverState.
2743 * It also checks if the binding has actually changing before
2747 bind_atomic_buffer(struct gl_context
*ctx
,
2749 struct gl_buffer_object
*bufObj
,
2754 struct gl_atomic_buffer_binding
*binding
;
2756 if (index
>= ctx
->Const
.MaxAtomicBufferBindings
) {
2757 _mesa_error(ctx
, GL_INVALID_VALUE
, "%s(index=%d)", name
, index
);
2761 if (offset
& (ATOMIC_COUNTER_SIZE
- 1)) {
2762 _mesa_error(ctx
, GL_INVALID_VALUE
,
2763 "%s(offset misalgned %d/%d)", name
, (int) offset
,
2764 ATOMIC_COUNTER_SIZE
);
2768 _mesa_reference_buffer_object(ctx
, &ctx
->AtomicBuffer
, bufObj
);
2770 binding
= &ctx
->AtomicBufferBindings
[index
];
2771 if (binding
->BufferObject
== bufObj
&&
2772 binding
->Offset
== offset
&&
2773 binding
->Size
== size
) {
2777 FLUSH_VERTICES(ctx
, 0);
2778 ctx
->NewDriverState
|= ctx
->DriverFlags
.NewAtomicBuffer
;
2780 set_atomic_buffer_binding(ctx
, binding
, bufObj
, offset
, size
);
2784 _mesa_BindBufferRange(GLenum target
, GLuint index
,
2785 GLuint buffer
, GLintptr offset
, GLsizeiptr size
)
2787 GET_CURRENT_CONTEXT(ctx
);
2788 struct gl_buffer_object
*bufObj
;
2791 bufObj
= ctx
->Shared
->NullBufferObj
;
2793 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2795 if (!_mesa_handle_bind_buffer_gen(ctx
, target
, buffer
,
2796 &bufObj
, "glBindBufferRange"))
2800 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2801 "glBindBufferRange(invalid buffer=%u)", buffer
);
2807 _mesa_error(ctx
, GL_INVALID_VALUE
, "glBindBufferRange(size=%d)",
2814 case GL_TRANSFORM_FEEDBACK_BUFFER
:
2815 _mesa_bind_buffer_range_transform_feedback(ctx
, index
, bufObj
,
2818 case GL_UNIFORM_BUFFER
:
2819 bind_buffer_range_uniform_buffer(ctx
, index
, bufObj
, offset
, size
);
2821 case GL_ATOMIC_COUNTER_BUFFER
:
2822 bind_atomic_buffer(ctx
, index
, bufObj
, offset
, size
,
2823 "glBindBufferRange");
2826 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBufferRange(target)");
2832 _mesa_BindBufferBase(GLenum target
, GLuint index
, GLuint buffer
)
2834 GET_CURRENT_CONTEXT(ctx
);
2835 struct gl_buffer_object
*bufObj
;
2838 bufObj
= ctx
->Shared
->NullBufferObj
;
2840 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2842 if (!_mesa_handle_bind_buffer_gen(ctx
, target
, buffer
,
2843 &bufObj
, "glBindBufferBase"))
2847 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2848 "glBindBufferBase(invalid buffer=%u)", buffer
);
2852 /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with
2853 * regards to BindBufferBase. It says (GL 3.1 core spec, page 63):
2855 * "BindBufferBase is equivalent to calling BindBufferRange with offset
2856 * zero and size equal to the size of buffer."
2858 * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230):
2860 * "If the parameter (starting offset or size) was not specified when the
2861 * buffer object was bound, zero is returned."
2863 * What happens if the size of the buffer changes? Does the size of the
2864 * buffer at the moment glBindBufferBase was called still play a role, like
2865 * the first quote would imply, or is the size meaningless in the
2866 * glBindBufferBase case like the second quote would suggest? The GL 4.1
2867 * core spec page 45 says:
2869 * "It is equivalent to calling BindBufferRange with offset zero, while
2870 * size is determined by the size of the bound buffer at the time the
2873 * My interpretation is that the GL 4.1 spec was a clarification of the
2874 * behavior, not a change. In particular, this choice will only make
2875 * rendering work in cases where it would have had undefined results.
2879 case GL_TRANSFORM_FEEDBACK_BUFFER
:
2880 _mesa_bind_buffer_base_transform_feedback(ctx
, index
, bufObj
);
2882 case GL_UNIFORM_BUFFER
:
2883 bind_buffer_base_uniform_buffer(ctx
, index
, bufObj
);
2885 case GL_ATOMIC_COUNTER_BUFFER
:
2886 bind_atomic_buffer(ctx
, index
, bufObj
, 0, 0,
2887 "glBindBufferBase");
2890 _mesa_error(ctx
, GL_INVALID_ENUM
, "glBindBufferBase(target)");
2896 _mesa_BindBuffersRange(GLenum target
, GLuint first
, GLsizei count
,
2897 const GLuint
*buffers
,
2898 const GLintptr
*offsets
, const GLsizeiptr
*sizes
)
2903 _mesa_BindBuffersBase(GLenum target
, GLuint first
, GLsizei count
,
2904 const GLuint
*buffers
)
2909 _mesa_InvalidateBufferSubData(GLuint buffer
, GLintptr offset
,
2912 GET_CURRENT_CONTEXT(ctx
);
2913 struct gl_buffer_object
*bufObj
;
2914 const GLintptr end
= offset
+ length
;
2916 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2918 _mesa_error(ctx
, GL_INVALID_VALUE
,
2919 "glInvalidateBufferSubData(name = 0x%x) invalid object",
2924 /* The GL_ARB_invalidate_subdata spec says:
2926 * "An INVALID_VALUE error is generated if <offset> or <length> is
2927 * negative, or if <offset> + <length> is greater than the value of
2930 if (end
< 0 || end
> bufObj
->Size
) {
2931 _mesa_error(ctx
, GL_INVALID_VALUE
,
2932 "glInvalidateBufferSubData(invalid offset or length)");
2936 /* The OpenGL 4.4 (Core Profile) spec says:
2938 * "An INVALID_OPERATION error is generated if buffer is currently
2939 * mapped by MapBuffer or if the invalidate range intersects the range
2940 * currently mapped by MapBufferRange, unless it was mapped
2941 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
2943 if (!(bufObj
->Mappings
[MAP_USER
].AccessFlags
& GL_MAP_PERSISTENT_BIT
) &&
2944 bufferobj_range_mapped(bufObj
, offset
, length
)) {
2945 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2946 "glInvalidateBufferSubData(intersection with mapped "
2951 /* We don't actually do anything for this yet. Just return after
2952 * validating the parameters and generating the required errors.
2958 _mesa_InvalidateBufferData(GLuint buffer
)
2960 GET_CURRENT_CONTEXT(ctx
);
2961 struct gl_buffer_object
*bufObj
;
2963 bufObj
= _mesa_lookup_bufferobj(ctx
, buffer
);
2965 _mesa_error(ctx
, GL_INVALID_VALUE
,
2966 "glInvalidateBufferData(name = 0x%x) invalid object",
2971 /* The OpenGL 4.4 (Core Profile) spec says:
2973 * "An INVALID_OPERATION error is generated if buffer is currently
2974 * mapped by MapBuffer or if the invalidate range intersects the range
2975 * currently mapped by MapBufferRange, unless it was mapped
2976 * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
2978 if (_mesa_check_disallowed_mapping(bufObj
)) {
2979 _mesa_error(ctx
, GL_INVALID_OPERATION
,
2980 "glInvalidateBufferData(intersection with mapped "
2985 /* We don't actually do anything for this yet. Just return after
2986 * validating the parameters and generating the required errors.