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