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