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