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