1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5848b8605Smrg * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
6848b8605Smrg *
7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8848b8605Smrg * copy of this software and associated documentation files (the "Software"),
9848b8605Smrg * to deal in the Software without restriction, including without limitation
10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
12848b8605Smrg * Software is furnished to do so, subject to the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice shall be included
15848b8605Smrg * in all copies or substantial portions of the Software.
16848b8605Smrg *
17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
24848b8605Smrg */
25848b8605Smrg
26848b8605Smrg
27848b8605Smrg/**
28848b8605Smrg * \file bufferobj.c
29848b8605Smrg * \brief Functions for the GL_ARB_vertex/pixel_buffer_object extensions.
30848b8605Smrg * \author Brian Paul, Ian Romanick
31848b8605Smrg */
32848b8605Smrg
33848b8605Smrg#include <stdbool.h>
34848b8605Smrg#include <inttypes.h>  /* for PRId64 macro */
35b8e80941Smrg#include "util/debug.h"
36848b8605Smrg#include "glheader.h"
37848b8605Smrg#include "enums.h"
38848b8605Smrg#include "hash.h"
39848b8605Smrg#include "imports.h"
40848b8605Smrg#include "context.h"
41848b8605Smrg#include "bufferobj.h"
42b8e80941Smrg#include "externalobjects.h"
43848b8605Smrg#include "mtypes.h"
44848b8605Smrg#include "teximage.h"
45848b8605Smrg#include "glformats.h"
46848b8605Smrg#include "texstore.h"
47848b8605Smrg#include "transformfeedback.h"
48b8e80941Smrg#include "varray.h"
49b8e80941Smrg#include "util/u_atomic.h"
50848b8605Smrg
51848b8605Smrg
52848b8605Smrg/* Debug flags */
53848b8605Smrg/*#define VBO_DEBUG*/
54848b8605Smrg/*#define BOUNDS_CHECK*/
55848b8605Smrg
56848b8605Smrg
57b8e80941Smrg/**
58b8e80941Smrg * We count the number of buffer modification calls to check for
59b8e80941Smrg * inefficient buffer use.  This is the number of such calls before we
60b8e80941Smrg * issue a warning.
61b8e80941Smrg */
62b8e80941Smrg#define BUFFER_WARNING_CALL_COUNT 4
63b8e80941Smrg
64b8e80941Smrg
65b8e80941Smrg/**
66b8e80941Smrg * Helper to warn of possible performance issues, such as frequently
67b8e80941Smrg * updating a buffer created with GL_STATIC_DRAW.  Called via the macro
68b8e80941Smrg * below.
69b8e80941Smrg */
70b8e80941Smrgstatic void
71b8e80941Smrgbuffer_usage_warning(struct gl_context *ctx, GLuint *id, const char *fmt, ...)
72b8e80941Smrg{
73b8e80941Smrg   va_list args;
74b8e80941Smrg
75b8e80941Smrg   va_start(args, fmt);
76b8e80941Smrg   _mesa_gl_vdebugf(ctx, id,
77b8e80941Smrg                    MESA_DEBUG_SOURCE_API,
78b8e80941Smrg                    MESA_DEBUG_TYPE_PERFORMANCE,
79b8e80941Smrg                    MESA_DEBUG_SEVERITY_MEDIUM,
80b8e80941Smrg                    fmt, args);
81b8e80941Smrg   va_end(args);
82b8e80941Smrg}
83b8e80941Smrg
84b8e80941Smrg#define BUFFER_USAGE_WARNING(CTX, FMT, ...) \
85b8e80941Smrg   do { \
86b8e80941Smrg      static GLuint id = 0; \
87b8e80941Smrg      buffer_usage_warning(CTX, &id, FMT, ##__VA_ARGS__); \
88b8e80941Smrg   } while (0)
89b8e80941Smrg
90b8e80941Smrg
91848b8605Smrg/**
92848b8605Smrg * Used as a placeholder for buffer objects between glGenBuffers() and
93848b8605Smrg * glBindBuffer() so that glIsBuffer() can work correctly.
94848b8605Smrg */
95848b8605Smrgstatic struct gl_buffer_object DummyBufferObject;
96848b8605Smrg
97848b8605Smrg
98848b8605Smrg/**
99848b8605Smrg * Return pointer to address of a buffer object target.
100848b8605Smrg * \param ctx  the GL context
101848b8605Smrg * \param target  the buffer object target to be retrieved.
102848b8605Smrg * \return   pointer to pointer to the buffer object bound to \c target in the
103848b8605Smrg *           specified context or \c NULL if \c target is invalid.
104848b8605Smrg */
105848b8605Smrgstatic inline struct gl_buffer_object **
106848b8605Smrgget_buffer_target(struct gl_context *ctx, GLenum target)
107848b8605Smrg{
108848b8605Smrg   /* Other targets are only supported in desktop OpenGL and OpenGL ES 3.0.
109848b8605Smrg    */
110848b8605Smrg   if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)
111848b8605Smrg       && target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER)
112848b8605Smrg      return NULL;
113848b8605Smrg
114848b8605Smrg   switch (target) {
115848b8605Smrg   case GL_ARRAY_BUFFER_ARB:
116b8e80941Smrg      if (ctx->Array.ArrayBufferObj)
117b8e80941Smrg         ctx->Array.ArrayBufferObj->UsageHistory |= USAGE_ARRAY_BUFFER;
118848b8605Smrg      return &ctx->Array.ArrayBufferObj;
119848b8605Smrg   case GL_ELEMENT_ARRAY_BUFFER_ARB:
120b8e80941Smrg      if (ctx->Array.VAO->IndexBufferObj)
121b8e80941Smrg         ctx->Array.VAO->IndexBufferObj->UsageHistory
122b8e80941Smrg            |= USAGE_ELEMENT_ARRAY_BUFFER;
123848b8605Smrg      return &ctx->Array.VAO->IndexBufferObj;
124848b8605Smrg   case GL_PIXEL_PACK_BUFFER_EXT:
125848b8605Smrg      return &ctx->Pack.BufferObj;
126848b8605Smrg   case GL_PIXEL_UNPACK_BUFFER_EXT:
127848b8605Smrg      return &ctx->Unpack.BufferObj;
128848b8605Smrg   case GL_COPY_READ_BUFFER:
129848b8605Smrg      return &ctx->CopyReadBuffer;
130848b8605Smrg   case GL_COPY_WRITE_BUFFER:
131848b8605Smrg      return &ctx->CopyWriteBuffer;
132b8e80941Smrg   case GL_QUERY_BUFFER:
133b8e80941Smrg      if (_mesa_has_ARB_query_buffer_object(ctx))
134b8e80941Smrg         return &ctx->QueryBuffer;
135b8e80941Smrg      break;
136848b8605Smrg   case GL_DRAW_INDIRECT_BUFFER:
137b8e80941Smrg      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_draw_indirect) ||
138b8e80941Smrg           _mesa_is_gles31(ctx)) {
139848b8605Smrg         return &ctx->DrawIndirectBuffer;
140848b8605Smrg      }
141848b8605Smrg      break;
142b8e80941Smrg   case GL_PARAMETER_BUFFER_ARB:
143b8e80941Smrg      if (_mesa_has_ARB_indirect_parameters(ctx)) {
144b8e80941Smrg         return &ctx->ParameterBuffer;
145b8e80941Smrg      }
146b8e80941Smrg      break;
147b8e80941Smrg   case GL_DISPATCH_INDIRECT_BUFFER:
148b8e80941Smrg      if (_mesa_has_compute_shaders(ctx)) {
149b8e80941Smrg         return &ctx->DispatchIndirectBuffer;
150b8e80941Smrg      }
151b8e80941Smrg      break;
152848b8605Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
153848b8605Smrg      if (ctx->Extensions.EXT_transform_feedback) {
154848b8605Smrg         return &ctx->TransformFeedback.CurrentBuffer;
155848b8605Smrg      }
156848b8605Smrg      break;
157848b8605Smrg   case GL_TEXTURE_BUFFER:
158b8e80941Smrg      if (_mesa_has_ARB_texture_buffer_object(ctx) ||
159b8e80941Smrg          _mesa_has_OES_texture_buffer(ctx)) {
160848b8605Smrg         return &ctx->Texture.BufferObject;
161848b8605Smrg      }
162848b8605Smrg      break;
163848b8605Smrg   case GL_UNIFORM_BUFFER:
164848b8605Smrg      if (ctx->Extensions.ARB_uniform_buffer_object) {
165848b8605Smrg         return &ctx->UniformBuffer;
166848b8605Smrg      }
167848b8605Smrg      break;
168b8e80941Smrg   case GL_SHADER_STORAGE_BUFFER:
169b8e80941Smrg      if (ctx->Extensions.ARB_shader_storage_buffer_object) {
170b8e80941Smrg         return &ctx->ShaderStorageBuffer;
171b8e80941Smrg      }
172b8e80941Smrg      break;
173848b8605Smrg   case GL_ATOMIC_COUNTER_BUFFER:
174848b8605Smrg      if (ctx->Extensions.ARB_shader_atomic_counters) {
175848b8605Smrg         return &ctx->AtomicBuffer;
176848b8605Smrg      }
177848b8605Smrg      break;
178b8e80941Smrg   case GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD:
179b8e80941Smrg      if (ctx->Extensions.AMD_pinned_memory) {
180b8e80941Smrg         return &ctx->ExternalVirtualMemoryBuffer;
181b8e80941Smrg      }
182b8e80941Smrg      break;
183848b8605Smrg   default:
184848b8605Smrg      return NULL;
185848b8605Smrg   }
186848b8605Smrg   return NULL;
187848b8605Smrg}
188848b8605Smrg
189848b8605Smrg
190848b8605Smrg/**
191848b8605Smrg * Get the buffer object bound to the specified target in a GL context.
192848b8605Smrg * \param ctx  the GL context
193848b8605Smrg * \param target  the buffer object target to be retrieved.
194848b8605Smrg * \param error  the GL error to record if target is illegal.
195848b8605Smrg * \return   pointer to the buffer object bound to \c target in the
196848b8605Smrg *           specified context or \c NULL if \c target is invalid.
197848b8605Smrg */
198848b8605Smrgstatic inline struct gl_buffer_object *
199848b8605Smrgget_buffer(struct gl_context *ctx, const char *func, GLenum target,
200848b8605Smrg           GLenum error)
201848b8605Smrg{
202848b8605Smrg   struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
203848b8605Smrg
204848b8605Smrg   if (!bufObj) {
205848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
206848b8605Smrg      return NULL;
207848b8605Smrg   }
208848b8605Smrg
209848b8605Smrg   if (!_mesa_is_bufferobj(*bufObj)) {
210848b8605Smrg      _mesa_error(ctx, error, "%s(no buffer bound)", func);
211848b8605Smrg      return NULL;
212848b8605Smrg   }
213848b8605Smrg
214848b8605Smrg   return *bufObj;
215848b8605Smrg}
216848b8605Smrg
217848b8605Smrg
218848b8605Smrg/**
219848b8605Smrg * Convert a GLbitfield describing the mapped buffer access flags
220848b8605Smrg * into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
221848b8605Smrg */
222848b8605Smrgstatic GLenum
223848b8605Smrgsimplified_access_mode(struct gl_context *ctx, GLbitfield access)
224848b8605Smrg{
225848b8605Smrg   const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
226848b8605Smrg   if ((access & rwFlags) == rwFlags)
227848b8605Smrg      return GL_READ_WRITE;
228848b8605Smrg   if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
229848b8605Smrg      return GL_READ_ONLY;
230848b8605Smrg   if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
231848b8605Smrg      return GL_WRITE_ONLY;
232848b8605Smrg
233848b8605Smrg   /* Otherwise, AccessFlags is zero (the default state).
234848b8605Smrg    *
235848b8605Smrg    * Table 2.6 on page 31 (page 44 of the PDF) of the OpenGL 1.5 spec says:
236848b8605Smrg    *
237848b8605Smrg    * Name           Type  Initial Value  Legal Values
238848b8605Smrg    * ...            ...   ...            ...
239848b8605Smrg    * BUFFER_ACCESS  enum  READ_WRITE     READ_ONLY, WRITE_ONLY
240848b8605Smrg    *                                     READ_WRITE
241848b8605Smrg    *
242848b8605Smrg    * However, table 6.8 in the GL_OES_mapbuffer extension says:
243848b8605Smrg    *
244848b8605Smrg    * Get Value         Type Get Command          Value          Description
245848b8605Smrg    * ---------         ---- -----------          -----          -----------
246848b8605Smrg    * BUFFER_ACCESS_OES Z1   GetBufferParameteriv WRITE_ONLY_OES buffer map flag
247848b8605Smrg    *
248848b8605Smrg    * The difference is because GL_OES_mapbuffer only supports mapping buffers
249848b8605Smrg    * write-only.
250848b8605Smrg    */
251848b8605Smrg   assert(access == 0);
252848b8605Smrg
253848b8605Smrg   return _mesa_is_gles(ctx) ? GL_WRITE_ONLY : GL_READ_WRITE;
254848b8605Smrg}
255848b8605Smrg
256848b8605Smrg
257848b8605Smrg/**
258848b8605Smrg * Test if the buffer is mapped, and if so, if the mapped range overlaps the
259848b8605Smrg * given range.
260848b8605Smrg * The regions do not overlap if and only if the end of the given
261848b8605Smrg * region is before the mapped region or the start of the given region
262848b8605Smrg * is after the mapped region.
263848b8605Smrg *
264848b8605Smrg * \param obj     Buffer object target on which to operate.
265848b8605Smrg * \param offset  Offset of the first byte of the subdata range.
266848b8605Smrg * \param size    Size, in bytes, of the subdata range.
267848b8605Smrg * \return   true if ranges overlap, false otherwise
268848b8605Smrg *
269848b8605Smrg */
270848b8605Smrgstatic bool
271848b8605Smrgbufferobj_range_mapped(const struct gl_buffer_object *obj,
272848b8605Smrg                       GLintptr offset, GLsizeiptr size)
273848b8605Smrg{
274848b8605Smrg   if (_mesa_bufferobj_mapped(obj, MAP_USER)) {
275848b8605Smrg      const GLintptr end = offset + size;
276848b8605Smrg      const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset +
277848b8605Smrg                              obj->Mappings[MAP_USER].Length;
278848b8605Smrg
279848b8605Smrg      if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) {
280848b8605Smrg         return true;
281848b8605Smrg      }
282848b8605Smrg   }
283848b8605Smrg   return false;
284848b8605Smrg}
285848b8605Smrg
286848b8605Smrg
287848b8605Smrg/**
288848b8605Smrg * Tests the subdata range parameters and sets the GL error code for
289848b8605Smrg * \c glBufferSubDataARB, \c glGetBufferSubDataARB and
290848b8605Smrg * \c glClearBufferSubData.
291848b8605Smrg *
292848b8605Smrg * \param ctx     GL context.
293b8e80941Smrg * \param bufObj  The buffer object.
294848b8605Smrg * \param offset  Offset of the first byte of the subdata range.
295848b8605Smrg * \param size    Size, in bytes, of the subdata range.
296848b8605Smrg * \param mappedRange  If true, checks if an overlapping range is mapped.
297848b8605Smrg *                     If false, checks if buffer is mapped.
298848b8605Smrg * \param caller  Name of calling function for recording errors.
299b8e80941Smrg * \return   false if error, true otherwise
300848b8605Smrg *
301848b8605Smrg * \sa glBufferSubDataARB, glGetBufferSubDataARB, glClearBufferSubData
302848b8605Smrg */
303b8e80941Smrgstatic bool
304b8e80941Smrgbuffer_object_subdata_range_good(struct gl_context *ctx,
305b8e80941Smrg                                 const struct gl_buffer_object *bufObj,
306b8e80941Smrg                                 GLintptr offset, GLsizeiptr size,
307b8e80941Smrg                                 bool mappedRange, const char *caller)
308848b8605Smrg{
309848b8605Smrg   if (size < 0) {
310848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller);
311b8e80941Smrg      return false;
312848b8605Smrg   }
313848b8605Smrg
314848b8605Smrg   if (offset < 0) {
315848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller);
316b8e80941Smrg      return false;
317848b8605Smrg   }
318848b8605Smrg
319848b8605Smrg   if (offset + size > bufObj->Size) {
320848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
321848b8605Smrg                  "%s(offset %lu + size %lu > buffer size %lu)", caller,
322848b8605Smrg                  (unsigned long) offset,
323848b8605Smrg                  (unsigned long) size,
324848b8605Smrg                  (unsigned long) bufObj->Size);
325b8e80941Smrg      return false;
326848b8605Smrg   }
327848b8605Smrg
328848b8605Smrg   if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT)
329b8e80941Smrg      return true;
330848b8605Smrg
331848b8605Smrg   if (mappedRange) {
332848b8605Smrg      if (bufferobj_range_mapped(bufObj, offset, size)) {
333b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
334b8e80941Smrg                     "%s(range is mapped without persistent bit)",
335b8e80941Smrg                     caller);
336b8e80941Smrg         return false;
337848b8605Smrg      }
338848b8605Smrg   }
339848b8605Smrg   else {
340848b8605Smrg      if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
341b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
342b8e80941Smrg                     "%s(buffer is mapped without persistent bit)",
343b8e80941Smrg                     caller);
344b8e80941Smrg         return false;
345848b8605Smrg      }
346848b8605Smrg   }
347848b8605Smrg
348b8e80941Smrg   return true;
349848b8605Smrg}
350848b8605Smrg
351848b8605Smrg
352848b8605Smrg/**
353848b8605Smrg * Test the format and type parameters and set the GL error code for
354b8e80941Smrg * \c glClearBufferData, \c glClearNamedBufferData, \c glClearBufferSubData
355b8e80941Smrg * and \c glClearNamedBufferSubData.
356848b8605Smrg *
357848b8605Smrg * \param ctx             GL context.
358848b8605Smrg * \param internalformat  Format to which the data is to be converted.
359848b8605Smrg * \param format          Format of the supplied data.
360848b8605Smrg * \param type            Type of the supplied data.
361848b8605Smrg * \param caller          Name of calling function for recording errors.
362848b8605Smrg * \return   If internalformat, format and type are legal the mesa_format
363848b8605Smrg *           corresponding to internalformat, otherwise MESA_FORMAT_NONE.
364848b8605Smrg *
365b8e80941Smrg * \sa glClearBufferData, glClearNamedBufferData, glClearBufferSubData and
366b8e80941Smrg *     glClearNamedBufferSubData.
367848b8605Smrg */
368848b8605Smrgstatic mesa_format
369848b8605Smrgvalidate_clear_buffer_format(struct gl_context *ctx,
370848b8605Smrg                             GLenum internalformat,
371848b8605Smrg                             GLenum format, GLenum type,
372848b8605Smrg                             const char *caller)
373848b8605Smrg{
374848b8605Smrg   mesa_format mesaFormat;
375848b8605Smrg   GLenum errorFormatType;
376848b8605Smrg
377848b8605Smrg   mesaFormat = _mesa_validate_texbuffer_format(ctx, internalformat);
378848b8605Smrg   if (mesaFormat == MESA_FORMAT_NONE) {
379848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
380848b8605Smrg                  "%s(invalid internalformat)", caller);
381848b8605Smrg      return MESA_FORMAT_NONE;
382848b8605Smrg   }
383848b8605Smrg
384848b8605Smrg   /* NOTE: not mentioned in ARB_clear_buffer_object but according to
385848b8605Smrg    * EXT_texture_integer there is no conversion between integer and
386848b8605Smrg    * non-integer formats
387848b8605Smrg   */
388848b8605Smrg   if (_mesa_is_enum_format_signed_int(format) !=
389848b8605Smrg       _mesa_is_format_integer_color(mesaFormat)) {
390848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
391848b8605Smrg                  "%s(integer vs non-integer)", caller);
392848b8605Smrg      return MESA_FORMAT_NONE;
393848b8605Smrg   }
394848b8605Smrg
395848b8605Smrg   if (!_mesa_is_color_format(format)) {
396b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
397848b8605Smrg                  "%s(format is not a color format)", caller);
398848b8605Smrg      return MESA_FORMAT_NONE;
399848b8605Smrg   }
400848b8605Smrg
401848b8605Smrg   errorFormatType = _mesa_error_check_format_and_type(ctx, format, type);
402848b8605Smrg   if (errorFormatType != GL_NO_ERROR) {
403b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
404848b8605Smrg                  "%s(invalid format or type)", caller);
405848b8605Smrg      return MESA_FORMAT_NONE;
406848b8605Smrg   }
407848b8605Smrg
408848b8605Smrg   return mesaFormat;
409848b8605Smrg}
410848b8605Smrg
411848b8605Smrg
412848b8605Smrg/**
413848b8605Smrg * Convert user-specified clear value to the specified internal format.
414848b8605Smrg *
415848b8605Smrg * \param ctx             GL context.
416848b8605Smrg * \param internalformat  Format to which the data is converted.
417848b8605Smrg * \param clearValue      Points to the converted clear value.
418848b8605Smrg * \param format          Format of the supplied data.
419848b8605Smrg * \param type            Type of the supplied data.
420848b8605Smrg * \param data            Data which is to be converted to internalformat.
421848b8605Smrg * \param caller          Name of calling function for recording errors.
422848b8605Smrg * \return   true if data could be converted, false otherwise.
423848b8605Smrg *
424848b8605Smrg * \sa glClearBufferData, glClearBufferSubData
425848b8605Smrg */
426848b8605Smrgstatic bool
427848b8605Smrgconvert_clear_buffer_data(struct gl_context *ctx,
428848b8605Smrg                          mesa_format internalformat,
429848b8605Smrg                          GLubyte *clearValue, GLenum format, GLenum type,
430848b8605Smrg                          const GLvoid *data, const char *caller)
431848b8605Smrg{
432848b8605Smrg   GLenum internalformatBase = _mesa_get_format_base_format(internalformat);
433848b8605Smrg
434848b8605Smrg   if (_mesa_texstore(ctx, 1, internalformatBase, internalformat,
435848b8605Smrg                      0, &clearValue, 1, 1, 1,
436848b8605Smrg                      format, type, data, &ctx->Unpack)) {
437848b8605Smrg      return true;
438848b8605Smrg   }
439848b8605Smrg   else {
440848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
441848b8605Smrg      return false;
442848b8605Smrg   }
443848b8605Smrg}
444848b8605Smrg
445848b8605Smrg
446848b8605Smrg/**
447848b8605Smrg * Allocate and initialize a new buffer object.
448b8e80941Smrg *
449848b8605Smrg * Default callback for the \c dd_function_table::NewBufferObject() hook.
450848b8605Smrg */
451848b8605Smrgstatic struct gl_buffer_object *
452b8e80941Smrg_mesa_new_buffer_object(struct gl_context *ctx, GLuint name)
453848b8605Smrg{
454b8e80941Smrg   struct gl_buffer_object *obj = MALLOC_STRUCT(gl_buffer_object);
455b8e80941Smrg   if (!obj)
456b8e80941Smrg      return NULL;
457848b8605Smrg
458b8e80941Smrg   _mesa_initialize_buffer_object(ctx, obj, name);
459848b8605Smrg   return obj;
460848b8605Smrg}
461848b8605Smrg
462848b8605Smrg
463848b8605Smrg/**
464848b8605Smrg * Delete a buffer object.
465b8e80941Smrg *
466848b8605Smrg * Default callback for the \c dd_function_table::DeleteBuffer() hook.
467848b8605Smrg */
468b8e80941Smrgvoid
469848b8605Smrg_mesa_delete_buffer_object(struct gl_context *ctx,
470848b8605Smrg                           struct gl_buffer_object *bufObj)
471848b8605Smrg{
472848b8605Smrg   (void) ctx;
473848b8605Smrg
474b8e80941Smrg   vbo_delete_minmax_cache(bufObj);
475848b8605Smrg   _mesa_align_free(bufObj->Data);
476848b8605Smrg
477848b8605Smrg   /* assign strange values here to help w/ debugging */
478848b8605Smrg   bufObj->RefCount = -1000;
479848b8605Smrg   bufObj->Name = ~0;
480848b8605Smrg
481b8e80941Smrg   simple_mtx_destroy(&bufObj->MinMaxCacheMutex);
482848b8605Smrg   free(bufObj->Label);
483848b8605Smrg   free(bufObj);
484848b8605Smrg}
485848b8605Smrg
486848b8605Smrg
487848b8605Smrg
488848b8605Smrg/**
489848b8605Smrg * Set ptr to bufObj w/ reference counting.
490848b8605Smrg * This is normally only called from the _mesa_reference_buffer_object() macro
491848b8605Smrg * when there's a real pointer change.
492848b8605Smrg */
493848b8605Smrgvoid
494848b8605Smrg_mesa_reference_buffer_object_(struct gl_context *ctx,
495848b8605Smrg                               struct gl_buffer_object **ptr,
496848b8605Smrg                               struct gl_buffer_object *bufObj)
497848b8605Smrg{
498848b8605Smrg   if (*ptr) {
499848b8605Smrg      /* Unreference the old buffer */
500848b8605Smrg      struct gl_buffer_object *oldObj = *ptr;
501848b8605Smrg
502b8e80941Smrg      if (p_atomic_dec_zero(&oldObj->RefCount)) {
503b8e80941Smrg	 assert(ctx->Driver.DeleteBuffer);
504848b8605Smrg         ctx->Driver.DeleteBuffer(ctx, oldObj);
505848b8605Smrg      }
506848b8605Smrg
507848b8605Smrg      *ptr = NULL;
508848b8605Smrg   }
509b8e80941Smrg   assert(!*ptr);
510848b8605Smrg
511848b8605Smrg   if (bufObj) {
512848b8605Smrg      /* reference new buffer */
513b8e80941Smrg      p_atomic_inc(&bufObj->RefCount);
514b8e80941Smrg      *ptr = bufObj;
515b8e80941Smrg   }
516b8e80941Smrg}
517b8e80941Smrg
518b8e80941Smrg
519b8e80941Smrg/**
520b8e80941Smrg * Get the value of MESA_NO_MINMAX_CACHE.
521b8e80941Smrg */
522b8e80941Smrgstatic bool
523b8e80941Smrgget_no_minmax_cache()
524b8e80941Smrg{
525b8e80941Smrg   static bool read = false;
526b8e80941Smrg   static bool disable = false;
527b8e80941Smrg
528b8e80941Smrg   if (!read) {
529b8e80941Smrg      disable = env_var_as_boolean("MESA_NO_MINMAX_CACHE", false);
530b8e80941Smrg      read = true;
531848b8605Smrg   }
532b8e80941Smrg
533b8e80941Smrg   return disable;
534848b8605Smrg}
535848b8605Smrg
536848b8605Smrg
537848b8605Smrg/**
538848b8605Smrg * Initialize a buffer object to default values.
539848b8605Smrg */
540848b8605Smrgvoid
541b8e80941Smrg_mesa_initialize_buffer_object(struct gl_context *ctx,
542b8e80941Smrg                               struct gl_buffer_object *obj,
543b8e80941Smrg                               GLuint name)
544848b8605Smrg{
545848b8605Smrg   memset(obj, 0, sizeof(struct gl_buffer_object));
546848b8605Smrg   obj->RefCount = 1;
547848b8605Smrg   obj->Name = name;
548848b8605Smrg   obj->Usage = GL_STATIC_DRAW_ARB;
549b8e80941Smrg
550b8e80941Smrg   simple_mtx_init(&obj->MinMaxCacheMutex, mtx_plain);
551b8e80941Smrg   if (get_no_minmax_cache())
552b8e80941Smrg      obj->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
553848b8605Smrg}
554848b8605Smrg
555848b8605Smrg
556848b8605Smrg
557848b8605Smrg/**
558848b8605Smrg * Callback called from _mesa_HashWalk()
559848b8605Smrg */
560848b8605Smrgstatic void
561848b8605Smrgcount_buffer_size(GLuint key, void *data, void *userData)
562848b8605Smrg{
563848b8605Smrg   const struct gl_buffer_object *bufObj =
564848b8605Smrg      (const struct gl_buffer_object *) data;
565848b8605Smrg   GLuint *total = (GLuint *) userData;
566848b8605Smrg
567b8e80941Smrg   (void) key;
568848b8605Smrg   *total = *total + bufObj->Size;
569848b8605Smrg}
570848b8605Smrg
571848b8605Smrg
572848b8605Smrg/**
573848b8605Smrg * Compute total size (in bytes) of all buffer objects for the given context.
574848b8605Smrg * For debugging purposes.
575848b8605Smrg */
576848b8605SmrgGLuint
577848b8605Smrg_mesa_total_buffer_object_memory(struct gl_context *ctx)
578848b8605Smrg{
579848b8605Smrg   GLuint total = 0;
580848b8605Smrg
581848b8605Smrg   _mesa_HashWalk(ctx->Shared->BufferObjects, count_buffer_size, &total);
582848b8605Smrg
583848b8605Smrg   return total;
584848b8605Smrg}
585848b8605Smrg
586848b8605Smrg
587848b8605Smrg/**
588848b8605Smrg * Allocate space for and store data in a buffer object.  Any data that was
589848b8605Smrg * previously stored in the buffer object is lost.  If \c data is \c NULL,
590848b8605Smrg * memory will be allocated, but no copy will occur.
591848b8605Smrg *
592848b8605Smrg * This is the default callback for \c dd_function_table::BufferData()
593848b8605Smrg * Note that all GL error checking will have been done already.
594848b8605Smrg *
595848b8605Smrg * \param ctx     GL context.
596848b8605Smrg * \param target  Buffer object target on which to operate.
597848b8605Smrg * \param size    Size, in bytes, of the new data store.
598848b8605Smrg * \param data    Pointer to the data to store in the buffer object.  This
599848b8605Smrg *                pointer may be \c NULL.
600848b8605Smrg * \param usage   Hints about how the data will be used.
601848b8605Smrg * \param bufObj  Object to be used.
602848b8605Smrg *
603848b8605Smrg * \return GL_TRUE for success, GL_FALSE for failure
604848b8605Smrg * \sa glBufferDataARB, dd_function_table::BufferData.
605848b8605Smrg */
606848b8605Smrgstatic GLboolean
607b8e80941Smrgbuffer_data_fallback(struct gl_context *ctx, GLenum target, GLsizeiptrARB size,
608b8e80941Smrg                     const GLvoid *data, GLenum usage, GLenum storageFlags,
609b8e80941Smrg                     struct gl_buffer_object *bufObj)
610848b8605Smrg{
611848b8605Smrg   void * new_data;
612848b8605Smrg
613848b8605Smrg   (void) target;
614848b8605Smrg
615848b8605Smrg   _mesa_align_free( bufObj->Data );
616848b8605Smrg
617848b8605Smrg   new_data = _mesa_align_malloc( size, ctx->Const.MinMapBufferAlignment );
618848b8605Smrg   if (new_data) {
619848b8605Smrg      bufObj->Data = (GLubyte *) new_data;
620848b8605Smrg      bufObj->Size = size;
621848b8605Smrg      bufObj->Usage = usage;
622848b8605Smrg      bufObj->StorageFlags = storageFlags;
623848b8605Smrg
624848b8605Smrg      if (data) {
625848b8605Smrg	 memcpy( bufObj->Data, data, size );
626848b8605Smrg      }
627848b8605Smrg
628848b8605Smrg      return GL_TRUE;
629848b8605Smrg   }
630848b8605Smrg   else {
631848b8605Smrg      return GL_FALSE;
632848b8605Smrg   }
633848b8605Smrg}
634848b8605Smrg
635848b8605Smrg
636848b8605Smrg/**
637848b8605Smrg * Replace data in a subrange of buffer object.  If the data range
638848b8605Smrg * specified by \c size + \c offset extends beyond the end of the buffer or
639848b8605Smrg * if \c data is \c NULL, no copy is performed.
640848b8605Smrg *
641848b8605Smrg * This is the default callback for \c dd_function_table::BufferSubData()
642848b8605Smrg * Note that all GL error checking will have been done already.
643848b8605Smrg *
644848b8605Smrg * \param ctx     GL context.
645848b8605Smrg * \param offset  Offset of the first byte to be modified.
646848b8605Smrg * \param size    Size, in bytes, of the data range.
647848b8605Smrg * \param data    Pointer to the data to store in the buffer object.
648848b8605Smrg * \param bufObj  Object to be used.
649848b8605Smrg *
650848b8605Smrg * \sa glBufferSubDataARB, dd_function_table::BufferSubData.
651848b8605Smrg */
652848b8605Smrgstatic void
653b8e80941Smrgbuffer_sub_data_fallback(struct gl_context *ctx, GLintptrARB offset,
654b8e80941Smrg                         GLsizeiptrARB size, const GLvoid *data,
655b8e80941Smrg                         struct gl_buffer_object *bufObj)
656848b8605Smrg{
657848b8605Smrg   (void) ctx;
658848b8605Smrg
659848b8605Smrg   /* this should have been caught in _mesa_BufferSubData() */
660b8e80941Smrg   assert(size + offset <= bufObj->Size);
661848b8605Smrg
662848b8605Smrg   if (bufObj->Data) {
663848b8605Smrg      memcpy( (GLubyte *) bufObj->Data + offset, data, size );
664848b8605Smrg   }
665848b8605Smrg}
666848b8605Smrg
667848b8605Smrg
668848b8605Smrg/**
669848b8605Smrg * Retrieve data from a subrange of buffer object.  If the data range
670848b8605Smrg * specified by \c size + \c offset extends beyond the end of the buffer or
671848b8605Smrg * if \c data is \c NULL, no copy is performed.
672848b8605Smrg *
673848b8605Smrg * This is the default callback for \c dd_function_table::GetBufferSubData()
674848b8605Smrg * Note that all GL error checking will have been done already.
675848b8605Smrg *
676848b8605Smrg * \param ctx     GL context.
677848b8605Smrg * \param target  Buffer object target on which to operate.
678848b8605Smrg * \param offset  Offset of the first byte to be fetched.
679848b8605Smrg * \param size    Size, in bytes, of the data range.
680848b8605Smrg * \param data    Destination for data
681848b8605Smrg * \param bufObj  Object to be used.
682848b8605Smrg *
683848b8605Smrg * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
684848b8605Smrg */
685848b8605Smrgstatic void
686b8e80941Smrgbuffer_get_subdata(struct gl_context *ctx, GLintptrARB offset,
687b8e80941Smrg                   GLsizeiptrARB size, GLvoid *data,
688b8e80941Smrg                   struct gl_buffer_object *bufObj )
689848b8605Smrg{
690848b8605Smrg   (void) ctx;
691848b8605Smrg
692848b8605Smrg   if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) {
693848b8605Smrg      memcpy( data, (GLubyte *) bufObj->Data + offset, size );
694848b8605Smrg   }
695848b8605Smrg}
696848b8605Smrg
697848b8605Smrg
698848b8605Smrg/**
699848b8605Smrg * Clear a subrange of the buffer object with copies of the supplied data.
700848b8605Smrg * If data is NULL the buffer is filled with zeros.
701848b8605Smrg *
702848b8605Smrg * This is the default callback for \c dd_function_table::ClearBufferSubData()
703848b8605Smrg * Note that all GL error checking will have been done already.
704848b8605Smrg *
705848b8605Smrg * \param ctx             GL context.
706848b8605Smrg * \param offset          Offset of the first byte to be cleared.
707848b8605Smrg * \param size            Size, in bytes, of the to be cleared range.
708848b8605Smrg * \param clearValue      Source of the data.
709848b8605Smrg * \param clearValueSize  Size, in bytes, of the supplied data.
710848b8605Smrg * \param bufObj          Object to be cleared.
711848b8605Smrg *
712848b8605Smrg * \sa glClearBufferSubData, glClearBufferData and
713848b8605Smrg * dd_function_table::ClearBufferSubData.
714848b8605Smrg */
715848b8605Smrgvoid
716b8e80941Smrg_mesa_ClearBufferSubData_sw(struct gl_context *ctx,
717b8e80941Smrg                            GLintptr offset, GLsizeiptr size,
718b8e80941Smrg                            const GLvoid *clearValue,
719b8e80941Smrg                            GLsizeiptr clearValueSize,
720b8e80941Smrg                            struct gl_buffer_object *bufObj)
721848b8605Smrg{
722848b8605Smrg   GLsizeiptr i;
723848b8605Smrg   GLubyte *dest;
724848b8605Smrg
725b8e80941Smrg   assert(ctx->Driver.MapBufferRange);
726848b8605Smrg   dest = ctx->Driver.MapBufferRange(ctx, offset, size,
727848b8605Smrg                                     GL_MAP_WRITE_BIT |
728848b8605Smrg                                     GL_MAP_INVALIDATE_RANGE_BIT,
729848b8605Smrg                                     bufObj, MAP_INTERNAL);
730848b8605Smrg
731848b8605Smrg   if (!dest) {
732848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data");
733848b8605Smrg      return;
734848b8605Smrg   }
735848b8605Smrg
736848b8605Smrg   if (clearValue == NULL) {
737848b8605Smrg      /* Clear with zeros, per the spec */
738848b8605Smrg      memset(dest, 0, size);
739848b8605Smrg      ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL);
740848b8605Smrg      return;
741848b8605Smrg   }
742848b8605Smrg
743848b8605Smrg   for (i = 0; i < size/clearValueSize; ++i) {
744848b8605Smrg      memcpy(dest, clearValue, clearValueSize);
745848b8605Smrg      dest += clearValueSize;
746848b8605Smrg   }
747848b8605Smrg
748848b8605Smrg   ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL);
749848b8605Smrg}
750848b8605Smrg
751848b8605Smrg
752848b8605Smrg/**
753848b8605Smrg * Default fallback for \c dd_function_table::MapBufferRange().
754848b8605Smrg * Called via glMapBufferRange().
755848b8605Smrg */
756848b8605Smrgstatic void *
757b8e80941Smrgmap_buffer_range_fallback(struct gl_context *ctx, GLintptr offset,
758b8e80941Smrg                          GLsizeiptr length, GLbitfield access,
759b8e80941Smrg                          struct gl_buffer_object *bufObj,
760b8e80941Smrg                          gl_map_buffer_index index)
761848b8605Smrg{
762848b8605Smrg   (void) ctx;
763848b8605Smrg   assert(!_mesa_bufferobj_mapped(bufObj, index));
764848b8605Smrg   /* Just return a direct pointer to the data */
765848b8605Smrg   bufObj->Mappings[index].Pointer = bufObj->Data + offset;
766848b8605Smrg   bufObj->Mappings[index].Length = length;
767848b8605Smrg   bufObj->Mappings[index].Offset = offset;
768848b8605Smrg   bufObj->Mappings[index].AccessFlags = access;
769848b8605Smrg   return bufObj->Mappings[index].Pointer;
770848b8605Smrg}
771848b8605Smrg
772848b8605Smrg
773848b8605Smrg/**
774848b8605Smrg * Default fallback for \c dd_function_table::FlushMappedBufferRange().
775848b8605Smrg * Called via glFlushMappedBufferRange().
776848b8605Smrg */
777848b8605Smrgstatic void
778b8e80941Smrgflush_mapped_buffer_range_fallback(struct gl_context *ctx,
779b8e80941Smrg                                   GLintptr offset, GLsizeiptr length,
780b8e80941Smrg                                   struct gl_buffer_object *obj,
781b8e80941Smrg                                   gl_map_buffer_index index)
782848b8605Smrg{
783848b8605Smrg   (void) ctx;
784848b8605Smrg   (void) offset;
785848b8605Smrg   (void) length;
786848b8605Smrg   (void) obj;
787b8e80941Smrg   (void) index;
788848b8605Smrg   /* no-op */
789848b8605Smrg}
790848b8605Smrg
791848b8605Smrg
792848b8605Smrg/**
793b8e80941Smrg * Default callback for \c dd_function_table::UnmapBuffer().
794848b8605Smrg *
795848b8605Smrg * The input parameters will have been already tested for errors.
796848b8605Smrg *
797848b8605Smrg * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer
798848b8605Smrg */
799848b8605Smrgstatic GLboolean
800b8e80941Smrgunmap_buffer_fallback(struct gl_context *ctx, struct gl_buffer_object *bufObj,
801b8e80941Smrg                      gl_map_buffer_index index)
802848b8605Smrg{
803848b8605Smrg   (void) ctx;
804848b8605Smrg   /* XXX we might assert here that bufObj->Pointer is non-null */
805848b8605Smrg   bufObj->Mappings[index].Pointer = NULL;
806848b8605Smrg   bufObj->Mappings[index].Length = 0;
807848b8605Smrg   bufObj->Mappings[index].Offset = 0;
808848b8605Smrg   bufObj->Mappings[index].AccessFlags = 0x0;
809848b8605Smrg   return GL_TRUE;
810848b8605Smrg}
811848b8605Smrg
812848b8605Smrg
813848b8605Smrg/**
814848b8605Smrg * Default fallback for \c dd_function_table::CopyBufferSubData().
815848b8605Smrg * Called via glCopyBufferSubData().
816848b8605Smrg */
817848b8605Smrgstatic void
818b8e80941Smrgcopy_buffer_sub_data_fallback(struct gl_context *ctx,
819b8e80941Smrg                              struct gl_buffer_object *src,
820b8e80941Smrg                              struct gl_buffer_object *dst,
821b8e80941Smrg                              GLintptr readOffset, GLintptr writeOffset,
822b8e80941Smrg                              GLsizeiptr size)
823848b8605Smrg{
824848b8605Smrg   GLubyte *srcPtr, *dstPtr;
825848b8605Smrg
826848b8605Smrg   if (src == dst) {
827848b8605Smrg      srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size,
828848b8605Smrg						   GL_MAP_READ_BIT |
829848b8605Smrg						   GL_MAP_WRITE_BIT, src,
830848b8605Smrg                                                   MAP_INTERNAL);
831848b8605Smrg
832848b8605Smrg      if (!srcPtr)
833848b8605Smrg	 return;
834848b8605Smrg
835848b8605Smrg      srcPtr += readOffset;
836848b8605Smrg      dstPtr += writeOffset;
837848b8605Smrg   } else {
838848b8605Smrg      srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size,
839848b8605Smrg					  GL_MAP_READ_BIT, src,
840848b8605Smrg                                          MAP_INTERNAL);
841848b8605Smrg      dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size,
842848b8605Smrg					  (GL_MAP_WRITE_BIT |
843848b8605Smrg					   GL_MAP_INVALIDATE_RANGE_BIT), dst,
844848b8605Smrg                                          MAP_INTERNAL);
845848b8605Smrg   }
846848b8605Smrg
847848b8605Smrg   /* Note: the src and dst regions will never overlap.  Trying to do so
848848b8605Smrg    * would generate GL_INVALID_VALUE earlier.
849848b8605Smrg    */
850848b8605Smrg   if (srcPtr && dstPtr)
851848b8605Smrg      memcpy(dstPtr, srcPtr, size);
852848b8605Smrg
853848b8605Smrg   ctx->Driver.UnmapBuffer(ctx, src, MAP_INTERNAL);
854848b8605Smrg   if (dst != src)
855848b8605Smrg      ctx->Driver.UnmapBuffer(ctx, dst, MAP_INTERNAL);
856848b8605Smrg}
857848b8605Smrg
858848b8605Smrg
859848b8605Smrg
860848b8605Smrg/**
861848b8605Smrg * Initialize the state associated with buffer objects
862848b8605Smrg */
863848b8605Smrgvoid
864848b8605Smrg_mesa_init_buffer_objects( struct gl_context *ctx )
865848b8605Smrg{
866848b8605Smrg   GLuint i;
867848b8605Smrg
868848b8605Smrg   memset(&DummyBufferObject, 0, sizeof(DummyBufferObject));
869b8e80941Smrg   simple_mtx_init(&DummyBufferObject.MinMaxCacheMutex, mtx_plain);
870848b8605Smrg   DummyBufferObject.RefCount = 1000*1000*1000; /* never delete */
871848b8605Smrg
872848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj,
873848b8605Smrg                                 ctx->Shared->NullBufferObj);
874848b8605Smrg
875848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer,
876848b8605Smrg                                 ctx->Shared->NullBufferObj);
877848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer,
878848b8605Smrg                                 ctx->Shared->NullBufferObj);
879848b8605Smrg
880848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer,
881848b8605Smrg				 ctx->Shared->NullBufferObj);
882848b8605Smrg
883b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer,
884b8e80941Smrg                                 ctx->Shared->NullBufferObj);
885b8e80941Smrg
886848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer,
887848b8605Smrg				 ctx->Shared->NullBufferObj);
888848b8605Smrg
889848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer,
890848b8605Smrg				 ctx->Shared->NullBufferObj);
891848b8605Smrg
892b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->ParameterBuffer,
893b8e80941Smrg				 ctx->Shared->NullBufferObj);
894b8e80941Smrg
895b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->DispatchIndirectBuffer,
896b8e80941Smrg				 ctx->Shared->NullBufferObj);
897b8e80941Smrg
898b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->QueryBuffer,
899b8e80941Smrg                                 ctx->Shared->NullBufferObj);
900b8e80941Smrg
901848b8605Smrg   for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
902848b8605Smrg      _mesa_reference_buffer_object(ctx,
903848b8605Smrg				    &ctx->UniformBufferBindings[i].BufferObject,
904848b8605Smrg				    ctx->Shared->NullBufferObj);
905848b8605Smrg      ctx->UniformBufferBindings[i].Offset = -1;
906848b8605Smrg      ctx->UniformBufferBindings[i].Size = -1;
907848b8605Smrg   }
908848b8605Smrg
909b8e80941Smrg   for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) {
910b8e80941Smrg      _mesa_reference_buffer_object(ctx,
911b8e80941Smrg                                    &ctx->ShaderStorageBufferBindings[i].BufferObject,
912b8e80941Smrg                                    ctx->Shared->NullBufferObj);
913b8e80941Smrg      ctx->ShaderStorageBufferBindings[i].Offset = -1;
914b8e80941Smrg      ctx->ShaderStorageBufferBindings[i].Size = -1;
915b8e80941Smrg   }
916b8e80941Smrg
917848b8605Smrg   for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) {
918848b8605Smrg      _mesa_reference_buffer_object(ctx,
919848b8605Smrg				    &ctx->AtomicBufferBindings[i].BufferObject,
920848b8605Smrg				    ctx->Shared->NullBufferObj);
921b8e80941Smrg      ctx->AtomicBufferBindings[i].Offset = 0;
922b8e80941Smrg      ctx->AtomicBufferBindings[i].Size = 0;
923848b8605Smrg   }
924848b8605Smrg}
925848b8605Smrg
926848b8605Smrg
927848b8605Smrgvoid
928848b8605Smrg_mesa_free_buffer_objects( struct gl_context *ctx )
929848b8605Smrg{
930848b8605Smrg   GLuint i;
931848b8605Smrg
932848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->Array.ArrayBufferObj, NULL);
933848b8605Smrg
934848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->CopyReadBuffer, NULL);
935848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->CopyWriteBuffer, NULL);
936848b8605Smrg
937848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, NULL);
938848b8605Smrg
939b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, NULL);
940b8e80941Smrg
941848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, NULL);
942848b8605Smrg
943848b8605Smrg   _mesa_reference_buffer_object(ctx, &ctx->DrawIndirectBuffer, NULL);
944848b8605Smrg
945b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->ParameterBuffer, NULL);
946b8e80941Smrg
947b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->DispatchIndirectBuffer, NULL);
948b8e80941Smrg
949b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->QueryBuffer, NULL);
950b8e80941Smrg
951848b8605Smrg   for (i = 0; i < MAX_COMBINED_UNIFORM_BUFFERS; i++) {
952848b8605Smrg      _mesa_reference_buffer_object(ctx,
953848b8605Smrg				    &ctx->UniformBufferBindings[i].BufferObject,
954848b8605Smrg				    NULL);
955848b8605Smrg   }
956848b8605Smrg
957b8e80941Smrg   for (i = 0; i < MAX_COMBINED_SHADER_STORAGE_BUFFERS; i++) {
958b8e80941Smrg      _mesa_reference_buffer_object(ctx,
959b8e80941Smrg                                    &ctx->ShaderStorageBufferBindings[i].BufferObject,
960b8e80941Smrg                                    NULL);
961b8e80941Smrg   }
962b8e80941Smrg
963848b8605Smrg   for (i = 0; i < MAX_COMBINED_ATOMIC_BUFFERS; i++) {
964848b8605Smrg      _mesa_reference_buffer_object(ctx,
965848b8605Smrg				    &ctx->AtomicBufferBindings[i].BufferObject,
966848b8605Smrg				    NULL);
967848b8605Smrg   }
968848b8605Smrg
969848b8605Smrg}
970848b8605Smrg
971848b8605Smrgbool
972848b8605Smrg_mesa_handle_bind_buffer_gen(struct gl_context *ctx,
973848b8605Smrg                             GLuint buffer,
974848b8605Smrg                             struct gl_buffer_object **buf_handle,
975848b8605Smrg                             const char *caller)
976848b8605Smrg{
977848b8605Smrg   struct gl_buffer_object *buf = *buf_handle;
978848b8605Smrg
979b8e80941Smrg   if (!buf && (ctx->API == API_OPENGL_CORE)) {
980848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller);
981848b8605Smrg      return false;
982848b8605Smrg   }
983848b8605Smrg
984848b8605Smrg   if (!buf || buf == &DummyBufferObject) {
985848b8605Smrg      /* If this is a new buffer object id, or one which was generated but
986848b8605Smrg       * never used before, allocate a buffer object now.
987848b8605Smrg       */
988b8e80941Smrg      buf = ctx->Driver.NewBufferObject(ctx, buffer);
989848b8605Smrg      if (!buf) {
990848b8605Smrg	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
991848b8605Smrg	 return false;
992848b8605Smrg      }
993848b8605Smrg      _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf);
994848b8605Smrg      *buf_handle = buf;
995848b8605Smrg   }
996848b8605Smrg
997848b8605Smrg   return true;
998848b8605Smrg}
999848b8605Smrg
1000848b8605Smrg/**
1001848b8605Smrg * Bind the specified target to buffer for the specified context.
1002848b8605Smrg * Called by glBindBuffer() and other functions.
1003848b8605Smrg */
1004848b8605Smrgstatic void
1005b8e80941Smrgbind_buffer_object(struct gl_context *ctx,
1006b8e80941Smrg                   struct gl_buffer_object **bindTarget, GLuint buffer)
1007848b8605Smrg{
1008848b8605Smrg   struct gl_buffer_object *oldBufObj;
1009848b8605Smrg   struct gl_buffer_object *newBufObj = NULL;
1010848b8605Smrg
1011b8e80941Smrg   assert(bindTarget);
1012848b8605Smrg
1013848b8605Smrg   /* Get pointer to old buffer object (to be unbound) */
1014848b8605Smrg   oldBufObj = *bindTarget;
1015848b8605Smrg   if (oldBufObj && oldBufObj->Name == buffer && !oldBufObj->DeletePending)
1016848b8605Smrg      return;   /* rebinding the same buffer object- no change */
1017848b8605Smrg
1018848b8605Smrg   /*
1019848b8605Smrg    * Get pointer to new buffer object (newBufObj)
1020848b8605Smrg    */
1021848b8605Smrg   if (buffer == 0) {
1022848b8605Smrg      /* The spec says there's not a buffer object named 0, but we use
1023848b8605Smrg       * one internally because it simplifies things.
1024848b8605Smrg       */
1025848b8605Smrg      newBufObj = ctx->Shared->NullBufferObj;
1026848b8605Smrg   }
1027848b8605Smrg   else {
1028848b8605Smrg      /* non-default buffer object */
1029848b8605Smrg      newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
1030b8e80941Smrg      if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
1031848b8605Smrg                                        &newBufObj, "glBindBuffer"))
1032848b8605Smrg         return;
1033848b8605Smrg   }
1034b8e80941Smrg
1035b8e80941Smrg   /* record usage history */
1036b8e80941Smrg   if (bindTarget == &ctx->Pack.BufferObj) {
1037b8e80941Smrg      newBufObj->UsageHistory |= USAGE_PIXEL_PACK_BUFFER;
1038b8e80941Smrg   }
1039b8e80941Smrg
1040848b8605Smrg   /* bind new buffer */
1041848b8605Smrg   _mesa_reference_buffer_object(ctx, bindTarget, newBufObj);
1042848b8605Smrg}
1043848b8605Smrg
1044848b8605Smrg
1045848b8605Smrg/**
1046848b8605Smrg * Update the default buffer objects in the given context to reference those
1047b8e80941Smrg * specified in the shared state and release those referencing the old
1048848b8605Smrg * shared state.
1049848b8605Smrg */
1050848b8605Smrgvoid
1051848b8605Smrg_mesa_update_default_objects_buffer_objects(struct gl_context *ctx)
1052848b8605Smrg{
1053848b8605Smrg   /* Bind the NullBufferObj to remove references to those
1054848b8605Smrg    * in the shared context hash table.
1055848b8605Smrg    */
1056b8e80941Smrg   bind_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 0);
1057b8e80941Smrg   bind_buffer_object(ctx, &ctx->Array.VAO->IndexBufferObj, 0);
1058b8e80941Smrg   bind_buffer_object(ctx, &ctx->Pack.BufferObj, 0);
1059b8e80941Smrg   bind_buffer_object(ctx, &ctx->Unpack.BufferObj, 0);
1060848b8605Smrg}
1061848b8605Smrg
1062848b8605Smrg
1063848b8605Smrg
1064848b8605Smrg/**
1065848b8605Smrg * Return the gl_buffer_object for the given ID.
1066848b8605Smrg * Always return NULL for ID 0.
1067848b8605Smrg */
1068848b8605Smrgstruct gl_buffer_object *
1069848b8605Smrg_mesa_lookup_bufferobj(struct gl_context *ctx, GLuint buffer)
1070848b8605Smrg{
1071848b8605Smrg   if (buffer == 0)
1072848b8605Smrg      return NULL;
1073848b8605Smrg   else
1074848b8605Smrg      return (struct gl_buffer_object *)
1075848b8605Smrg         _mesa_HashLookup(ctx->Shared->BufferObjects, buffer);
1076848b8605Smrg}
1077848b8605Smrg
1078848b8605Smrg
1079848b8605Smrgstruct gl_buffer_object *
1080848b8605Smrg_mesa_lookup_bufferobj_locked(struct gl_context *ctx, GLuint buffer)
1081848b8605Smrg{
1082b8e80941Smrg   if (buffer == 0)
1083b8e80941Smrg      return NULL;
1084b8e80941Smrg   else
1085b8e80941Smrg      return (struct gl_buffer_object *)
1086b8e80941Smrg         _mesa_HashLookupLocked(ctx->Shared->BufferObjects, buffer);
1087848b8605Smrg}
1088848b8605Smrg
1089b8e80941Smrg/**
1090b8e80941Smrg * A convenience function for direct state access functions that throws
1091b8e80941Smrg * GL_INVALID_OPERATION if buffer is not the name of an existing
1092b8e80941Smrg * buffer object.
1093b8e80941Smrg */
1094b8e80941Smrgstruct gl_buffer_object *
1095b8e80941Smrg_mesa_lookup_bufferobj_err(struct gl_context *ctx, GLuint buffer,
1096b8e80941Smrg                           const char *caller)
1097848b8605Smrg{
1098b8e80941Smrg   struct gl_buffer_object *bufObj;
1099848b8605Smrg
1100b8e80941Smrg   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1101b8e80941Smrg   if (!bufObj || bufObj == &DummyBufferObject) {
1102b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1103b8e80941Smrg                  "%s(non-existent buffer object %u)", caller, buffer);
1104b8e80941Smrg      return NULL;
1105b8e80941Smrg   }
1106848b8605Smrg
1107b8e80941Smrg   return bufObj;
1108848b8605Smrg}
1109848b8605Smrg
1110848b8605Smrg
1111848b8605Smrg/**
1112848b8605Smrg * Look up a buffer object for a multi-bind function.
1113848b8605Smrg *
1114848b8605Smrg * Unlike _mesa_lookup_bufferobj(), this function also takes care
1115848b8605Smrg * of generating an error if the buffer ID is not zero or the name
1116848b8605Smrg * of an existing buffer object.
1117848b8605Smrg *
1118848b8605Smrg * If the buffer ID refers to an existing buffer object, a pointer
1119848b8605Smrg * to the buffer object is returned.  If the ID is zero, a pointer
1120848b8605Smrg * to the shared NullBufferObj is returned.  If the ID is not zero
1121848b8605Smrg * and does not refer to a valid buffer object, this function
1122848b8605Smrg * returns NULL.
1123848b8605Smrg *
1124848b8605Smrg * This function assumes that the caller has already locked the
1125b8e80941Smrg * hash table mutex by calling
1126b8e80941Smrg * _mesa_HashLockMutex(ctx->Shared->BufferObjects).
1127848b8605Smrg */
1128848b8605Smrgstruct gl_buffer_object *
1129848b8605Smrg_mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx,
1130848b8605Smrg                                  const GLuint *buffers,
1131848b8605Smrg                                  GLuint index, const char *caller)
1132848b8605Smrg{
1133848b8605Smrg   struct gl_buffer_object *bufObj;
1134848b8605Smrg
1135848b8605Smrg   if (buffers[index] != 0) {
1136848b8605Smrg      bufObj = _mesa_lookup_bufferobj_locked(ctx, buffers[index]);
1137848b8605Smrg
1138848b8605Smrg      /* The multi-bind functions don't create the buffer objects
1139848b8605Smrg         when they don't exist. */
1140848b8605Smrg      if (bufObj == &DummyBufferObject)
1141848b8605Smrg         bufObj = NULL;
1142848b8605Smrg   } else
1143848b8605Smrg      bufObj = ctx->Shared->NullBufferObj;
1144848b8605Smrg
1145848b8605Smrg   if (!bufObj) {
1146848b8605Smrg      /* The ARB_multi_bind spec says:
1147848b8605Smrg       *
1148848b8605Smrg       *    "An INVALID_OPERATION error is generated if any value
1149848b8605Smrg       *     in <buffers> is not zero or the name of an existing
1150848b8605Smrg       *     buffer object (per binding)."
1151848b8605Smrg       */
1152848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1153848b8605Smrg                  "%s(buffers[%u]=%u is not zero or the name "
1154848b8605Smrg                  "of an existing buffer object)",
1155848b8605Smrg                  caller, index, buffers[index]);
1156848b8605Smrg   }
1157848b8605Smrg
1158848b8605Smrg   return bufObj;
1159848b8605Smrg}
1160848b8605Smrg
1161848b8605Smrg
1162848b8605Smrg/**
1163848b8605Smrg * If *ptr points to obj, set ptr = the Null/default buffer object.
1164848b8605Smrg * This is a helper for buffer object deletion.
1165848b8605Smrg * The GL spec says that deleting a buffer object causes it to get
1166848b8605Smrg * unbound from all arrays in the current context.
1167848b8605Smrg */
1168848b8605Smrgstatic void
1169848b8605Smrgunbind(struct gl_context *ctx,
1170b8e80941Smrg       struct gl_vertex_array_object *vao, unsigned index,
1171848b8605Smrg       struct gl_buffer_object *obj)
1172848b8605Smrg{
1173b8e80941Smrg   if (vao->BufferBinding[index].BufferObj == obj) {
1174b8e80941Smrg      _mesa_bind_vertex_buffer(ctx, vao, index, ctx->Shared->NullBufferObj,
1175b8e80941Smrg                               vao->BufferBinding[index].Offset,
1176b8e80941Smrg                               vao->BufferBinding[index].Stride);
1177848b8605Smrg   }
1178848b8605Smrg}
1179848b8605Smrg
1180848b8605Smrg
1181848b8605Smrg/**
1182848b8605Smrg * Plug default/fallback buffer object functions into the device
1183848b8605Smrg * driver hooks.
1184848b8605Smrg */
1185848b8605Smrgvoid
1186848b8605Smrg_mesa_init_buffer_object_functions(struct dd_function_table *driver)
1187848b8605Smrg{
1188848b8605Smrg   /* GL_ARB_vertex/pixel_buffer_object */
1189848b8605Smrg   driver->NewBufferObject = _mesa_new_buffer_object;
1190848b8605Smrg   driver->DeleteBuffer = _mesa_delete_buffer_object;
1191b8e80941Smrg   driver->BufferData = buffer_data_fallback;
1192b8e80941Smrg   driver->BufferSubData = buffer_sub_data_fallback;
1193b8e80941Smrg   driver->GetBufferSubData = buffer_get_subdata;
1194b8e80941Smrg   driver->UnmapBuffer = unmap_buffer_fallback;
1195848b8605Smrg
1196848b8605Smrg   /* GL_ARB_clear_buffer_object */
1197b8e80941Smrg   driver->ClearBufferSubData = _mesa_ClearBufferSubData_sw;
1198848b8605Smrg
1199848b8605Smrg   /* GL_ARB_map_buffer_range */
1200b8e80941Smrg   driver->MapBufferRange = map_buffer_range_fallback;
1201b8e80941Smrg   driver->FlushMappedBufferRange = flush_mapped_buffer_range_fallback;
1202848b8605Smrg
1203848b8605Smrg   /* GL_ARB_copy_buffer */
1204b8e80941Smrg   driver->CopyBufferSubData = copy_buffer_sub_data_fallback;
1205848b8605Smrg}
1206848b8605Smrg
1207848b8605Smrg
1208848b8605Smrgvoid
1209848b8605Smrg_mesa_buffer_unmap_all_mappings(struct gl_context *ctx,
1210848b8605Smrg                                struct gl_buffer_object *bufObj)
1211848b8605Smrg{
1212b8e80941Smrg   for (int i = 0; i < MAP_COUNT; i++) {
1213848b8605Smrg      if (_mesa_bufferobj_mapped(bufObj, i)) {
1214848b8605Smrg         ctx->Driver.UnmapBuffer(ctx, bufObj, i);
1215b8e80941Smrg         assert(bufObj->Mappings[i].Pointer == NULL);
1216848b8605Smrg         bufObj->Mappings[i].AccessFlags = 0;
1217848b8605Smrg      }
1218848b8605Smrg   }
1219848b8605Smrg}
1220848b8605Smrg
1221848b8605Smrg
1222848b8605Smrg/**********************************************************************/
1223848b8605Smrg/* API Functions                                                      */
1224848b8605Smrg/**********************************************************************/
1225848b8605Smrg
1226848b8605Smrgvoid GLAPIENTRY
1227b8e80941Smrg_mesa_BindBuffer_no_error(GLenum target, GLuint buffer)
1228848b8605Smrg{
1229848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1230848b8605Smrg
1231b8e80941Smrg   struct gl_buffer_object **bindTarget = get_buffer_target(ctx, target);
1232b8e80941Smrg   bind_buffer_object(ctx, bindTarget, buffer);
1233848b8605Smrg}
1234848b8605Smrg
1235848b8605Smrg
1236848b8605Smrgvoid GLAPIENTRY
1237b8e80941Smrg_mesa_BindBuffer(GLenum target, GLuint buffer)
1238848b8605Smrg{
1239848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1240848b8605Smrg
1241b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
1242b8e80941Smrg      _mesa_debug(ctx, "glBindBuffer(%s, %u)\n",
1243b8e80941Smrg                  _mesa_enum_to_string(target), buffer);
1244848b8605Smrg   }
1245848b8605Smrg
1246b8e80941Smrg   struct gl_buffer_object **bindTarget = get_buffer_target(ctx, target);
1247b8e80941Smrg   if (!bindTarget) {
1248b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target %s)",
1249b8e80941Smrg                  _mesa_enum_to_string(target));
1250b8e80941Smrg      return;
1251848b8605Smrg   }
1252848b8605Smrg
1253b8e80941Smrg   bind_buffer_object(ctx, bindTarget, buffer);
1254848b8605Smrg}
1255848b8605Smrg
1256848b8605Smrg/**
1257b8e80941Smrg * Binds a buffer object to a binding point.
1258b8e80941Smrg *
1259b8e80941Smrg * The caller is responsible for validating the offset,
1260b8e80941Smrg * flushing the vertices and updating NewDriverState.
1261848b8605Smrg */
1262b8e80941Smrgstatic void
1263b8e80941Smrgset_buffer_binding(struct gl_context *ctx,
1264b8e80941Smrg                   struct gl_buffer_binding *binding,
1265b8e80941Smrg                   struct gl_buffer_object *bufObj,
1266b8e80941Smrg                   GLintptr offset,
1267b8e80941Smrg                   GLsizeiptr size,
1268b8e80941Smrg                   bool autoSize, gl_buffer_usage usage)
1269848b8605Smrg{
1270b8e80941Smrg   _mesa_reference_buffer_object(ctx, &binding->BufferObject, bufObj);
1271848b8605Smrg
1272b8e80941Smrg   binding->Offset = offset;
1273b8e80941Smrg   binding->Size = size;
1274b8e80941Smrg   binding->AutomaticSize = autoSize;
1275848b8605Smrg
1276b8e80941Smrg   /* If this is a real buffer object, mark it has having been used
1277b8e80941Smrg    * at some point as an atomic counter buffer.
1278b8e80941Smrg    */
1279b8e80941Smrg   if (size >= 0)
1280b8e80941Smrg      bufObj->UsageHistory |= usage;
1281b8e80941Smrg}
1282b8e80941Smrg
1283b8e80941Smrgstatic void
1284b8e80941Smrgset_buffer_multi_binding(struct gl_context *ctx,
1285b8e80941Smrg                         const GLuint *buffers,
1286b8e80941Smrg                         int idx,
1287b8e80941Smrg                         const char *caller,
1288b8e80941Smrg                         struct gl_buffer_binding *binding,
1289b8e80941Smrg                         GLintptr offset,
1290b8e80941Smrg                         GLsizeiptr size,
1291b8e80941Smrg                         bool range,
1292b8e80941Smrg                         gl_buffer_usage usage)
1293b8e80941Smrg{
1294b8e80941Smrg   struct gl_buffer_object *bufObj;
1295b8e80941Smrg   if (binding->BufferObject && binding->BufferObject->Name == buffers[idx])
1296b8e80941Smrg      bufObj = binding->BufferObject;
1297b8e80941Smrg   else
1298b8e80941Smrg      bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, idx, caller);
1299b8e80941Smrg
1300b8e80941Smrg   if (bufObj) {
1301b8e80941Smrg      if (bufObj == ctx->Shared->NullBufferObj)
1302b8e80941Smrg         set_buffer_binding(ctx, binding, bufObj, -1, -1, !range, usage);
1303b8e80941Smrg      else
1304b8e80941Smrg         set_buffer_binding(ctx, binding, bufObj, offset, size, !range, usage);
1305848b8605Smrg   }
1306b8e80941Smrg}
1307848b8605Smrg
1308b8e80941Smrgstatic void
1309b8e80941Smrgbind_buffer(struct gl_context *ctx,
1310b8e80941Smrg            struct gl_buffer_binding *binding,
1311b8e80941Smrg            struct gl_buffer_object *bufObj,
1312b8e80941Smrg            GLintptr offset,
1313b8e80941Smrg            GLsizeiptr size,
1314b8e80941Smrg            GLboolean autoSize,
1315b8e80941Smrg            uint64_t driver_state,
1316b8e80941Smrg            gl_buffer_usage usage)
1317b8e80941Smrg{
1318b8e80941Smrg   if (binding->BufferObject == bufObj &&
1319b8e80941Smrg       binding->Offset == offset &&
1320b8e80941Smrg       binding->Size == size &&
1321b8e80941Smrg       binding->AutomaticSize == autoSize) {
1322848b8605Smrg      return;
1323848b8605Smrg   }
1324848b8605Smrg
1325b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
1326b8e80941Smrg   ctx->NewDriverState |= driver_state;
1327848b8605Smrg
1328b8e80941Smrg   set_buffer_binding(ctx, binding, bufObj, offset, size, autoSize, usage);
1329848b8605Smrg}
1330848b8605Smrg
1331b8e80941Smrg/**
1332b8e80941Smrg * Binds a buffer object to a uniform buffer binding point.
1333b8e80941Smrg *
1334b8e80941Smrg * Unlike set_buffer_binding(), this function also flushes vertices
1335b8e80941Smrg * and updates NewDriverState.  It also checks if the binding
1336b8e80941Smrg * has actually changed before updating it.
1337b8e80941Smrg */
1338b8e80941Smrgstatic void
1339b8e80941Smrgbind_uniform_buffer(struct gl_context *ctx,
1340b8e80941Smrg                    GLuint index,
1341b8e80941Smrg                    struct gl_buffer_object *bufObj,
1342b8e80941Smrg                    GLintptr offset,
1343b8e80941Smrg                    GLsizeiptr size,
1344b8e80941Smrg                    GLboolean autoSize)
1345b8e80941Smrg{
1346b8e80941Smrg   bind_buffer(ctx, &ctx->UniformBufferBindings[index],
1347b8e80941Smrg               bufObj, offset, size, autoSize,
1348b8e80941Smrg               ctx->DriverFlags.NewUniformBuffer,
1349b8e80941Smrg               USAGE_UNIFORM_BUFFER);
1350b8e80941Smrg}
1351b8e80941Smrg
1352b8e80941Smrg/**
1353b8e80941Smrg * Binds a buffer object to a shader storage buffer binding point.
1354b8e80941Smrg *
1355b8e80941Smrg * Unlike set_ssbo_binding(), this function also flushes vertices
1356b8e80941Smrg * and updates NewDriverState.  It also checks if the binding
1357b8e80941Smrg * has actually changed before updating it.
1358b8e80941Smrg */
1359b8e80941Smrgstatic void
1360b8e80941Smrgbind_shader_storage_buffer(struct gl_context *ctx,
1361b8e80941Smrg                           GLuint index,
1362b8e80941Smrg                           struct gl_buffer_object *bufObj,
1363b8e80941Smrg                           GLintptr offset,
1364b8e80941Smrg                           GLsizeiptr size,
1365b8e80941Smrg                           GLboolean autoSize)
1366b8e80941Smrg{
1367b8e80941Smrg   bind_buffer(ctx, &ctx->ShaderStorageBufferBindings[index],
1368b8e80941Smrg               bufObj, offset, size, autoSize,
1369b8e80941Smrg               ctx->DriverFlags.NewShaderStorageBuffer,
1370b8e80941Smrg               USAGE_SHADER_STORAGE_BUFFER);
1371b8e80941Smrg}
1372b8e80941Smrg
1373b8e80941Smrg/**
1374b8e80941Smrg * Binds a buffer object to an atomic buffer binding point.
1375b8e80941Smrg *
1376b8e80941Smrg * Unlike set_atomic_binding(), this function also flushes vertices
1377b8e80941Smrg * and updates NewDriverState.  It also checks if the binding
1378b8e80941Smrg * has actually changed before updating it.
1379b8e80941Smrg */
1380b8e80941Smrgstatic void
1381b8e80941Smrgbind_atomic_buffer(struct gl_context *ctx, unsigned index,
1382b8e80941Smrg                   struct gl_buffer_object *bufObj, GLintptr offset,
1383b8e80941Smrg                   GLsizeiptr size, GLboolean autoSize)
1384b8e80941Smrg{
1385b8e80941Smrg   bind_buffer(ctx, &ctx->AtomicBufferBindings[index],
1386b8e80941Smrg               bufObj, offset, size, autoSize,
1387b8e80941Smrg               ctx->DriverFlags.NewAtomicBuffer,
1388b8e80941Smrg               USAGE_ATOMIC_COUNTER_BUFFER);
1389b8e80941Smrg}
1390b8e80941Smrg
1391b8e80941Smrg/**
1392b8e80941Smrg * Bind a buffer object to a uniform block binding point.
1393b8e80941Smrg * As above, but offset = 0.
1394b8e80941Smrg */
1395b8e80941Smrgstatic void
1396b8e80941Smrgbind_buffer_base_uniform_buffer(struct gl_context *ctx,
1397b8e80941Smrg				GLuint index,
1398b8e80941Smrg				struct gl_buffer_object *bufObj)
1399b8e80941Smrg{
1400b8e80941Smrg   if (index >= ctx->Const.MaxUniformBufferBindings) {
1401b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
1402b8e80941Smrg      return;
1403b8e80941Smrg   }
1404b8e80941Smrg
1405b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
1406b8e80941Smrg
1407b8e80941Smrg   if (bufObj == ctx->Shared->NullBufferObj)
1408b8e80941Smrg      bind_uniform_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
1409b8e80941Smrg   else
1410b8e80941Smrg      bind_uniform_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
1411b8e80941Smrg}
1412b8e80941Smrg
1413b8e80941Smrg/**
1414b8e80941Smrg * Bind a buffer object to a shader storage block binding point.
1415b8e80941Smrg * As above, but offset = 0.
1416b8e80941Smrg */
1417b8e80941Smrgstatic void
1418b8e80941Smrgbind_buffer_base_shader_storage_buffer(struct gl_context *ctx,
1419b8e80941Smrg                                       GLuint index,
1420b8e80941Smrg                                       struct gl_buffer_object *bufObj)
1421b8e80941Smrg{
1422b8e80941Smrg   if (index >= ctx->Const.MaxShaderStorageBufferBindings) {
1423b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
1424b8e80941Smrg      return;
1425b8e80941Smrg   }
1426b8e80941Smrg
1427b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
1428b8e80941Smrg
1429b8e80941Smrg   if (bufObj == ctx->Shared->NullBufferObj)
1430b8e80941Smrg      bind_shader_storage_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
1431b8e80941Smrg   else
1432b8e80941Smrg      bind_shader_storage_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
1433b8e80941Smrg}
1434b8e80941Smrg
1435b8e80941Smrg/**
1436b8e80941Smrg * Bind a buffer object to a shader storage block binding point.
1437b8e80941Smrg * As above, but offset = 0.
1438b8e80941Smrg */
1439b8e80941Smrgstatic void
1440b8e80941Smrgbind_buffer_base_atomic_buffer(struct gl_context *ctx,
1441b8e80941Smrg                               GLuint index,
1442b8e80941Smrg                               struct gl_buffer_object *bufObj)
1443b8e80941Smrg{
1444b8e80941Smrg   if (index >= ctx->Const.MaxAtomicBufferBindings) {
1445b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferBase(index=%d)", index);
1446b8e80941Smrg      return;
1447b8e80941Smrg   }
1448b8e80941Smrg
1449b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
1450b8e80941Smrg
1451b8e80941Smrg   if (bufObj == ctx->Shared->NullBufferObj)
1452b8e80941Smrg      bind_atomic_buffer(ctx, index, bufObj, -1, -1, GL_TRUE);
1453b8e80941Smrg   else
1454b8e80941Smrg      bind_atomic_buffer(ctx, index, bufObj, 0, 0, GL_TRUE);
1455b8e80941Smrg}
1456b8e80941Smrg
1457b8e80941Smrg/**
1458b8e80941Smrg * Delete a set of buffer objects.
1459b8e80941Smrg *
1460b8e80941Smrg * \param n      Number of buffer objects to delete.
1461b8e80941Smrg * \param ids    Array of \c n buffer object IDs.
1462b8e80941Smrg */
1463b8e80941Smrgstatic void
1464b8e80941Smrgdelete_buffers(struct gl_context *ctx, GLsizei n, const GLuint *ids)
1465b8e80941Smrg{
1466b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
1467b8e80941Smrg
1468b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->BufferObjects);
1469b8e80941Smrg
1470b8e80941Smrg   for (GLsizei i = 0; i < n; i++) {
1471b8e80941Smrg      struct gl_buffer_object *bufObj =
1472b8e80941Smrg         _mesa_lookup_bufferobj_locked(ctx, ids[i]);
1473b8e80941Smrg      if (bufObj) {
1474b8e80941Smrg         struct gl_vertex_array_object *vao = ctx->Array.VAO;
1475b8e80941Smrg         GLuint j;
1476b8e80941Smrg
1477b8e80941Smrg         assert(bufObj->Name == ids[i] || bufObj == &DummyBufferObject);
1478b8e80941Smrg
1479b8e80941Smrg         _mesa_buffer_unmap_all_mappings(ctx, bufObj);
1480b8e80941Smrg
1481b8e80941Smrg         /* unbind any vertex pointers bound to this buffer */
1482b8e80941Smrg         for (j = 0; j < ARRAY_SIZE(vao->BufferBinding); j++) {
1483b8e80941Smrg            unbind(ctx, vao, j, bufObj);
1484b8e80941Smrg         }
1485b8e80941Smrg
1486b8e80941Smrg         if (ctx->Array.ArrayBufferObj == bufObj) {
1487b8e80941Smrg            bind_buffer_object(ctx, &ctx->Array.ArrayBufferObj, 0);
1488b8e80941Smrg         }
1489b8e80941Smrg         if (vao->IndexBufferObj == bufObj) {
1490b8e80941Smrg            bind_buffer_object(ctx, &vao->IndexBufferObj, 0);
1491b8e80941Smrg         }
1492b8e80941Smrg
1493b8e80941Smrg         /* unbind ARB_draw_indirect binding point */
1494b8e80941Smrg         if (ctx->DrawIndirectBuffer == bufObj) {
1495b8e80941Smrg            bind_buffer_object(ctx, &ctx->DrawIndirectBuffer, 0);
1496b8e80941Smrg         }
1497b8e80941Smrg
1498b8e80941Smrg         /* unbind ARB_indirect_parameters binding point */
1499b8e80941Smrg         if (ctx->ParameterBuffer == bufObj) {
1500b8e80941Smrg            bind_buffer_object(ctx, &ctx->ParameterBuffer, 0);
1501b8e80941Smrg         }
1502b8e80941Smrg
1503b8e80941Smrg         /* unbind ARB_compute_shader binding point */
1504b8e80941Smrg         if (ctx->DispatchIndirectBuffer == bufObj) {
1505b8e80941Smrg            bind_buffer_object(ctx, &ctx->DispatchIndirectBuffer, 0);
1506b8e80941Smrg         }
1507b8e80941Smrg
1508b8e80941Smrg         /* unbind ARB_copy_buffer binding points */
1509b8e80941Smrg         if (ctx->CopyReadBuffer == bufObj) {
1510b8e80941Smrg            bind_buffer_object(ctx, &ctx->CopyReadBuffer, 0);
1511b8e80941Smrg         }
1512b8e80941Smrg         if (ctx->CopyWriteBuffer == bufObj) {
1513b8e80941Smrg            bind_buffer_object(ctx, &ctx->CopyWriteBuffer, 0);
1514b8e80941Smrg         }
1515b8e80941Smrg
1516b8e80941Smrg         /* unbind transform feedback binding points */
1517b8e80941Smrg         if (ctx->TransformFeedback.CurrentBuffer == bufObj) {
1518b8e80941Smrg            bind_buffer_object(ctx, &ctx->TransformFeedback.CurrentBuffer, 0);
1519b8e80941Smrg         }
1520b8e80941Smrg         for (j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
1521b8e80941Smrg            if (ctx->TransformFeedback.CurrentObject->Buffers[j] == bufObj) {
1522b8e80941Smrg               _mesa_bind_buffer_base_transform_feedback(ctx,
1523b8e80941Smrg                                           ctx->TransformFeedback.CurrentObject,
1524b8e80941Smrg                                           j, ctx->Shared->NullBufferObj,
1525b8e80941Smrg                                           false);
1526b8e80941Smrg            }
1527b8e80941Smrg         }
1528b8e80941Smrg
1529b8e80941Smrg         /* unbind UBO binding points */
1530b8e80941Smrg         for (j = 0; j < ctx->Const.MaxUniformBufferBindings; j++) {
1531b8e80941Smrg            if (ctx->UniformBufferBindings[j].BufferObject == bufObj) {
1532b8e80941Smrg               bind_buffer_base_uniform_buffer(ctx, j,
1533b8e80941Smrg                                               ctx->Shared->NullBufferObj);
1534b8e80941Smrg            }
1535b8e80941Smrg         }
1536b8e80941Smrg
1537b8e80941Smrg         if (ctx->UniformBuffer == bufObj) {
1538b8e80941Smrg            bind_buffer_object(ctx, &ctx->UniformBuffer, 0);
1539b8e80941Smrg         }
1540b8e80941Smrg
1541b8e80941Smrg         /* unbind SSBO binding points */
1542b8e80941Smrg         for (j = 0; j < ctx->Const.MaxShaderStorageBufferBindings; j++) {
1543b8e80941Smrg            if (ctx->ShaderStorageBufferBindings[j].BufferObject == bufObj) {
1544b8e80941Smrg               bind_buffer_base_shader_storage_buffer(ctx, j,
1545b8e80941Smrg                                                    ctx->Shared->NullBufferObj);
1546b8e80941Smrg            }
1547b8e80941Smrg         }
1548b8e80941Smrg
1549b8e80941Smrg         if (ctx->ShaderStorageBuffer == bufObj) {
1550b8e80941Smrg            bind_buffer_object(ctx, &ctx->ShaderStorageBuffer, 0);
1551b8e80941Smrg         }
1552b8e80941Smrg
1553b8e80941Smrg         /* unbind Atomci Buffer binding points */
1554b8e80941Smrg         for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) {
1555b8e80941Smrg            if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) {
1556b8e80941Smrg               bind_buffer_base_atomic_buffer(ctx, j,
1557b8e80941Smrg                                              ctx->Shared->NullBufferObj);
1558b8e80941Smrg            }
1559b8e80941Smrg         }
1560b8e80941Smrg
1561b8e80941Smrg         if (ctx->AtomicBuffer == bufObj) {
1562b8e80941Smrg            bind_buffer_object(ctx, &ctx->AtomicBuffer, 0);
1563b8e80941Smrg         }
1564b8e80941Smrg
1565b8e80941Smrg         /* unbind any pixel pack/unpack pointers bound to this buffer */
1566b8e80941Smrg         if (ctx->Pack.BufferObj == bufObj) {
1567b8e80941Smrg            bind_buffer_object(ctx, &ctx->Pack.BufferObj, 0);
1568b8e80941Smrg         }
1569b8e80941Smrg         if (ctx->Unpack.BufferObj == bufObj) {
1570b8e80941Smrg            bind_buffer_object(ctx, &ctx->Unpack.BufferObj, 0);
1571b8e80941Smrg         }
1572b8e80941Smrg
1573b8e80941Smrg         if (ctx->Texture.BufferObject == bufObj) {
1574b8e80941Smrg            bind_buffer_object(ctx, &ctx->Texture.BufferObject, 0);
1575b8e80941Smrg         }
1576b8e80941Smrg
1577b8e80941Smrg         if (ctx->ExternalVirtualMemoryBuffer == bufObj) {
1578b8e80941Smrg            bind_buffer_object(ctx, &ctx->ExternalVirtualMemoryBuffer, 0);
1579b8e80941Smrg         }
1580b8e80941Smrg
1581b8e80941Smrg         /* unbind query buffer binding point */
1582b8e80941Smrg         if (ctx->QueryBuffer == bufObj) {
1583b8e80941Smrg            bind_buffer_object(ctx, &ctx->QueryBuffer, 0);
1584b8e80941Smrg         }
1585b8e80941Smrg
1586b8e80941Smrg         /* The ID is immediately freed for re-use */
1587b8e80941Smrg         _mesa_HashRemoveLocked(ctx->Shared->BufferObjects, ids[i]);
1588b8e80941Smrg         /* Make sure we do not run into the classic ABA problem on bind.
1589b8e80941Smrg          * We don't want to allow re-binding a buffer object that's been
1590b8e80941Smrg          * "deleted" by glDeleteBuffers().
1591b8e80941Smrg          *
1592b8e80941Smrg          * The explicit rebinding to the default object in the current context
1593b8e80941Smrg          * prevents the above in the current context, but another context
1594b8e80941Smrg          * sharing the same objects might suffer from this problem.
1595b8e80941Smrg          * The alternative would be to do the hash lookup in any case on bind
1596b8e80941Smrg          * which would introduce more runtime overhead than this.
1597b8e80941Smrg          */
1598b8e80941Smrg         bufObj->DeletePending = GL_TRUE;
1599b8e80941Smrg         _mesa_reference_buffer_object(ctx, &bufObj, NULL);
1600b8e80941Smrg      }
1601b8e80941Smrg   }
1602b8e80941Smrg
1603b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
1604b8e80941Smrg}
1605b8e80941Smrg
1606b8e80941Smrg
1607b8e80941Smrgvoid GLAPIENTRY
1608b8e80941Smrg_mesa_DeleteBuffers_no_error(GLsizei n, const GLuint *ids)
1609b8e80941Smrg{
1610b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1611b8e80941Smrg   delete_buffers(ctx, n, ids);
1612b8e80941Smrg}
1613b8e80941Smrg
1614b8e80941Smrg
1615b8e80941Smrgvoid GLAPIENTRY
1616b8e80941Smrg_mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
1617b8e80941Smrg{
1618b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1619b8e80941Smrg
1620b8e80941Smrg   if (n < 0) {
1621b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)");
1622b8e80941Smrg      return;
1623b8e80941Smrg   }
1624b8e80941Smrg
1625b8e80941Smrg   delete_buffers(ctx, n, ids);
1626b8e80941Smrg}
1627b8e80941Smrg
1628b8e80941Smrg
1629b8e80941Smrg/**
1630b8e80941Smrg * This is the implementation for glGenBuffers and glCreateBuffers. It is not
1631b8e80941Smrg * exposed to the rest of Mesa to encourage the use of nameless buffers in
1632b8e80941Smrg * driver internals.
1633b8e80941Smrg */
1634b8e80941Smrgstatic void
1635b8e80941Smrgcreate_buffers(struct gl_context *ctx, GLsizei n, GLuint *buffers, bool dsa)
1636b8e80941Smrg{
1637b8e80941Smrg   GLuint first;
1638b8e80941Smrg   struct gl_buffer_object *buf;
1639b8e80941Smrg
1640b8e80941Smrg   if (!buffers)
1641b8e80941Smrg      return;
1642b8e80941Smrg
1643b8e80941Smrg   /*
1644b8e80941Smrg    * This must be atomic (generation and allocation of buffer object IDs)
1645b8e80941Smrg    */
1646b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->BufferObjects);
1647b8e80941Smrg
1648b8e80941Smrg   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n);
1649b8e80941Smrg
1650b8e80941Smrg   /* Insert the ID and pointer into the hash table. If non-DSA, insert a
1651b8e80941Smrg    * DummyBufferObject.  Otherwise, create a new buffer object and insert
1652b8e80941Smrg    * it.
1653b8e80941Smrg    */
1654b8e80941Smrg   for (int i = 0; i < n; i++) {
1655b8e80941Smrg      buffers[i] = first + i;
1656b8e80941Smrg      if (dsa) {
1657b8e80941Smrg         assert(ctx->Driver.NewBufferObject);
1658b8e80941Smrg         buf = ctx->Driver.NewBufferObject(ctx, buffers[i]);
1659b8e80941Smrg         if (!buf) {
1660b8e80941Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCreateBuffers");
1661b8e80941Smrg            _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
1662b8e80941Smrg            return;
1663b8e80941Smrg         }
1664b8e80941Smrg      }
1665b8e80941Smrg      else
1666b8e80941Smrg         buf = &DummyBufferObject;
1667b8e80941Smrg
1668b8e80941Smrg      _mesa_HashInsertLocked(ctx->Shared->BufferObjects, buffers[i], buf);
1669b8e80941Smrg   }
1670b8e80941Smrg
1671b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
1672b8e80941Smrg}
1673b8e80941Smrg
1674b8e80941Smrg
1675b8e80941Smrgstatic void
1676b8e80941Smrgcreate_buffers_err(struct gl_context *ctx, GLsizei n, GLuint *buffers, bool dsa)
1677b8e80941Smrg{
1678b8e80941Smrg   const char *func = dsa ? "glCreateBuffers" : "glGenBuffers";
1679b8e80941Smrg
1680b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API)
1681b8e80941Smrg      _mesa_debug(ctx, "%s(%d)\n", func, n);
1682b8e80941Smrg
1683b8e80941Smrg   if (n < 0) {
1684b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n %d < 0)", func, n);
1685b8e80941Smrg      return;
1686b8e80941Smrg   }
1687b8e80941Smrg
1688b8e80941Smrg   create_buffers(ctx, n, buffers, dsa);
1689b8e80941Smrg}
1690b8e80941Smrg
1691b8e80941Smrg/**
1692b8e80941Smrg * Generate a set of unique buffer object IDs and store them in \c buffers.
1693b8e80941Smrg *
1694b8e80941Smrg * \param n        Number of IDs to generate.
1695b8e80941Smrg * \param buffers  Array of \c n locations to store the IDs.
1696b8e80941Smrg */
1697b8e80941Smrgvoid GLAPIENTRY
1698b8e80941Smrg_mesa_GenBuffers_no_error(GLsizei n, GLuint *buffers)
1699b8e80941Smrg{
1700b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1701b8e80941Smrg   create_buffers(ctx, n, buffers, false);
1702b8e80941Smrg}
1703b8e80941Smrg
1704b8e80941Smrg
1705b8e80941Smrgvoid GLAPIENTRY
1706b8e80941Smrg_mesa_GenBuffers(GLsizei n, GLuint *buffers)
1707b8e80941Smrg{
1708b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1709b8e80941Smrg   create_buffers_err(ctx, n, buffers, false);
1710b8e80941Smrg}
1711b8e80941Smrg
1712b8e80941Smrg/**
1713b8e80941Smrg * Create a set of buffer objects and store their unique IDs in \c buffers.
1714b8e80941Smrg *
1715b8e80941Smrg * \param n        Number of IDs to generate.
1716b8e80941Smrg * \param buffers  Array of \c n locations to store the IDs.
1717b8e80941Smrg */
1718b8e80941Smrgvoid GLAPIENTRY
1719b8e80941Smrg_mesa_CreateBuffers_no_error(GLsizei n, GLuint *buffers)
1720b8e80941Smrg{
1721b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1722b8e80941Smrg   create_buffers(ctx, n, buffers, true);
1723b8e80941Smrg}
1724b8e80941Smrg
1725b8e80941Smrg
1726b8e80941Smrgvoid GLAPIENTRY
1727b8e80941Smrg_mesa_CreateBuffers(GLsizei n, GLuint *buffers)
1728b8e80941Smrg{
1729b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1730b8e80941Smrg   create_buffers_err(ctx, n, buffers, true);
1731b8e80941Smrg}
1732b8e80941Smrg
1733b8e80941Smrg
1734848b8605Smrg/**
1735848b8605Smrg * Determine if ID is the name of a buffer object.
1736b8e80941Smrg *
1737848b8605Smrg * \param id  ID of the potential buffer object.
1738b8e80941Smrg * \return  \c GL_TRUE if \c id is the name of a buffer object,
1739848b8605Smrg *          \c GL_FALSE otherwise.
1740848b8605Smrg */
1741848b8605SmrgGLboolean GLAPIENTRY
1742848b8605Smrg_mesa_IsBuffer(GLuint id)
1743848b8605Smrg{
1744848b8605Smrg   struct gl_buffer_object *bufObj;
1745848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1746848b8605Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1747848b8605Smrg
1748848b8605Smrg   bufObj = _mesa_lookup_bufferobj(ctx, id);
1749848b8605Smrg
1750848b8605Smrg   return bufObj && bufObj != &DummyBufferObject;
1751848b8605Smrg}
1752848b8605Smrg
1753848b8605Smrg
1754b8e80941Smrgstatic bool
1755b8e80941Smrgvalidate_buffer_storage(struct gl_context *ctx,
1756b8e80941Smrg                        struct gl_buffer_object *bufObj, GLsizeiptr size,
1757b8e80941Smrg                        GLbitfield flags, const char *func)
1758848b8605Smrg{
1759848b8605Smrg   if (size <= 0) {
1760b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size <= 0)", func);
1761b8e80941Smrg      return false;
1762848b8605Smrg   }
1763848b8605Smrg
1764b8e80941Smrg   GLbitfield valid_flags = GL_MAP_READ_BIT |
1765b8e80941Smrg                            GL_MAP_WRITE_BIT |
1766b8e80941Smrg                            GL_MAP_PERSISTENT_BIT |
1767b8e80941Smrg                            GL_MAP_COHERENT_BIT |
1768b8e80941Smrg                            GL_DYNAMIC_STORAGE_BIT |
1769b8e80941Smrg                            GL_CLIENT_STORAGE_BIT;
1770b8e80941Smrg
1771b8e80941Smrg   if (ctx->Extensions.ARB_sparse_buffer)
1772b8e80941Smrg      valid_flags |= GL_SPARSE_STORAGE_BIT_ARB;
1773b8e80941Smrg
1774b8e80941Smrg   if (flags & ~valid_flags) {
1775b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid flag bits set)", func);
1776b8e80941Smrg      return false;
1777b8e80941Smrg   }
1778b8e80941Smrg
1779b8e80941Smrg   /* The Errors section of the GL_ARB_sparse_buffer spec says:
1780b8e80941Smrg    *
1781b8e80941Smrg    *    "INVALID_VALUE is generated by BufferStorage if <flags> contains
1782b8e80941Smrg    *     SPARSE_STORAGE_BIT_ARB and <flags> also contains any combination of
1783b8e80941Smrg    *     MAP_READ_BIT or MAP_WRITE_BIT."
1784b8e80941Smrg    */
1785b8e80941Smrg   if (flags & GL_SPARSE_STORAGE_BIT_ARB &&
1786b8e80941Smrg       flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) {
1787b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(SPARSE_STORAGE and READ/WRITE)", func);
1788b8e80941Smrg      return false;
1789848b8605Smrg   }
1790848b8605Smrg
1791848b8605Smrg   if (flags & GL_MAP_PERSISTENT_BIT &&
1792848b8605Smrg       !(flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT))) {
1793b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
1794b8e80941Smrg                  "%s(PERSISTENT and flags!=READ/WRITE)", func);
1795b8e80941Smrg      return false;
1796848b8605Smrg   }
1797848b8605Smrg
1798848b8605Smrg   if (flags & GL_MAP_COHERENT_BIT && !(flags & GL_MAP_PERSISTENT_BIT)) {
1799b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
1800b8e80941Smrg                  "%s(COHERENT and flags!=PERSISTENT)", func);
1801b8e80941Smrg      return false;
1802848b8605Smrg   }
1803848b8605Smrg
1804b8e80941Smrg   if (bufObj->Immutable || bufObj->HandleAllocated) {
1805b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
1806b8e80941Smrg      return false;
1807848b8605Smrg   }
1808848b8605Smrg
1809b8e80941Smrg   return true;
1810b8e80941Smrg}
1811b8e80941Smrg
1812b8e80941Smrg
1813b8e80941Smrgstatic void
1814b8e80941Smrgbuffer_storage(struct gl_context *ctx, struct gl_buffer_object *bufObj,
1815b8e80941Smrg               struct gl_memory_object *memObj, GLenum target,
1816b8e80941Smrg               GLsizeiptr size, const GLvoid *data, GLbitfield flags,
1817b8e80941Smrg               GLuint64 offset, const char *func)
1818b8e80941Smrg{
1819b8e80941Smrg   GLboolean res;
1820b8e80941Smrg
1821848b8605Smrg   /* Unmap the existing buffer.  We'll replace it now.  Not an error. */
1822848b8605Smrg   _mesa_buffer_unmap_all_mappings(ctx, bufObj);
1823848b8605Smrg
1824b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
1825848b8605Smrg
1826848b8605Smrg   bufObj->Written = GL_TRUE;
1827848b8605Smrg   bufObj->Immutable = GL_TRUE;
1828b8e80941Smrg   bufObj->MinMaxCacheDirty = true;
1829b8e80941Smrg
1830b8e80941Smrg   if (memObj) {
1831b8e80941Smrg      assert(ctx->Driver.BufferDataMem);
1832b8e80941Smrg      res = ctx->Driver.BufferDataMem(ctx, target, size, memObj, offset,
1833b8e80941Smrg                                      GL_DYNAMIC_DRAW, bufObj);
1834b8e80941Smrg   }
1835b8e80941Smrg   else {
1836b8e80941Smrg      assert(ctx->Driver.BufferData);
1837b8e80941Smrg      res = ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW,
1838b8e80941Smrg                                   flags, bufObj);
1839b8e80941Smrg   }
1840848b8605Smrg
1841b8e80941Smrg   if (!res) {
1842b8e80941Smrg      if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
1843b8e80941Smrg         /* Even though the interaction between AMD_pinned_memory and
1844b8e80941Smrg          * glBufferStorage is not described in the spec, Graham Sellers
1845b8e80941Smrg          * said that it should behave the same as glBufferData.
1846b8e80941Smrg          */
1847b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1848b8e80941Smrg      }
1849b8e80941Smrg      else {
1850b8e80941Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1851b8e80941Smrg      }
1852848b8605Smrg   }
1853848b8605Smrg}
1854848b8605Smrg
1855848b8605Smrg
1856b8e80941Smrgstatic ALWAYS_INLINE void
1857b8e80941Smrginlined_buffer_storage(GLenum target, GLuint buffer, GLsizeiptr size,
1858b8e80941Smrg                       const GLvoid *data, GLbitfield flags,
1859b8e80941Smrg                       GLuint memory, GLuint64 offset,
1860b8e80941Smrg                       bool dsa, bool mem, bool no_error, const char *func)
1861848b8605Smrg{
1862848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1863848b8605Smrg   struct gl_buffer_object *bufObj;
1864b8e80941Smrg   struct gl_memory_object *memObj = NULL;
1865848b8605Smrg
1866b8e80941Smrg   if (mem) {
1867b8e80941Smrg      if (!no_error) {
1868b8e80941Smrg         if (!ctx->Extensions.EXT_memory_object) {
1869b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
1870b8e80941Smrg            return;
1871b8e80941Smrg         }
1872848b8605Smrg
1873b8e80941Smrg         /* From the EXT_external_objects spec:
1874b8e80941Smrg          *
1875b8e80941Smrg          *   "An INVALID_VALUE error is generated by BufferStorageMemEXT and
1876b8e80941Smrg          *   NamedBufferStorageMemEXT if <memory> is 0, or ..."
1877b8e80941Smrg          */
1878b8e80941Smrg         if (memory == 0) {
1879b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory == 0)", func);
1880b8e80941Smrg         }
1881b8e80941Smrg      }
1882b8e80941Smrg
1883b8e80941Smrg      memObj = _mesa_lookup_memory_object(ctx, memory);
1884b8e80941Smrg      if (!memObj)
1885b8e80941Smrg         return;
1886b8e80941Smrg
1887b8e80941Smrg      /* From the EXT_external_objects spec:
1888b8e80941Smrg       *
1889b8e80941Smrg       *   "An INVALID_OPERATION error is generated if <memory> names a
1890b8e80941Smrg       *   valid memory object which has no associated memory."
1891b8e80941Smrg       */
1892b8e80941Smrg      if (!no_error && !memObj->Immutable) {
1893b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)",
1894b8e80941Smrg                     func);
1895b8e80941Smrg         return;
1896b8e80941Smrg      }
1897848b8605Smrg   }
1898848b8605Smrg
1899b8e80941Smrg   if (dsa) {
1900b8e80941Smrg      if (no_error) {
1901b8e80941Smrg         bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1902b8e80941Smrg      } else {
1903b8e80941Smrg         bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func);
1904b8e80941Smrg         if (!bufObj)
1905b8e80941Smrg            return;
1906b8e80941Smrg      }
1907b8e80941Smrg   } else {
1908b8e80941Smrg      if (no_error) {
1909b8e80941Smrg         struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
1910b8e80941Smrg         bufObj = *bufObjPtr;
1911b8e80941Smrg      } else {
1912b8e80941Smrg         bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION);
1913b8e80941Smrg         if (!bufObj)
1914b8e80941Smrg            return;
1915b8e80941Smrg      }
1916b8e80941Smrg   }
1917848b8605Smrg
1918b8e80941Smrg   if (no_error || validate_buffer_storage(ctx, bufObj, size, flags, func))
1919b8e80941Smrg      buffer_storage(ctx, bufObj, memObj, target, size, data, flags, offset, func);
1920b8e80941Smrg}
1921848b8605Smrg
1922848b8605Smrg
1923b8e80941Smrgvoid GLAPIENTRY
1924b8e80941Smrg_mesa_BufferStorage_no_error(GLenum target, GLsizeiptr size,
1925b8e80941Smrg                             const GLvoid *data, GLbitfield flags)
1926b8e80941Smrg{
1927b8e80941Smrg   inlined_buffer_storage(target, 0, size, data, flags, GL_NONE, 0,
1928b8e80941Smrg                          false, false, true, "glBufferStorage");
1929b8e80941Smrg}
1930848b8605Smrg
1931b8e80941Smrg
1932b8e80941Smrgvoid GLAPIENTRY
1933b8e80941Smrg_mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
1934b8e80941Smrg                    GLbitfield flags)
1935b8e80941Smrg{
1936b8e80941Smrg   inlined_buffer_storage(target, 0, size, data, flags, GL_NONE, 0,
1937b8e80941Smrg                          false, false, false, "glBufferStorage");
1938b8e80941Smrg}
1939b8e80941Smrg
1940b8e80941Smrg
1941b8e80941Smrgvoid GLAPIENTRY
1942b8e80941Smrg_mesa_BufferStorageMemEXT(GLenum target, GLsizeiptr size,
1943b8e80941Smrg                          GLuint memory, GLuint64 offset)
1944b8e80941Smrg{
1945b8e80941Smrg   inlined_buffer_storage(target, 0, size, NULL, 0, memory, offset,
1946b8e80941Smrg                          false, true, false, "glBufferStorageMemEXT");
1947b8e80941Smrg}
1948b8e80941Smrg
1949b8e80941Smrg
1950b8e80941Smrgvoid GLAPIENTRY
1951b8e80941Smrg_mesa_BufferStorageMemEXT_no_error(GLenum target, GLsizeiptr size,
1952b8e80941Smrg                                   GLuint memory, GLuint64 offset)
1953b8e80941Smrg{
1954b8e80941Smrg   inlined_buffer_storage(target, 0, size, NULL, 0, memory, offset,
1955b8e80941Smrg                          false, true, true, "glBufferStorageMemEXT");
1956b8e80941Smrg}
1957b8e80941Smrg
1958b8e80941Smrg
1959b8e80941Smrgvoid GLAPIENTRY
1960b8e80941Smrg_mesa_NamedBufferStorage_no_error(GLuint buffer, GLsizeiptr size,
1961b8e80941Smrg                                  const GLvoid *data, GLbitfield flags)
1962b8e80941Smrg{
1963b8e80941Smrg   /* In direct state access, buffer objects have an unspecified target
1964b8e80941Smrg    * since they are not required to be bound.
1965b8e80941Smrg    */
1966b8e80941Smrg   inlined_buffer_storage(GL_NONE, buffer, size, data, flags, GL_NONE, 0,
1967b8e80941Smrg                          true, false, true, "glNamedBufferStorage");
1968b8e80941Smrg}
1969b8e80941Smrg
1970b8e80941Smrg
1971b8e80941Smrgvoid GLAPIENTRY
1972b8e80941Smrg_mesa_NamedBufferStorage(GLuint buffer, GLsizeiptr size, const GLvoid *data,
1973b8e80941Smrg                         GLbitfield flags)
1974b8e80941Smrg{
1975b8e80941Smrg   /* In direct state access, buffer objects have an unspecified target
1976b8e80941Smrg    * since they are not required to be bound.
1977b8e80941Smrg    */
1978b8e80941Smrg   inlined_buffer_storage(GL_NONE, buffer, size, data, flags, GL_NONE, 0,
1979b8e80941Smrg                          true, false, false, "glNamedBufferStorage");
1980b8e80941Smrg}
1981b8e80941Smrg
1982b8e80941Smrgvoid GLAPIENTRY
1983b8e80941Smrg_mesa_NamedBufferStorageMemEXT(GLuint buffer, GLsizeiptr size,
1984b8e80941Smrg                               GLuint memory, GLuint64 offset)
1985b8e80941Smrg{
1986b8e80941Smrg   inlined_buffer_storage(GL_NONE, buffer, size, GL_NONE, 0, memory, offset,
1987b8e80941Smrg                          true, true, false, "glNamedBufferStorageMemEXT");
1988b8e80941Smrg}
1989b8e80941Smrg
1990b8e80941Smrg
1991b8e80941Smrgvoid GLAPIENTRY
1992b8e80941Smrg_mesa_NamedBufferStorageMemEXT_no_error(GLuint buffer, GLsizeiptr size,
1993b8e80941Smrg                                        GLuint memory, GLuint64 offset)
1994b8e80941Smrg{
1995b8e80941Smrg   inlined_buffer_storage(GL_NONE, buffer, size, GL_NONE, 0, memory, offset,
1996b8e80941Smrg                          true, true, true, "glNamedBufferStorageMemEXT");
1997b8e80941Smrg}
1998b8e80941Smrg
1999b8e80941Smrg
2000b8e80941Smrgstatic ALWAYS_INLINE void
2001b8e80941Smrgbuffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2002b8e80941Smrg            GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage,
2003b8e80941Smrg            const char *func, bool no_error)
2004b8e80941Smrg{
2005b8e80941Smrg   bool valid_usage;
2006b8e80941Smrg
2007b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
2008b8e80941Smrg      _mesa_debug(ctx, "%s(%s, %ld, %p, %s)\n",
2009b8e80941Smrg                  func,
2010b8e80941Smrg                  _mesa_enum_to_string(target),
2011b8e80941Smrg                  (long int) size, data,
2012b8e80941Smrg                  _mesa_enum_to_string(usage));
2013848b8605Smrg   }
2014848b8605Smrg
2015b8e80941Smrg   if (!no_error) {
2016b8e80941Smrg      if (size < 0) {
2017b8e80941Smrg         _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", func);
2018b8e80941Smrg         return;
2019b8e80941Smrg      }
2020848b8605Smrg
2021b8e80941Smrg      switch (usage) {
2022b8e80941Smrg      case GL_STREAM_DRAW_ARB:
2023b8e80941Smrg         valid_usage = (ctx->API != API_OPENGLES);
2024b8e80941Smrg         break;
2025b8e80941Smrg      case GL_STATIC_DRAW_ARB:
2026b8e80941Smrg      case GL_DYNAMIC_DRAW_ARB:
2027b8e80941Smrg         valid_usage = true;
2028b8e80941Smrg         break;
2029b8e80941Smrg      case GL_STREAM_READ_ARB:
2030b8e80941Smrg      case GL_STREAM_COPY_ARB:
2031b8e80941Smrg      case GL_STATIC_READ_ARB:
2032b8e80941Smrg      case GL_STATIC_COPY_ARB:
2033b8e80941Smrg      case GL_DYNAMIC_READ_ARB:
2034b8e80941Smrg      case GL_DYNAMIC_COPY_ARB:
2035b8e80941Smrg         valid_usage = _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx);
2036b8e80941Smrg         break;
2037b8e80941Smrg      default:
2038b8e80941Smrg         valid_usage = false;
2039b8e80941Smrg         break;
2040b8e80941Smrg      }
2041b8e80941Smrg
2042b8e80941Smrg      if (!valid_usage) {
2043b8e80941Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid usage: %s)", func,
2044b8e80941Smrg                     _mesa_enum_to_string(usage));
2045b8e80941Smrg         return;
2046b8e80941Smrg      }
2047b8e80941Smrg
2048b8e80941Smrg      if (bufObj->Immutable || bufObj->HandleAllocated) {
2049b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
2050b8e80941Smrg         return;
2051b8e80941Smrg      }
2052848b8605Smrg   }
2053848b8605Smrg
2054848b8605Smrg   /* Unmap the existing buffer.  We'll replace it now.  Not an error. */
2055848b8605Smrg   _mesa_buffer_unmap_all_mappings(ctx, bufObj);
2056848b8605Smrg
2057b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
2058848b8605Smrg
2059848b8605Smrg   bufObj->Written = GL_TRUE;
2060b8e80941Smrg   bufObj->MinMaxCacheDirty = true;
2061848b8605Smrg
2062848b8605Smrg#ifdef VBO_DEBUG
2063848b8605Smrg   printf("glBufferDataARB(%u, sz %ld, from %p, usage 0x%x)\n",
2064848b8605Smrg                bufObj->Name, size, data, usage);
2065848b8605Smrg#endif
2066848b8605Smrg
2067848b8605Smrg#ifdef BOUNDS_CHECK
2068848b8605Smrg   size += 100;
2069848b8605Smrg#endif
2070848b8605Smrg
2071b8e80941Smrg   assert(ctx->Driver.BufferData);
2072848b8605Smrg   if (!ctx->Driver.BufferData(ctx, target, size, data, usage,
2073848b8605Smrg                               GL_MAP_READ_BIT |
2074848b8605Smrg                               GL_MAP_WRITE_BIT |
2075848b8605Smrg                               GL_DYNAMIC_STORAGE_BIT,
2076848b8605Smrg                               bufObj)) {
2077b8e80941Smrg      if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
2078b8e80941Smrg         if (!no_error) {
2079b8e80941Smrg            /* From GL_AMD_pinned_memory:
2080b8e80941Smrg             *
2081b8e80941Smrg             *   INVALID_OPERATION is generated by BufferData if <target> is
2082b8e80941Smrg             *   EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be
2083b8e80941Smrg             *   mapped to the GPU address space.
2084b8e80941Smrg             */
2085b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
2086b8e80941Smrg         }
2087b8e80941Smrg      } else {
2088b8e80941Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
2089b8e80941Smrg      }
2090b8e80941Smrg   }
2091b8e80941Smrg}
2092b8e80941Smrg
2093b8e80941Smrgstatic void
2094b8e80941Smrgbuffer_data_error(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2095b8e80941Smrg                  GLenum target, GLsizeiptr size, const GLvoid *data,
2096b8e80941Smrg                  GLenum usage, const char *func)
2097b8e80941Smrg{
2098b8e80941Smrg   buffer_data(ctx, bufObj, target, size, data, usage, func, false);
2099b8e80941Smrg}
2100b8e80941Smrg
2101b8e80941Smrgstatic void
2102b8e80941Smrgbuffer_data_no_error(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2103b8e80941Smrg                     GLenum target, GLsizeiptr size, const GLvoid *data,
2104b8e80941Smrg                     GLenum usage, const char *func)
2105b8e80941Smrg{
2106b8e80941Smrg   buffer_data(ctx, bufObj, target, size, data, usage, func, true);
2107b8e80941Smrg}
2108b8e80941Smrg
2109b8e80941Smrgvoid
2110b8e80941Smrg_mesa_buffer_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2111b8e80941Smrg                  GLenum target, GLsizeiptr size, const GLvoid *data,
2112b8e80941Smrg                  GLenum usage, const char *func)
2113b8e80941Smrg{
2114b8e80941Smrg   buffer_data_error(ctx, bufObj, target, size, data, usage, func);
2115b8e80941Smrg}
2116b8e80941Smrg
2117b8e80941Smrgvoid GLAPIENTRY
2118b8e80941Smrg_mesa_BufferData_no_error(GLenum target, GLsizeiptr size, const GLvoid *data,
2119b8e80941Smrg                          GLenum usage)
2120b8e80941Smrg{
2121b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2122b8e80941Smrg
2123b8e80941Smrg   struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
2124b8e80941Smrg   buffer_data_no_error(ctx, *bufObj, target, size, data, usage,
2125b8e80941Smrg                        "glBufferData");
2126b8e80941Smrg}
2127b8e80941Smrg
2128b8e80941Smrgvoid GLAPIENTRY
2129b8e80941Smrg_mesa_BufferData(GLenum target, GLsizeiptr size,
2130b8e80941Smrg                 const GLvoid *data, GLenum usage)
2131b8e80941Smrg{
2132b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2133b8e80941Smrg   struct gl_buffer_object *bufObj;
2134b8e80941Smrg
2135b8e80941Smrg   bufObj = get_buffer(ctx, "glBufferData", target, GL_INVALID_OPERATION);
2136b8e80941Smrg   if (!bufObj)
2137b8e80941Smrg      return;
2138b8e80941Smrg
2139b8e80941Smrg   _mesa_buffer_data(ctx, bufObj, target, size, data, usage,
2140b8e80941Smrg                     "glBufferData");
2141b8e80941Smrg}
2142b8e80941Smrg
2143b8e80941Smrgvoid GLAPIENTRY
2144b8e80941Smrg_mesa_NamedBufferData_no_error(GLuint buffer, GLsizeiptr size,
2145b8e80941Smrg                               const GLvoid *data, GLenum usage)
2146b8e80941Smrg{
2147b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2148b8e80941Smrg
2149b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2150b8e80941Smrg   buffer_data_no_error(ctx, bufObj, GL_NONE, size, data, usage,
2151b8e80941Smrg                        "glNamedBufferData");
2152b8e80941Smrg}
2153b8e80941Smrg
2154b8e80941Smrgvoid GLAPIENTRY
2155b8e80941Smrg_mesa_NamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid *data,
2156b8e80941Smrg                      GLenum usage)
2157b8e80941Smrg{
2158b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2159b8e80941Smrg   struct gl_buffer_object *bufObj;
2160b8e80941Smrg
2161b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glNamedBufferData");
2162b8e80941Smrg   if (!bufObj)
2163b8e80941Smrg      return;
2164b8e80941Smrg
2165b8e80941Smrg   /* In direct state access, buffer objects have an unspecified target since
2166b8e80941Smrg    * they are not required to be bound.
2167b8e80941Smrg    */
2168b8e80941Smrg   _mesa_buffer_data(ctx, bufObj, GL_NONE, size, data, usage,
2169b8e80941Smrg                     "glNamedBufferData");
2170b8e80941Smrg}
2171b8e80941Smrg
2172b8e80941Smrg
2173b8e80941Smrgstatic bool
2174b8e80941Smrgvalidate_buffer_sub_data(struct gl_context *ctx,
2175b8e80941Smrg                         struct gl_buffer_object *bufObj,
2176b8e80941Smrg                         GLintptr offset, GLsizeiptr size,
2177b8e80941Smrg                         const char *func)
2178b8e80941Smrg{
2179b8e80941Smrg   if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size,
2180b8e80941Smrg                                         true, func)) {
2181b8e80941Smrg      /* error already recorded */
2182b8e80941Smrg      return false;
2183b8e80941Smrg   }
2184b8e80941Smrg
2185b8e80941Smrg   if (bufObj->Immutable &&
2186b8e80941Smrg       !(bufObj->StorageFlags & GL_DYNAMIC_STORAGE_BIT)) {
2187b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
2188b8e80941Smrg      return false;
2189b8e80941Smrg   }
2190b8e80941Smrg
2191b8e80941Smrg   if ((bufObj->Usage == GL_STATIC_DRAW ||
2192b8e80941Smrg        bufObj->Usage == GL_STATIC_COPY) &&
2193b8e80941Smrg       bufObj->NumSubDataCalls >= BUFFER_WARNING_CALL_COUNT - 1) {
2194b8e80941Smrg      /* If the application declared the buffer as static draw/copy or stream
2195b8e80941Smrg       * draw, it should not be frequently modified with glBufferSubData.
2196b8e80941Smrg       */
2197b8e80941Smrg      BUFFER_USAGE_WARNING(ctx,
2198b8e80941Smrg                           "using %s(buffer %u, offset %u, size %u) to "
2199b8e80941Smrg                           "update a %s buffer",
2200b8e80941Smrg                           func, bufObj->Name, offset, size,
2201b8e80941Smrg                           _mesa_enum_to_string(bufObj->Usage));
2202b8e80941Smrg   }
2203b8e80941Smrg
2204b8e80941Smrg   return true;
2205b8e80941Smrg}
2206b8e80941Smrg
2207b8e80941Smrg
2208b8e80941Smrg/**
2209b8e80941Smrg * Implementation for glBufferSubData and glNamedBufferSubData.
2210b8e80941Smrg *
2211b8e80941Smrg * \param ctx     GL context.
2212b8e80941Smrg * \param bufObj  The buffer object.
2213b8e80941Smrg * \param offset  Offset of the first byte of the subdata range.
2214b8e80941Smrg * \param size    Size, in bytes, of the subdata range.
2215b8e80941Smrg * \param data    The data store.
2216b8e80941Smrg * \param func  Name of calling function for recording errors.
2217b8e80941Smrg *
2218b8e80941Smrg */
2219b8e80941Smrgvoid
2220b8e80941Smrg_mesa_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2221b8e80941Smrg                      GLintptr offset, GLsizeiptr size, const GLvoid *data)
2222b8e80941Smrg{
2223b8e80941Smrg   if (size == 0)
2224b8e80941Smrg      return;
2225b8e80941Smrg
2226b8e80941Smrg   bufObj->NumSubDataCalls++;
2227b8e80941Smrg   bufObj->Written = GL_TRUE;
2228b8e80941Smrg   bufObj->MinMaxCacheDirty = true;
2229b8e80941Smrg
2230b8e80941Smrg   assert(ctx->Driver.BufferSubData);
2231b8e80941Smrg   ctx->Driver.BufferSubData(ctx, offset, size, data, bufObj);
2232b8e80941Smrg}
2233b8e80941Smrg
2234b8e80941Smrg
2235b8e80941Smrgstatic ALWAYS_INLINE void
2236b8e80941Smrgbuffer_sub_data(GLenum target, GLuint buffer, GLintptr offset,
2237b8e80941Smrg                GLsizeiptr size, const GLvoid *data,
2238b8e80941Smrg                bool dsa, bool no_error, const char *func)
2239b8e80941Smrg{
2240b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2241b8e80941Smrg   struct gl_buffer_object *bufObj;
2242b8e80941Smrg
2243b8e80941Smrg   if (dsa) {
2244b8e80941Smrg      if (no_error) {
2245b8e80941Smrg         bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2246b8e80941Smrg      } else {
2247b8e80941Smrg         bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, func);
2248b8e80941Smrg         if (!bufObj)
2249b8e80941Smrg            return;
2250b8e80941Smrg      }
2251b8e80941Smrg   } else {
2252b8e80941Smrg      if (no_error) {
2253b8e80941Smrg         struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
2254b8e80941Smrg         bufObj = *bufObjPtr;
2255b8e80941Smrg      } else {
2256b8e80941Smrg         bufObj = get_buffer(ctx, func, target, GL_INVALID_OPERATION);
2257b8e80941Smrg         if (!bufObj)
2258b8e80941Smrg            return;
2259b8e80941Smrg      }
2260848b8605Smrg   }
2261b8e80941Smrg
2262b8e80941Smrg   if (no_error || validate_buffer_sub_data(ctx, bufObj, offset, size, func))
2263b8e80941Smrg      _mesa_buffer_sub_data(ctx, bufObj, offset, size, data);
2264b8e80941Smrg}
2265b8e80941Smrg
2266b8e80941Smrg
2267b8e80941Smrgvoid GLAPIENTRY
2268b8e80941Smrg_mesa_BufferSubData_no_error(GLenum target, GLintptr offset,
2269b8e80941Smrg                             GLsizeiptr size, const GLvoid *data)
2270b8e80941Smrg{
2271b8e80941Smrg   buffer_sub_data(target, 0, offset, size, data, false, true,
2272b8e80941Smrg                   "glBufferSubData");
2273b8e80941Smrg}
2274b8e80941Smrg
2275b8e80941Smrg
2276b8e80941Smrgvoid GLAPIENTRY
2277b8e80941Smrg_mesa_BufferSubData(GLenum target, GLintptr offset,
2278b8e80941Smrg                    GLsizeiptr size, const GLvoid *data)
2279b8e80941Smrg{
2280b8e80941Smrg   buffer_sub_data(target, 0, offset, size, data, false, false,
2281b8e80941Smrg                   "glBufferSubData");
2282b8e80941Smrg}
2283b8e80941Smrg
2284b8e80941Smrgvoid GLAPIENTRY
2285b8e80941Smrg_mesa_NamedBufferSubData_no_error(GLuint buffer, GLintptr offset,
2286b8e80941Smrg                                  GLsizeiptr size, const GLvoid *data)
2287b8e80941Smrg{
2288b8e80941Smrg   buffer_sub_data(0, buffer, offset, size, data, true, true,
2289b8e80941Smrg                   "glNamedBufferSubData");
2290b8e80941Smrg}
2291b8e80941Smrg
2292b8e80941Smrgvoid GLAPIENTRY
2293b8e80941Smrg_mesa_NamedBufferSubData(GLuint buffer, GLintptr offset,
2294b8e80941Smrg                         GLsizeiptr size, const GLvoid *data)
2295b8e80941Smrg{
2296b8e80941Smrg   buffer_sub_data(0, buffer, offset, size, data, true, false,
2297b8e80941Smrg                   "glNamedBufferSubData");
2298848b8605Smrg}
2299848b8605Smrg
2300848b8605Smrg
2301848b8605Smrgvoid GLAPIENTRY
2302b8e80941Smrg_mesa_GetBufferSubData(GLenum target, GLintptr offset,
2303b8e80941Smrg                       GLsizeiptr size, GLvoid *data)
2304848b8605Smrg{
2305848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2306848b8605Smrg   struct gl_buffer_object *bufObj;
2307848b8605Smrg
2308b8e80941Smrg   bufObj = get_buffer(ctx, "glGetBufferSubData", target,
2309b8e80941Smrg                       GL_INVALID_OPERATION);
2310b8e80941Smrg   if (!bufObj)
2311848b8605Smrg      return;
2312848b8605Smrg
2313b8e80941Smrg   if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
2314b8e80941Smrg                                         "glGetBufferSubData")) {
2315848b8605Smrg      return;
2316848b8605Smrg   }
2317848b8605Smrg
2318b8e80941Smrg   assert(ctx->Driver.GetBufferSubData);
2319b8e80941Smrg   ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
2320848b8605Smrg}
2321848b8605Smrg
2322848b8605Smrgvoid GLAPIENTRY
2323b8e80941Smrg_mesa_GetNamedBufferSubData(GLuint buffer, GLintptr offset,
2324b8e80941Smrg                            GLsizeiptr size, GLvoid *data)
2325848b8605Smrg{
2326848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2327848b8605Smrg   struct gl_buffer_object *bufObj;
2328848b8605Smrg
2329b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2330b8e80941Smrg                                       "glGetNamedBufferSubData");
2331b8e80941Smrg   if (!bufObj)
2332b8e80941Smrg      return;
2333b8e80941Smrg
2334b8e80941Smrg   if (!buffer_object_subdata_range_good(ctx, bufObj, offset, size, false,
2335b8e80941Smrg                                         "glGetNamedBufferSubData")) {
2336848b8605Smrg      return;
2337848b8605Smrg   }
2338848b8605Smrg
2339b8e80941Smrg   assert(ctx->Driver.GetBufferSubData);
2340b8e80941Smrg   ctx->Driver.GetBufferSubData(ctx, offset, size, data, bufObj);
2341848b8605Smrg}
2342848b8605Smrg
2343848b8605Smrg
2344b8e80941Smrg/**
2345b8e80941Smrg * \param subdata   true if caller is *SubData, false if *Data
2346b8e80941Smrg */
2347b8e80941Smrgstatic ALWAYS_INLINE void
2348b8e80941Smrgclear_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *bufObj,
2349b8e80941Smrg                      GLenum internalformat, GLintptr offset, GLsizeiptr size,
2350b8e80941Smrg                      GLenum format, GLenum type, const GLvoid *data,
2351b8e80941Smrg                      const char *func, bool subdata, bool no_error)
2352848b8605Smrg{
2353848b8605Smrg   mesa_format mesaFormat;
2354848b8605Smrg   GLubyte clearValue[MAX_PIXEL_BYTES];
2355848b8605Smrg   GLsizeiptr clearValueSize;
2356848b8605Smrg
2357b8e80941Smrg   /* This checks for disallowed mappings. */
2358b8e80941Smrg   if (!no_error && !buffer_object_subdata_range_good(ctx, bufObj, offset, size,
2359b8e80941Smrg                                                      subdata, func)) {
2360848b8605Smrg      return;
2361848b8605Smrg   }
2362848b8605Smrg
2363b8e80941Smrg   if (no_error) {
2364b8e80941Smrg      mesaFormat = _mesa_get_texbuffer_format(ctx, internalformat);
2365b8e80941Smrg   } else {
2366b8e80941Smrg      mesaFormat = validate_clear_buffer_format(ctx, internalformat,
2367b8e80941Smrg                                                format, type, func);
2368848b8605Smrg   }
2369848b8605Smrg
2370b8e80941Smrg   if (mesaFormat == MESA_FORMAT_NONE)
2371848b8605Smrg      return;
2372848b8605Smrg
2373848b8605Smrg   clearValueSize = _mesa_get_format_bytes(mesaFormat);
2374b8e80941Smrg   if (!no_error &&
2375b8e80941Smrg       (offset % clearValueSize != 0 || size % clearValueSize != 0)) {
2376848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2377b8e80941Smrg                  "%s(offset or size is not a multiple of "
2378b8e80941Smrg                  "internalformat size)", func);
2379848b8605Smrg      return;
2380848b8605Smrg   }
2381848b8605Smrg
2382b8e80941Smrg   /* Bail early. Negative size has already been checked. */
2383b8e80941Smrg   if (size == 0)
2384b8e80941Smrg      return;
2385b8e80941Smrg
2386b8e80941Smrg   bufObj->MinMaxCacheDirty = true;
2387b8e80941Smrg
2388848b8605Smrg   if (data == NULL) {
2389848b8605Smrg      /* clear to zeros, per the spec */
2390b8e80941Smrg      ctx->Driver.ClearBufferSubData(ctx, offset, size,
2391848b8605Smrg                                     NULL, clearValueSize, bufObj);
2392848b8605Smrg      return;
2393848b8605Smrg   }
2394848b8605Smrg
2395848b8605Smrg   if (!convert_clear_buffer_data(ctx, mesaFormat, clearValue,
2396b8e80941Smrg                                  format, type, data, func)) {
2397848b8605Smrg      return;
2398848b8605Smrg   }
2399848b8605Smrg
2400b8e80941Smrg   ctx->Driver.ClearBufferSubData(ctx, offset, size,
2401848b8605Smrg                                  clearValue, clearValueSize, bufObj);
2402848b8605Smrg}
2403848b8605Smrg
2404b8e80941Smrgstatic void
2405b8e80941Smrgclear_buffer_sub_data_error(struct gl_context *ctx,
2406b8e80941Smrg                            struct gl_buffer_object *bufObj,
2407b8e80941Smrg                            GLenum internalformat, GLintptr offset,
2408b8e80941Smrg                            GLsizeiptr size, GLenum format, GLenum type,
2409b8e80941Smrg                            const GLvoid *data, const char *func, bool subdata)
2410b8e80941Smrg{
2411b8e80941Smrg   clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, format,
2412b8e80941Smrg                         type, data, func, subdata, false);
2413b8e80941Smrg}
2414b8e80941Smrg
2415b8e80941Smrg
2416b8e80941Smrgstatic void
2417b8e80941Smrgclear_buffer_sub_data_no_error(struct gl_context *ctx,
2418b8e80941Smrg                               struct gl_buffer_object *bufObj,
2419b8e80941Smrg                               GLenum internalformat, GLintptr offset,
2420b8e80941Smrg                               GLsizeiptr size, GLenum format, GLenum type,
2421b8e80941Smrg                               const GLvoid *data, const char *func,
2422b8e80941Smrg                               bool subdata)
2423b8e80941Smrg{
2424b8e80941Smrg   clear_buffer_sub_data(ctx, bufObj, internalformat, offset, size, format,
2425b8e80941Smrg                         type, data, func, subdata, true);
2426b8e80941Smrg}
2427b8e80941Smrg
2428848b8605Smrg
2429848b8605Smrgvoid GLAPIENTRY
2430b8e80941Smrg_mesa_ClearBufferData_no_error(GLenum target, GLenum internalformat,
2431b8e80941Smrg                               GLenum format, GLenum type, const GLvoid *data)
2432848b8605Smrg{
2433848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2434848b8605Smrg
2435b8e80941Smrg   struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
2436b8e80941Smrg   clear_buffer_sub_data_no_error(ctx, *bufObj, internalformat, 0,
2437b8e80941Smrg                                  (*bufObj)->Size, format, type, data,
2438b8e80941Smrg                                  "glClearBufferData", false);
2439b8e80941Smrg}
2440848b8605Smrg
2441848b8605Smrg
2442b8e80941Smrgvoid GLAPIENTRY
2443b8e80941Smrg_mesa_ClearBufferData(GLenum target, GLenum internalformat, GLenum format,
2444b8e80941Smrg                      GLenum type, const GLvoid *data)
2445b8e80941Smrg{
2446b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2447b8e80941Smrg   struct gl_buffer_object *bufObj;
2448848b8605Smrg
2449b8e80941Smrg   bufObj = get_buffer(ctx, "glClearBufferData", target, GL_INVALID_VALUE);
2450b8e80941Smrg   if (!bufObj)
2451848b8605Smrg      return;
2452848b8605Smrg
2453b8e80941Smrg   clear_buffer_sub_data_error(ctx, bufObj, internalformat, 0, bufObj->Size,
2454b8e80941Smrg                               format, type, data, "glClearBufferData", false);
2455848b8605Smrg}
2456848b8605Smrg
2457848b8605Smrg
2458b8e80941Smrgvoid GLAPIENTRY
2459b8e80941Smrg_mesa_ClearNamedBufferData_no_error(GLuint buffer, GLenum internalformat,
2460b8e80941Smrg                                    GLenum format, GLenum type,
2461b8e80941Smrg                                    const GLvoid *data)
2462848b8605Smrg{
2463848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2464848b8605Smrg
2465b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2466b8e80941Smrg   clear_buffer_sub_data_no_error(ctx, bufObj, internalformat, 0, bufObj->Size,
2467b8e80941Smrg                                  format, type, data, "glClearNamedBufferData",
2468b8e80941Smrg                                  false);
2469b8e80941Smrg}
2470848b8605Smrg
2471848b8605Smrg
2472b8e80941Smrgvoid GLAPIENTRY
2473b8e80941Smrg_mesa_ClearNamedBufferData(GLuint buffer, GLenum internalformat,
2474b8e80941Smrg                           GLenum format, GLenum type, const GLvoid *data)
2475b8e80941Smrg{
2476b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2477b8e80941Smrg   struct gl_buffer_object *bufObj;
2478848b8605Smrg
2479b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glClearNamedBufferData");
2480848b8605Smrg   if (!bufObj)
2481b8e80941Smrg      return;
2482848b8605Smrg
2483b8e80941Smrg   clear_buffer_sub_data_error(ctx, bufObj, internalformat, 0, bufObj->Size,
2484b8e80941Smrg                               format, type, data, "glClearNamedBufferData",
2485b8e80941Smrg                               false);
2486b8e80941Smrg}
2487848b8605Smrg
2488848b8605Smrg
2489b8e80941Smrgvoid GLAPIENTRY
2490b8e80941Smrg_mesa_ClearBufferSubData_no_error(GLenum target, GLenum internalformat,
2491b8e80941Smrg                                  GLintptr offset, GLsizeiptr size,
2492b8e80941Smrg                                  GLenum format, GLenum type,
2493b8e80941Smrg                                  const GLvoid *data)
2494b8e80941Smrg{
2495b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2496848b8605Smrg
2497b8e80941Smrg   struct gl_buffer_object **bufObj = get_buffer_target(ctx, target);
2498b8e80941Smrg   clear_buffer_sub_data_no_error(ctx, *bufObj, internalformat, offset, size,
2499b8e80941Smrg                                  format, type, data, "glClearBufferSubData",
2500b8e80941Smrg                                  true);
2501b8e80941Smrg}
2502848b8605Smrg
2503848b8605Smrg
2504b8e80941Smrgvoid GLAPIENTRY
2505b8e80941Smrg_mesa_ClearBufferSubData(GLenum target, GLenum internalformat,
2506b8e80941Smrg                         GLintptr offset, GLsizeiptr size,
2507b8e80941Smrg                         GLenum format, GLenum type,
2508b8e80941Smrg                         const GLvoid *data)
2509b8e80941Smrg{
2510b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2511b8e80941Smrg   struct gl_buffer_object *bufObj;
2512848b8605Smrg
2513b8e80941Smrg   bufObj = get_buffer(ctx, "glClearBufferSubData", target, GL_INVALID_VALUE);
2514b8e80941Smrg   if (!bufObj)
2515b8e80941Smrg      return;
2516b8e80941Smrg
2517b8e80941Smrg   clear_buffer_sub_data_error(ctx, bufObj, internalformat, offset, size,
2518b8e80941Smrg                               format, type, data, "glClearBufferSubData",
2519b8e80941Smrg                               true);
2520b8e80941Smrg}
2521848b8605Smrg
2522848b8605Smrg
2523b8e80941Smrgvoid GLAPIENTRY
2524b8e80941Smrg_mesa_ClearNamedBufferSubData_no_error(GLuint buffer, GLenum internalformat,
2525b8e80941Smrg                                       GLintptr offset, GLsizeiptr size,
2526b8e80941Smrg                                       GLenum format, GLenum type,
2527b8e80941Smrg                                       const GLvoid *data)
2528b8e80941Smrg{
2529b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2530b8e80941Smrg
2531b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2532b8e80941Smrg   clear_buffer_sub_data_no_error(ctx, bufObj, internalformat, offset, size,
2533b8e80941Smrg                                  format, type, data,
2534b8e80941Smrg                                  "glClearNamedBufferSubData", true);
2535848b8605Smrg}
2536848b8605Smrg
2537848b8605Smrg
2538b8e80941Smrgvoid GLAPIENTRY
2539b8e80941Smrg_mesa_ClearNamedBufferSubData(GLuint buffer, GLenum internalformat,
2540b8e80941Smrg                              GLintptr offset, GLsizeiptr size,
2541b8e80941Smrg                              GLenum format, GLenum type,
2542b8e80941Smrg                              const GLvoid *data)
2543848b8605Smrg{
2544848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2545848b8605Smrg   struct gl_buffer_object *bufObj;
2546848b8605Smrg
2547b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2548b8e80941Smrg                                       "glClearNamedBufferSubData");
2549848b8605Smrg   if (!bufObj)
2550b8e80941Smrg      return;
2551b8e80941Smrg
2552b8e80941Smrg   clear_buffer_sub_data_error(ctx, bufObj, internalformat, offset, size,
2553b8e80941Smrg                               format, type, data, "glClearNamedBufferSubData",
2554b8e80941Smrg                               true);
2555b8e80941Smrg}
2556b8e80941Smrg
2557b8e80941Smrgstatic GLboolean
2558b8e80941Smrgunmap_buffer(struct gl_context *ctx, struct gl_buffer_object *bufObj)
2559b8e80941Smrg{
2560b8e80941Smrg   GLboolean status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER);
2561b8e80941Smrg   bufObj->Mappings[MAP_USER].AccessFlags = 0;
2562b8e80941Smrg   assert(bufObj->Mappings[MAP_USER].Pointer == NULL);
2563b8e80941Smrg   assert(bufObj->Mappings[MAP_USER].Offset == 0);
2564b8e80941Smrg   assert(bufObj->Mappings[MAP_USER].Length == 0);
2565b8e80941Smrg
2566b8e80941Smrg   return status;
2567b8e80941Smrg}
2568b8e80941Smrg
2569b8e80941Smrgstatic GLboolean
2570b8e80941Smrgvalidate_and_unmap_buffer(struct gl_context *ctx,
2571b8e80941Smrg                          struct gl_buffer_object *bufObj,
2572b8e80941Smrg                          const char *func)
2573b8e80941Smrg{
2574b8e80941Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
2575848b8605Smrg
2576848b8605Smrg   if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
2577b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2578b8e80941Smrg                  "%s(buffer is not mapped)", func);
2579848b8605Smrg      return GL_FALSE;
2580848b8605Smrg   }
2581848b8605Smrg
2582848b8605Smrg#ifdef BOUNDS_CHECK
2583848b8605Smrg   if (bufObj->Access != GL_READ_ONLY_ARB) {
2584848b8605Smrg      GLubyte *buf = (GLubyte *) bufObj->Pointer;
2585848b8605Smrg      GLuint i;
2586848b8605Smrg      /* check that last 100 bytes are still = magic value */
2587848b8605Smrg      for (i = 0; i < 100; i++) {
2588848b8605Smrg         GLuint pos = bufObj->Size - i - 1;
2589848b8605Smrg         if (buf[pos] != 123) {
2590848b8605Smrg            _mesa_warning(ctx, "Out of bounds buffer object write detected"
2591848b8605Smrg                          " at position %d (value = %u)\n",
2592848b8605Smrg                          pos, buf[pos]);
2593848b8605Smrg         }
2594848b8605Smrg      }
2595848b8605Smrg   }
2596848b8605Smrg#endif
2597848b8605Smrg
2598848b8605Smrg#ifdef VBO_DEBUG
2599848b8605Smrg   if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
2600848b8605Smrg      GLuint i, unchanged = 0;
2601848b8605Smrg      GLubyte *b = (GLubyte *) bufObj->Pointer;
2602848b8605Smrg      GLint pos = -1;
2603848b8605Smrg      /* check which bytes changed */
2604848b8605Smrg      for (i = 0; i < bufObj->Size - 1; i++) {
2605848b8605Smrg         if (b[i] == (i & 0xff) && b[i+1] == ((i+1) & 0xff)) {
2606848b8605Smrg            unchanged++;
2607848b8605Smrg            if (pos == -1)
2608848b8605Smrg               pos = i;
2609848b8605Smrg         }
2610848b8605Smrg      }
2611848b8605Smrg      if (unchanged) {
2612848b8605Smrg         printf("glUnmapBufferARB(%u): %u of %ld unchanged, starting at %d\n",
2613848b8605Smrg                      bufObj->Name, unchanged, bufObj->Size, pos);
2614848b8605Smrg      }
2615848b8605Smrg   }
2616848b8605Smrg#endif
2617848b8605Smrg
2618b8e80941Smrg   return unmap_buffer(ctx, bufObj);
2619848b8605Smrg}
2620848b8605Smrg
2621b8e80941SmrgGLboolean GLAPIENTRY
2622b8e80941Smrg_mesa_UnmapBuffer_no_error(GLenum target)
2623b8e80941Smrg{
2624b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2625b8e80941Smrg   struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
2626b8e80941Smrg   struct gl_buffer_object *bufObj = *bufObjPtr;
2627b8e80941Smrg
2628b8e80941Smrg   return unmap_buffer(ctx, bufObj);
2629b8e80941Smrg}
2630848b8605Smrg
2631b8e80941SmrgGLboolean GLAPIENTRY
2632b8e80941Smrg_mesa_UnmapBuffer(GLenum target)
2633848b8605Smrg{
2634848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2635848b8605Smrg   struct gl_buffer_object *bufObj;
2636848b8605Smrg
2637b8e80941Smrg   bufObj = get_buffer(ctx, "glUnmapBuffer", target, GL_INVALID_OPERATION);
2638848b8605Smrg   if (!bufObj)
2639b8e80941Smrg      return GL_FALSE;
2640848b8605Smrg
2641b8e80941Smrg   return validate_and_unmap_buffer(ctx, bufObj, "glUnmapBuffer");
2642848b8605Smrg}
2643848b8605Smrg
2644b8e80941SmrgGLboolean GLAPIENTRY
2645b8e80941Smrg_mesa_UnmapNamedBuffer_no_error(GLuint buffer)
2646b8e80941Smrg{
2647b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2648b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
2649848b8605Smrg
2650b8e80941Smrg   return unmap_buffer(ctx, bufObj);
2651b8e80941Smrg}
2652b8e80941Smrg
2653b8e80941SmrgGLboolean GLAPIENTRY
2654b8e80941Smrg_mesa_UnmapNamedBuffer(GLuint buffer)
2655848b8605Smrg{
2656848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2657848b8605Smrg   struct gl_buffer_object *bufObj;
2658848b8605Smrg
2659b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glUnmapNamedBuffer");
2660848b8605Smrg   if (!bufObj)
2661b8e80941Smrg      return GL_FALSE;
2662b8e80941Smrg
2663b8e80941Smrg   return validate_and_unmap_buffer(ctx, bufObj, "glUnmapNamedBuffer");
2664b8e80941Smrg}
2665b8e80941Smrg
2666848b8605Smrg
2667b8e80941Smrgstatic bool
2668b8e80941Smrgget_buffer_parameter(struct gl_context *ctx,
2669b8e80941Smrg                     struct gl_buffer_object *bufObj, GLenum pname,
2670b8e80941Smrg                     GLint64 *params, const char *func)
2671b8e80941Smrg{
2672848b8605Smrg   switch (pname) {
2673848b8605Smrg   case GL_BUFFER_SIZE_ARB:
2674848b8605Smrg      *params = bufObj->Size;
2675b8e80941Smrg      break;
2676848b8605Smrg   case GL_BUFFER_USAGE_ARB:
2677848b8605Smrg      *params = bufObj->Usage;
2678b8e80941Smrg      break;
2679848b8605Smrg   case GL_BUFFER_ACCESS_ARB:
2680848b8605Smrg      *params = simplified_access_mode(ctx,
2681b8e80941Smrg                            bufObj->Mappings[MAP_USER].AccessFlags);
2682b8e80941Smrg      break;
2683b8e80941Smrg   case GL_BUFFER_MAPPED_ARB:
2684b8e80941Smrg      *params = _mesa_bufferobj_mapped(bufObj, MAP_USER);
2685b8e80941Smrg      break;
2686848b8605Smrg   case GL_BUFFER_ACCESS_FLAGS:
2687848b8605Smrg      if (!ctx->Extensions.ARB_map_buffer_range)
2688848b8605Smrg         goto invalid_pname;
2689848b8605Smrg      *params = bufObj->Mappings[MAP_USER].AccessFlags;
2690b8e80941Smrg      break;
2691848b8605Smrg   case GL_BUFFER_MAP_OFFSET:
2692848b8605Smrg      if (!ctx->Extensions.ARB_map_buffer_range)
2693848b8605Smrg         goto invalid_pname;
2694848b8605Smrg      *params = bufObj->Mappings[MAP_USER].Offset;
2695b8e80941Smrg      break;
2696848b8605Smrg   case GL_BUFFER_MAP_LENGTH:
2697848b8605Smrg      if (!ctx->Extensions.ARB_map_buffer_range)
2698848b8605Smrg         goto invalid_pname;
2699848b8605Smrg      *params = bufObj->Mappings[MAP_USER].Length;
2700b8e80941Smrg      break;
2701848b8605Smrg   case GL_BUFFER_IMMUTABLE_STORAGE:
2702848b8605Smrg      if (!ctx->Extensions.ARB_buffer_storage)
2703848b8605Smrg         goto invalid_pname;
2704848b8605Smrg      *params = bufObj->Immutable;
2705b8e80941Smrg      break;
2706848b8605Smrg   case GL_BUFFER_STORAGE_FLAGS:
2707848b8605Smrg      if (!ctx->Extensions.ARB_buffer_storage)
2708848b8605Smrg         goto invalid_pname;
2709848b8605Smrg      *params = bufObj->StorageFlags;
2710b8e80941Smrg      break;
2711848b8605Smrg   default:
2712b8e80941Smrg      goto invalid_pname;
2713848b8605Smrg   }
2714848b8605Smrg
2715b8e80941Smrg   return true;
2716b8e80941Smrg
2717848b8605Smrginvalid_pname:
2718b8e80941Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid pname: %s)", func,
2719b8e80941Smrg               _mesa_enum_to_string(pname));
2720b8e80941Smrg   return false;
2721b8e80941Smrg}
2722b8e80941Smrg
2723b8e80941Smrgvoid GLAPIENTRY
2724b8e80941Smrg_mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
2725b8e80941Smrg{
2726b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2727b8e80941Smrg   struct gl_buffer_object *bufObj;
2728b8e80941Smrg   GLint64 parameter;
2729b8e80941Smrg
2730b8e80941Smrg   bufObj = get_buffer(ctx, "glGetBufferParameteriv", target,
2731b8e80941Smrg                       GL_INVALID_OPERATION);
2732b8e80941Smrg   if (!bufObj)
2733b8e80941Smrg      return;
2734b8e80941Smrg
2735b8e80941Smrg   if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2736b8e80941Smrg                             "glGetBufferParameteriv"))
2737b8e80941Smrg      return; /* Error already recorded. */
2738b8e80941Smrg
2739b8e80941Smrg   *params = (GLint) parameter;
2740b8e80941Smrg}
2741b8e80941Smrg
2742b8e80941Smrgvoid GLAPIENTRY
2743b8e80941Smrg_mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
2744b8e80941Smrg{
2745b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2746b8e80941Smrg   struct gl_buffer_object *bufObj;
2747b8e80941Smrg   GLint64 parameter;
2748b8e80941Smrg
2749b8e80941Smrg   bufObj = get_buffer(ctx, "glGetBufferParameteri64v", target,
2750b8e80941Smrg                       GL_INVALID_OPERATION);
2751b8e80941Smrg   if (!bufObj)
2752b8e80941Smrg      return;
2753b8e80941Smrg
2754b8e80941Smrg   if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2755b8e80941Smrg                             "glGetBufferParameteri64v"))
2756b8e80941Smrg      return; /* Error already recorded. */
2757b8e80941Smrg
2758b8e80941Smrg   *params = parameter;
2759b8e80941Smrg}
2760b8e80941Smrg
2761b8e80941Smrgvoid GLAPIENTRY
2762b8e80941Smrg_mesa_GetNamedBufferParameteriv(GLuint buffer, GLenum pname, GLint *params)
2763b8e80941Smrg{
2764b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2765b8e80941Smrg   struct gl_buffer_object *bufObj;
2766b8e80941Smrg   GLint64 parameter;
2767b8e80941Smrg
2768b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2769b8e80941Smrg                                       "glGetNamedBufferParameteriv");
2770b8e80941Smrg   if (!bufObj)
2771b8e80941Smrg      return;
2772b8e80941Smrg
2773b8e80941Smrg   if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2774b8e80941Smrg                             "glGetNamedBufferParameteriv"))
2775b8e80941Smrg      return; /* Error already recorded. */
2776b8e80941Smrg
2777b8e80941Smrg   *params = (GLint) parameter;
2778b8e80941Smrg}
2779b8e80941Smrg
2780b8e80941Smrgvoid GLAPIENTRY
2781b8e80941Smrg_mesa_GetNamedBufferParameteri64v(GLuint buffer, GLenum pname,
2782b8e80941Smrg                                  GLint64 *params)
2783b8e80941Smrg{
2784b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2785b8e80941Smrg   struct gl_buffer_object *bufObj;
2786b8e80941Smrg   GLint64 parameter;
2787b8e80941Smrg
2788b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2789b8e80941Smrg                                       "glGetNamedBufferParameteri64v");
2790b8e80941Smrg   if (!bufObj)
2791b8e80941Smrg      return;
2792b8e80941Smrg
2793b8e80941Smrg   if (!get_buffer_parameter(ctx, bufObj, pname, &parameter,
2794b8e80941Smrg                             "glGetNamedBufferParameteri64v"))
2795b8e80941Smrg      return; /* Error already recorded. */
2796b8e80941Smrg
2797b8e80941Smrg   *params = parameter;
2798848b8605Smrg}
2799848b8605Smrg
2800848b8605Smrg
2801848b8605Smrgvoid GLAPIENTRY
2802848b8605Smrg_mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params)
2803848b8605Smrg{
2804848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2805b8e80941Smrg   struct gl_buffer_object *bufObj;
2806848b8605Smrg
2807b8e80941Smrg   if (pname != GL_BUFFER_MAP_POINTER) {
2808b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointerv(pname != "
2809b8e80941Smrg                  "GL_BUFFER_MAP_POINTER)");
2810848b8605Smrg      return;
2811848b8605Smrg   }
2812848b8605Smrg
2813b8e80941Smrg   bufObj = get_buffer(ctx, "glGetBufferPointerv", target,
2814848b8605Smrg                       GL_INVALID_OPERATION);
2815848b8605Smrg   if (!bufObj)
2816848b8605Smrg      return;
2817848b8605Smrg
2818848b8605Smrg   *params = bufObj->Mappings[MAP_USER].Pointer;
2819848b8605Smrg}
2820848b8605Smrg
2821848b8605Smrgvoid GLAPIENTRY
2822b8e80941Smrg_mesa_GetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid **params)
2823848b8605Smrg{
2824848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2825b8e80941Smrg   struct gl_buffer_object *bufObj;
2826848b8605Smrg
2827b8e80941Smrg   if (pname != GL_BUFFER_MAP_POINTER) {
2828b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedBufferPointerv(pname != "
2829b8e80941Smrg                  "GL_BUFFER_MAP_POINTER)");
2830848b8605Smrg      return;
2831b8e80941Smrg   }
2832848b8605Smrg
2833b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
2834b8e80941Smrg                                       "glGetNamedBufferPointerv");
2835b8e80941Smrg   if (!bufObj)
2836848b8605Smrg      return;
2837848b8605Smrg
2838b8e80941Smrg   *params = bufObj->Mappings[MAP_USER].Pointer;
2839b8e80941Smrg}
2840b8e80941Smrg
2841b8e80941Smrg
2842b8e80941Smrgstatic void
2843b8e80941Smrgcopy_buffer_sub_data(struct gl_context *ctx, struct gl_buffer_object *src,
2844b8e80941Smrg                     struct gl_buffer_object *dst, GLintptr readOffset,
2845b8e80941Smrg                     GLintptr writeOffset, GLsizeiptr size, const char *func)
2846b8e80941Smrg{
2847848b8605Smrg   if (_mesa_check_disallowed_mapping(src)) {
2848848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2849b8e80941Smrg                  "%s(readBuffer is mapped)", func);
2850848b8605Smrg      return;
2851848b8605Smrg   }
2852848b8605Smrg
2853848b8605Smrg   if (_mesa_check_disallowed_mapping(dst)) {
2854848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2855b8e80941Smrg                  "%s(writeBuffer is mapped)", func);
2856848b8605Smrg      return;
2857848b8605Smrg   }
2858848b8605Smrg
2859848b8605Smrg   if (readOffset < 0) {
2860848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2861b8e80941Smrg                  "%s(readOffset %d < 0)", func, (int) readOffset);
2862848b8605Smrg      return;
2863848b8605Smrg   }
2864848b8605Smrg
2865848b8605Smrg   if (writeOffset < 0) {
2866848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2867b8e80941Smrg                  "%s(writeOffset %d < 0)", func, (int) writeOffset);
2868848b8605Smrg      return;
2869848b8605Smrg   }
2870848b8605Smrg
2871848b8605Smrg   if (size < 0) {
2872848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2873b8e80941Smrg                  "%s(size %d < 0)", func, (int) size);
2874848b8605Smrg      return;
2875848b8605Smrg   }
2876848b8605Smrg
2877848b8605Smrg   if (readOffset + size > src->Size) {
2878848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2879b8e80941Smrg                  "%s(readOffset %d + size %d > src_buffer_size %d)", func,
2880b8e80941Smrg                  (int) readOffset, (int) size, (int) src->Size);
2881848b8605Smrg      return;
2882848b8605Smrg   }
2883848b8605Smrg
2884848b8605Smrg   if (writeOffset + size > dst->Size) {
2885848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
2886b8e80941Smrg                  "%s(writeOffset %d + size %d > dst_buffer_size %d)", func,
2887b8e80941Smrg                  (int) writeOffset, (int) size, (int) dst->Size);
2888848b8605Smrg      return;
2889848b8605Smrg   }
2890848b8605Smrg
2891848b8605Smrg   if (src == dst) {
2892848b8605Smrg      if (readOffset + size <= writeOffset) {
2893848b8605Smrg         /* OK */
2894848b8605Smrg      }
2895848b8605Smrg      else if (writeOffset + size <= readOffset) {
2896848b8605Smrg         /* OK */
2897848b8605Smrg      }
2898848b8605Smrg      else {
2899848b8605Smrg         /* overlapping src/dst is illegal */
2900848b8605Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
2901b8e80941Smrg                     "%s(overlapping src/dst)", func);
2902848b8605Smrg         return;
2903848b8605Smrg      }
2904848b8605Smrg   }
2905848b8605Smrg
2906b8e80941Smrg   dst->MinMaxCacheDirty = true;
2907b8e80941Smrg
2908848b8605Smrg   ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
2909848b8605Smrg}
2910848b8605Smrg
2911b8e80941Smrgvoid GLAPIENTRY
2912b8e80941Smrg_mesa_CopyBufferSubData_no_error(GLenum readTarget, GLenum writeTarget,
2913b8e80941Smrg                                 GLintptr readOffset, GLintptr writeOffset,
2914b8e80941Smrg                                 GLsizeiptr size)
2915b8e80941Smrg{
2916b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2917b8e80941Smrg
2918b8e80941Smrg   struct gl_buffer_object **src_ptr = get_buffer_target(ctx, readTarget);
2919b8e80941Smrg   struct gl_buffer_object *src = *src_ptr;
2920848b8605Smrg
2921b8e80941Smrg   struct gl_buffer_object **dst_ptr = get_buffer_target(ctx, writeTarget);
2922b8e80941Smrg   struct gl_buffer_object *dst = *dst_ptr;
2923b8e80941Smrg
2924b8e80941Smrg   dst->MinMaxCacheDirty = true;
2925b8e80941Smrg   ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset,
2926b8e80941Smrg                                 size);
2927b8e80941Smrg}
2928b8e80941Smrg
2929b8e80941Smrgvoid GLAPIENTRY
2930b8e80941Smrg_mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
2931b8e80941Smrg                        GLintptr readOffset, GLintptr writeOffset,
2932b8e80941Smrg                        GLsizeiptr size)
2933848b8605Smrg{
2934848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
2935b8e80941Smrg   struct gl_buffer_object *src, *dst;
2936848b8605Smrg
2937b8e80941Smrg   src = get_buffer(ctx, "glCopyBufferSubData", readTarget,
2938b8e80941Smrg                    GL_INVALID_OPERATION);
2939b8e80941Smrg   if (!src)
2940b8e80941Smrg      return;
2941848b8605Smrg
2942b8e80941Smrg   dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget,
2943b8e80941Smrg                    GL_INVALID_OPERATION);
2944b8e80941Smrg   if (!dst)
2945b8e80941Smrg      return;
2946b8e80941Smrg
2947b8e80941Smrg   copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
2948b8e80941Smrg                        "glCopyBufferSubData");
2949b8e80941Smrg}
2950b8e80941Smrg
2951b8e80941Smrgvoid GLAPIENTRY
2952b8e80941Smrg_mesa_CopyNamedBufferSubData_no_error(GLuint readBuffer, GLuint writeBuffer,
2953b8e80941Smrg                                      GLintptr readOffset,
2954b8e80941Smrg                                      GLintptr writeOffset, GLsizeiptr size)
2955b8e80941Smrg{
2956b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2957b8e80941Smrg
2958b8e80941Smrg   struct gl_buffer_object *src = _mesa_lookup_bufferobj(ctx, readBuffer);
2959b8e80941Smrg   struct gl_buffer_object *dst = _mesa_lookup_bufferobj(ctx, writeBuffer);
2960b8e80941Smrg
2961b8e80941Smrg   dst->MinMaxCacheDirty = true;
2962b8e80941Smrg   ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset,
2963b8e80941Smrg                                 size);
2964b8e80941Smrg}
2965b8e80941Smrg
2966b8e80941Smrgvoid GLAPIENTRY
2967b8e80941Smrg_mesa_CopyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer,
2968b8e80941Smrg                             GLintptr readOffset, GLintptr writeOffset,
2969b8e80941Smrg                             GLsizeiptr size)
2970b8e80941Smrg{
2971b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2972b8e80941Smrg   struct gl_buffer_object *src, *dst;
2973b8e80941Smrg
2974b8e80941Smrg   src = _mesa_lookup_bufferobj_err(ctx, readBuffer,
2975b8e80941Smrg                                    "glCopyNamedBufferSubData");
2976b8e80941Smrg   if (!src)
2977b8e80941Smrg      return;
2978b8e80941Smrg
2979b8e80941Smrg   dst = _mesa_lookup_bufferobj_err(ctx, writeBuffer,
2980b8e80941Smrg                                    "glCopyNamedBufferSubData");
2981b8e80941Smrg   if (!dst)
2982b8e80941Smrg      return;
2983b8e80941Smrg
2984b8e80941Smrg   copy_buffer_sub_data(ctx, src, dst, readOffset, writeOffset, size,
2985b8e80941Smrg                        "glCopyNamedBufferSubData");
2986b8e80941Smrg}
2987b8e80941Smrg
2988b8e80941Smrgstatic bool
2989b8e80941Smrgvalidate_map_buffer_range(struct gl_context *ctx,
2990b8e80941Smrg                          struct gl_buffer_object *bufObj, GLintptr offset,
2991b8e80941Smrg                          GLsizeiptr length, GLbitfield access,
2992b8e80941Smrg                          const char *func)
2993b8e80941Smrg{
2994b8e80941Smrg   GLbitfield allowed_access;
2995b8e80941Smrg
2996b8e80941Smrg   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, false);
2997848b8605Smrg
2998848b8605Smrg   if (offset < 0) {
2999848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3000b8e80941Smrg                  "%s(offset %ld < 0)", func, (long) offset);
3001b8e80941Smrg      return false;
3002848b8605Smrg   }
3003848b8605Smrg
3004848b8605Smrg   if (length < 0) {
3005848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3006b8e80941Smrg                  "%s(length %ld < 0)", func, (long) length);
3007b8e80941Smrg      return false;
3008848b8605Smrg   }
3009848b8605Smrg
3010848b8605Smrg   /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
3011848b8605Smrg    *
3012848b8605Smrg    *     "An INVALID_OPERATION error is generated for any of the following
3013848b8605Smrg    *     conditions:
3014848b8605Smrg    *
3015848b8605Smrg    *     * <length> is zero."
3016b8e80941Smrg    *
3017b8e80941Smrg    * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec
3018b8e80941Smrg    * (30.10.2014) also says this, so it's no longer allowed for desktop GL,
3019b8e80941Smrg    * either.
3020848b8605Smrg    */
3021b8e80941Smrg   if (length == 0) {
3022b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(length = 0)", func);
3023b8e80941Smrg      return false;
3024848b8605Smrg   }
3025848b8605Smrg
3026848b8605Smrg   allowed_access = GL_MAP_READ_BIT |
3027848b8605Smrg                    GL_MAP_WRITE_BIT |
3028848b8605Smrg                    GL_MAP_INVALIDATE_RANGE_BIT |
3029848b8605Smrg                    GL_MAP_INVALIDATE_BUFFER_BIT |
3030848b8605Smrg                    GL_MAP_FLUSH_EXPLICIT_BIT |
3031848b8605Smrg                    GL_MAP_UNSYNCHRONIZED_BIT;
3032848b8605Smrg
3033848b8605Smrg   if (ctx->Extensions.ARB_buffer_storage) {
3034848b8605Smrg         allowed_access |= GL_MAP_PERSISTENT_BIT |
3035848b8605Smrg                           GL_MAP_COHERENT_BIT;
3036848b8605Smrg   }
3037848b8605Smrg
3038848b8605Smrg   if (access & ~allowed_access) {
3039b8e80941Smrg      /* generate an error if any bits other than those allowed are set */
3040b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3041b8e80941Smrg                  "%s(access has undefined bits set)", func);
3042b8e80941Smrg      return false;
3043848b8605Smrg   }
3044848b8605Smrg
3045848b8605Smrg   if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
3046848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3047b8e80941Smrg                  "%s(access indicates neither read or write)", func);
3048b8e80941Smrg      return false;
3049848b8605Smrg   }
3050848b8605Smrg
3051848b8605Smrg   if ((access & GL_MAP_READ_BIT) &&
3052848b8605Smrg       (access & (GL_MAP_INVALIDATE_RANGE_BIT |
3053848b8605Smrg                  GL_MAP_INVALIDATE_BUFFER_BIT |
3054848b8605Smrg                  GL_MAP_UNSYNCHRONIZED_BIT))) {
3055848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3056b8e80941Smrg                  "%s(read access with disallowed bits)", func);
3057b8e80941Smrg      return false;
3058848b8605Smrg   }
3059848b8605Smrg
3060848b8605Smrg   if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
3061848b8605Smrg       ((access & GL_MAP_WRITE_BIT) == 0)) {
3062848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3063b8e80941Smrg                  "%s(access has flush explicit without write)", func);
3064b8e80941Smrg      return false;
3065848b8605Smrg   }
3066848b8605Smrg
3067848b8605Smrg   if (access & GL_MAP_READ_BIT &&
3068848b8605Smrg       !(bufObj->StorageFlags & GL_MAP_READ_BIT)) {
3069848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3070b8e80941Smrg                  "%s(buffer does not allow read access)", func);
3071b8e80941Smrg      return false;
3072848b8605Smrg   }
3073848b8605Smrg
3074848b8605Smrg   if (access & GL_MAP_WRITE_BIT &&
3075848b8605Smrg       !(bufObj->StorageFlags & GL_MAP_WRITE_BIT)) {
3076848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3077b8e80941Smrg                  "%s(buffer does not allow write access)", func);
3078b8e80941Smrg      return false;
3079848b8605Smrg   }
3080848b8605Smrg
3081848b8605Smrg   if (access & GL_MAP_COHERENT_BIT &&
3082848b8605Smrg       !(bufObj->StorageFlags & GL_MAP_COHERENT_BIT)) {
3083848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3084b8e80941Smrg                  "%s(buffer does not allow coherent access)", func);
3085b8e80941Smrg      return false;
3086848b8605Smrg   }
3087848b8605Smrg
3088b8e80941Smrg   if (access & GL_MAP_PERSISTENT_BIT &&
3089b8e80941Smrg       !(bufObj->StorageFlags & GL_MAP_PERSISTENT_BIT)) {
3090848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3091b8e80941Smrg                  "%s(buffer does not allow persistent access)", func);
3092b8e80941Smrg      return false;
3093848b8605Smrg   }
3094848b8605Smrg
3095b8e80941Smrg   if (offset + length > bufObj->Size) {
3096848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3097b8e80941Smrg                  "%s(offset %lu + length %lu > buffer_size %lu)", func,
3098b8e80941Smrg                  (unsigned long) offset, (unsigned long) length,
3099b8e80941Smrg                  (unsigned long) bufObj->Size);
3100b8e80941Smrg      return false;
3101848b8605Smrg   }
3102848b8605Smrg
3103b8e80941Smrg   if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
3104b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3105b8e80941Smrg                  "%s(buffer already mapped)", func);
3106b8e80941Smrg      return false;
3107b8e80941Smrg   }
3108848b8605Smrg
3109b8e80941Smrg   if (access & GL_MAP_WRITE_BIT) {
3110b8e80941Smrg      bufObj->NumMapBufferWriteCalls++;
3111b8e80941Smrg      if ((bufObj->Usage == GL_STATIC_DRAW ||
3112b8e80941Smrg           bufObj->Usage == GL_STATIC_COPY) &&
3113b8e80941Smrg          bufObj->NumMapBufferWriteCalls >= BUFFER_WARNING_CALL_COUNT) {
3114b8e80941Smrg         BUFFER_USAGE_WARNING(ctx,
3115b8e80941Smrg                              "using %s(buffer %u, offset %u, length %u) to "
3116b8e80941Smrg                              "update a %s buffer",
3117b8e80941Smrg                              func, bufObj->Name, offset, length,
3118b8e80941Smrg                              _mesa_enum_to_string(bufObj->Usage));
3119b8e80941Smrg      }
3120b8e80941Smrg   }
3121848b8605Smrg
3122b8e80941Smrg   return true;
3123b8e80941Smrg}
3124848b8605Smrg
3125b8e80941Smrgstatic void *
3126b8e80941Smrgmap_buffer_range(struct gl_context *ctx, struct gl_buffer_object *bufObj,
3127b8e80941Smrg                 GLintptr offset, GLsizeiptr length, GLbitfield access,
3128b8e80941Smrg                 const char *func)
3129848b8605Smrg{
3130b8e80941Smrg   if (!bufObj->Size) {
3131b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(buffer size = 0)", func);
3132b8e80941Smrg      return NULL;
3133b8e80941Smrg   }
3134848b8605Smrg
3135b8e80941Smrg   assert(ctx->Driver.MapBufferRange);
3136b8e80941Smrg   void *map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj,
3137b8e80941Smrg                                          MAP_USER);
3138b8e80941Smrg   if (!map) {
3139b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(map failed)", func);
3140848b8605Smrg   }
3141b8e80941Smrg   else {
3142b8e80941Smrg      /* The driver callback should have set all these fields.
3143b8e80941Smrg       * This is important because other modules (like VBO) might call
3144b8e80941Smrg       * the driver function directly.
3145b8e80941Smrg       */
3146b8e80941Smrg      assert(bufObj->Mappings[MAP_USER].Pointer == map);
3147b8e80941Smrg      assert(bufObj->Mappings[MAP_USER].Length == length);
3148b8e80941Smrg      assert(bufObj->Mappings[MAP_USER].Offset == offset);
3149b8e80941Smrg      assert(bufObj->Mappings[MAP_USER].AccessFlags == access);
3150848b8605Smrg   }
3151848b8605Smrg
3152b8e80941Smrg   if (access & GL_MAP_WRITE_BIT) {
3153b8e80941Smrg      bufObj->Written = GL_TRUE;
3154b8e80941Smrg      bufObj->MinMaxCacheDirty = true;
3155848b8605Smrg   }
3156848b8605Smrg
3157b8e80941Smrg#ifdef VBO_DEBUG
3158b8e80941Smrg   if (strstr(func, "Range") == NULL) { /* If not MapRange */
3159b8e80941Smrg      printf("glMapBuffer(%u, sz %ld, access 0x%x)\n",
3160b8e80941Smrg            bufObj->Name, bufObj->Size, access);
3161b8e80941Smrg      /* Access must be write only */
3162b8e80941Smrg      if ((access & GL_MAP_WRITE_BIT) && (!(access & ~GL_MAP_WRITE_BIT))) {
3163b8e80941Smrg         GLuint i;
3164b8e80941Smrg         GLubyte *b = (GLubyte *) bufObj->Pointer;
3165b8e80941Smrg         for (i = 0; i < bufObj->Size; i++)
3166b8e80941Smrg            b[i] = i & 0xff;
3167b8e80941Smrg      }
3168b8e80941Smrg   }
3169b8e80941Smrg#endif
3170848b8605Smrg
3171b8e80941Smrg#ifdef BOUNDS_CHECK
3172b8e80941Smrg   if (strstr(func, "Range") == NULL) { /* If not MapRange */
3173b8e80941Smrg      GLubyte *buf = (GLubyte *) bufObj->Pointer;
3174b8e80941Smrg      GLuint i;
3175b8e80941Smrg      /* buffer is 100 bytes larger than requested, fill with magic value */
3176b8e80941Smrg      for (i = 0; i < 100; i++) {
3177b8e80941Smrg         buf[bufObj->Size - i - 1] = 123;
3178b8e80941Smrg      }
3179b8e80941Smrg   }
3180b8e80941Smrg#endif
3181848b8605Smrg
3182b8e80941Smrg   return map;
3183848b8605Smrg}
3184848b8605Smrg
3185b8e80941Smrgvoid * GLAPIENTRY
3186b8e80941Smrg_mesa_MapBufferRange_no_error(GLenum target, GLintptr offset,
3187b8e80941Smrg                              GLsizeiptr length, GLbitfield access)
3188848b8605Smrg{
3189b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3190848b8605Smrg
3191b8e80941Smrg   struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
3192b8e80941Smrg   struct gl_buffer_object *bufObj = *bufObjPtr;
3193848b8605Smrg
3194b8e80941Smrg   return map_buffer_range(ctx, bufObj, offset, length, access,
3195b8e80941Smrg                           "glMapBufferRange");
3196848b8605Smrg}
3197848b8605Smrg
3198b8e80941Smrgvoid * GLAPIENTRY
3199b8e80941Smrg_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
3200b8e80941Smrg                     GLbitfield access)
3201848b8605Smrg{
3202b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3203b8e80941Smrg   struct gl_buffer_object *bufObj;
3204848b8605Smrg
3205b8e80941Smrg   if (!ctx->Extensions.ARB_map_buffer_range) {
3206848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3207b8e80941Smrg                  "glMapBufferRange(ARB_map_buffer_range not supported)");
3208b8e80941Smrg      return NULL;
3209848b8605Smrg   }
3210848b8605Smrg
3211b8e80941Smrg   bufObj = get_buffer(ctx, "glMapBufferRange", target, GL_INVALID_OPERATION);
3212b8e80941Smrg   if (!bufObj)
3213b8e80941Smrg      return NULL;
3214848b8605Smrg
3215b8e80941Smrg   if (!validate_map_buffer_range(ctx, bufObj, offset, length, access,
3216b8e80941Smrg                                  "glMapBufferRange"))
3217b8e80941Smrg      return NULL;
3218848b8605Smrg
3219b8e80941Smrg   return map_buffer_range(ctx, bufObj, offset, length, access,
3220b8e80941Smrg                           "glMapBufferRange");
3221848b8605Smrg}
3222848b8605Smrg
3223b8e80941Smrgvoid * GLAPIENTRY
3224b8e80941Smrg_mesa_MapNamedBufferRange_no_error(GLuint buffer, GLintptr offset,
3225b8e80941Smrg                                   GLsizeiptr length, GLbitfield access)
3226848b8605Smrg{
3227848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
3228b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3229848b8605Smrg
3230b8e80941Smrg   return map_buffer_range(ctx, bufObj, offset, length, access,
3231b8e80941Smrg                           "glMapNamedBufferRange");
3232848b8605Smrg}
3233848b8605Smrg
3234b8e80941Smrgvoid * GLAPIENTRY
3235b8e80941Smrg_mesa_MapNamedBufferRange(GLuint buffer, GLintptr offset, GLsizeiptr length,
3236b8e80941Smrg                          GLbitfield access)
3237848b8605Smrg{
3238b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3239848b8605Smrg   struct gl_buffer_object *bufObj;
3240848b8605Smrg
3241b8e80941Smrg   if (!ctx->Extensions.ARB_map_buffer_range) {
3242848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3243b8e80941Smrg                  "glMapNamedBufferRange("
3244b8e80941Smrg                  "ARB_map_buffer_range not supported)");
3245b8e80941Smrg      return NULL;
3246848b8605Smrg   }
3247848b8605Smrg
3248b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBufferRange");
3249b8e80941Smrg   if (!bufObj)
3250b8e80941Smrg      return NULL;
3251848b8605Smrg
3252b8e80941Smrg   if (!validate_map_buffer_range(ctx, bufObj, offset, length, access,
3253b8e80941Smrg                                  "glMapNamedBufferRange"))
3254b8e80941Smrg      return NULL;
3255848b8605Smrg
3256b8e80941Smrg   return map_buffer_range(ctx, bufObj, offset, length, access,
3257b8e80941Smrg                           "glMapNamedBufferRange");
3258848b8605Smrg}
3259848b8605Smrg
3260b8e80941Smrg/**
3261b8e80941Smrg * Converts GLenum access from MapBuffer and MapNamedBuffer into
3262b8e80941Smrg * flags for input to map_buffer_range.
3263b8e80941Smrg *
3264b8e80941Smrg * \return true if the type of requested access is permissible.
3265b8e80941Smrg */
3266b8e80941Smrgstatic bool
3267b8e80941Smrgget_map_buffer_access_flags(struct gl_context *ctx, GLenum access,
3268b8e80941Smrg                            GLbitfield *flags)
3269848b8605Smrg{
3270b8e80941Smrg   switch (access) {
3271b8e80941Smrg   case GL_READ_ONLY_ARB:
3272b8e80941Smrg      *flags = GL_MAP_READ_BIT;
3273b8e80941Smrg      return _mesa_is_desktop_gl(ctx);
3274b8e80941Smrg   case GL_WRITE_ONLY_ARB:
3275b8e80941Smrg      *flags = GL_MAP_WRITE_BIT;
3276b8e80941Smrg      return true;
3277b8e80941Smrg   case GL_READ_WRITE_ARB:
3278b8e80941Smrg      *flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
3279b8e80941Smrg      return _mesa_is_desktop_gl(ctx);
3280b8e80941Smrg   default:
3281b8e80941Smrg      *flags = 0;
3282b8e80941Smrg      return false;
3283848b8605Smrg   }
3284b8e80941Smrg}
3285848b8605Smrg
3286b8e80941Smrgvoid * GLAPIENTRY
3287b8e80941Smrg_mesa_MapBuffer_no_error(GLenum target, GLenum access)
3288b8e80941Smrg{
3289b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3290848b8605Smrg
3291b8e80941Smrg   GLbitfield accessFlags;
3292b8e80941Smrg   get_map_buffer_access_flags(ctx, access, &accessFlags);
3293848b8605Smrg
3294b8e80941Smrg   struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
3295b8e80941Smrg   struct gl_buffer_object *bufObj = *bufObjPtr;
3296848b8605Smrg
3297b8e80941Smrg   return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3298b8e80941Smrg                           "glMapBuffer");
3299848b8605Smrg}
3300848b8605Smrg
3301b8e80941Smrgvoid * GLAPIENTRY
3302b8e80941Smrg_mesa_MapBuffer(GLenum target, GLenum access)
3303848b8605Smrg{
3304b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3305b8e80941Smrg   struct gl_buffer_object *bufObj;
3306b8e80941Smrg   GLbitfield accessFlags;
3307848b8605Smrg
3308b8e80941Smrg   if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
3309b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glMapBuffer(invalid access)");
3310b8e80941Smrg      return NULL;
3311848b8605Smrg   }
3312848b8605Smrg
3313b8e80941Smrg   bufObj = get_buffer(ctx, "glMapBuffer", target, GL_INVALID_OPERATION);
3314b8e80941Smrg   if (!bufObj)
3315b8e80941Smrg      return NULL;
3316848b8605Smrg
3317b8e80941Smrg   if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3318b8e80941Smrg                                  "glMapBuffer"))
3319b8e80941Smrg      return NULL;
3320848b8605Smrg
3321b8e80941Smrg   return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3322b8e80941Smrg                           "glMapBuffer");
3323848b8605Smrg}
3324848b8605Smrg
3325b8e80941Smrgvoid * GLAPIENTRY
3326b8e80941Smrg_mesa_MapNamedBuffer_no_error(GLuint buffer, GLenum access)
3327b8e80941Smrg{
3328b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3329b8e80941Smrg
3330b8e80941Smrg   GLbitfield accessFlags;
3331b8e80941Smrg   get_map_buffer_access_flags(ctx, access, &accessFlags);
3332b8e80941Smrg
3333b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3334b8e80941Smrg
3335b8e80941Smrg   return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3336b8e80941Smrg                           "glMapNamedBuffer");
3337b8e80941Smrg}
3338848b8605Smrg
3339b8e80941Smrgvoid * GLAPIENTRY
3340b8e80941Smrg_mesa_MapNamedBuffer(GLuint buffer, GLenum access)
3341848b8605Smrg{
3342848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
3343b8e80941Smrg   struct gl_buffer_object *bufObj;
3344b8e80941Smrg   GLbitfield accessFlags;
3345848b8605Smrg
3346b8e80941Smrg   if (!get_map_buffer_access_flags(ctx, access, &accessFlags)) {
3347b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glMapNamedBuffer(invalid access)");
3348b8e80941Smrg      return NULL;
3349848b8605Smrg   }
3350848b8605Smrg
3351b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMapNamedBuffer");
3352b8e80941Smrg   if (!bufObj)
3353b8e80941Smrg      return NULL;
3354b8e80941Smrg
3355b8e80941Smrg   if (!validate_map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3356b8e80941Smrg                                  "glMapNamedBuffer"))
3357b8e80941Smrg      return NULL;
3358b8e80941Smrg
3359b8e80941Smrg   return map_buffer_range(ctx, bufObj, 0, bufObj->Size, accessFlags,
3360b8e80941Smrg                           "glMapNamedBuffer");
3361848b8605Smrg}
3362848b8605Smrg
3363848b8605Smrg
3364848b8605Smrgstatic void
3365b8e80941Smrgflush_mapped_buffer_range(struct gl_context *ctx,
3366b8e80941Smrg                          struct gl_buffer_object *bufObj,
3367b8e80941Smrg                          GLintptr offset, GLsizeiptr length,
3368b8e80941Smrg                          const char *func)
3369848b8605Smrg{
3370b8e80941Smrg   if (!ctx->Extensions.ARB_map_buffer_range) {
3371b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3372b8e80941Smrg                  "%s(ARB_map_buffer_range not supported)", func);
3373848b8605Smrg      return;
3374848b8605Smrg   }
3375848b8605Smrg
3376b8e80941Smrg   if (offset < 0) {
3377b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3378b8e80941Smrg                  "%s(offset %ld < 0)", func, (long) offset);
3379b8e80941Smrg      return;
3380848b8605Smrg   }
3381848b8605Smrg
3382b8e80941Smrg   if (length < 0) {
3383848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3384b8e80941Smrg                  "%s(length %ld < 0)", func, (long) length);
3385848b8605Smrg      return;
3386848b8605Smrg   }
3387848b8605Smrg
3388b8e80941Smrg   if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) {
3389b8e80941Smrg      /* buffer is not mapped */
3390b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3391b8e80941Smrg                  "%s(buffer is not mapped)", func);
3392b8e80941Smrg      return;
3393848b8605Smrg   }
3394848b8605Smrg
3395b8e80941Smrg   if ((bufObj->Mappings[MAP_USER].AccessFlags &
3396b8e80941Smrg        GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
3397b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3398b8e80941Smrg                  "%s(GL_MAP_FLUSH_EXPLICIT_BIT not set)", func);
3399b8e80941Smrg      return;
3400b8e80941Smrg   }
3401848b8605Smrg
3402b8e80941Smrg   if (offset + length > bufObj->Mappings[MAP_USER].Length) {
3403848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3404b8e80941Smrg                  "%s(offset %ld + length %ld > mapped length %ld)", func,
3405b8e80941Smrg                  (long) offset, (long) length,
3406b8e80941Smrg                  (long) bufObj->Mappings[MAP_USER].Length);
3407848b8605Smrg      return;
3408848b8605Smrg   }
3409848b8605Smrg
3410b8e80941Smrg   assert(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT);
3411b8e80941Smrg
3412b8e80941Smrg   if (ctx->Driver.FlushMappedBufferRange)
3413b8e80941Smrg      ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
3414b8e80941Smrg                                         MAP_USER);
3415848b8605Smrg}
3416848b8605Smrg
3417b8e80941Smrgvoid GLAPIENTRY
3418b8e80941Smrg_mesa_FlushMappedBufferRange_no_error(GLenum target, GLintptr offset,
3419b8e80941Smrg                                      GLsizeiptr length)
3420b8e80941Smrg{
3421b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3422b8e80941Smrg   struct gl_buffer_object **bufObjPtr = get_buffer_target(ctx, target);
3423b8e80941Smrg   struct gl_buffer_object *bufObj = *bufObjPtr;
3424b8e80941Smrg
3425b8e80941Smrg   if (ctx->Driver.FlushMappedBufferRange)
3426b8e80941Smrg      ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
3427b8e80941Smrg                                         MAP_USER);
3428b8e80941Smrg}
3429848b8605Smrg
3430848b8605Smrgvoid GLAPIENTRY
3431b8e80941Smrg_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset,
3432b8e80941Smrg                             GLsizeiptr length)
3433848b8605Smrg{
3434848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
3435b8e80941Smrg   struct gl_buffer_object *bufObj;
3436848b8605Smrg
3437b8e80941Smrg   bufObj = get_buffer(ctx, "glFlushMappedBufferRange", target,
3438b8e80941Smrg                       GL_INVALID_OPERATION);
3439b8e80941Smrg   if (!bufObj)
3440848b8605Smrg      return;
3441848b8605Smrg
3442b8e80941Smrg   flush_mapped_buffer_range(ctx, bufObj, offset, length,
3443b8e80941Smrg                             "glFlushMappedBufferRange");
3444848b8605Smrg}
3445848b8605Smrg
3446b8e80941Smrgvoid GLAPIENTRY
3447b8e80941Smrg_mesa_FlushMappedNamedBufferRange_no_error(GLuint buffer, GLintptr offset,
3448b8e80941Smrg                                           GLsizeiptr length)
3449b8e80941Smrg{
3450b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3451b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
3452b8e80941Smrg
3453b8e80941Smrg   if (ctx->Driver.FlushMappedBufferRange)
3454b8e80941Smrg      ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj,
3455b8e80941Smrg                                         MAP_USER);
3456b8e80941Smrg}
3457b8e80941Smrg
3458b8e80941Smrgvoid GLAPIENTRY
3459b8e80941Smrg_mesa_FlushMappedNamedBufferRange(GLuint buffer, GLintptr offset,
3460b8e80941Smrg                                  GLsizeiptr length)
3461848b8605Smrg{
3462b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
3463b8e80941Smrg   struct gl_buffer_object *bufObj;
3464848b8605Smrg
3465b8e80941Smrg   bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
3466b8e80941Smrg                                       "glFlushMappedNamedBufferRange");
3467b8e80941Smrg   if (!bufObj)
3468b8e80941Smrg      return;
3469b8e80941Smrg
3470b8e80941Smrg   flush_mapped_buffer_range(ctx, bufObj, offset, length,
3471b8e80941Smrg                             "glFlushMappedNamedBufferRange");
3472848b8605Smrg}
3473848b8605Smrg
3474848b8605Smrgstatic void
3475b8e80941Smrgbind_buffer_range_uniform_buffer(struct gl_context *ctx, GLuint index,
3476b8e80941Smrg                                 struct gl_buffer_object *bufObj,
3477b8e80941Smrg                                 GLintptr offset, GLsizeiptr size)
3478848b8605Smrg{
3479b8e80941Smrg   if (bufObj == ctx->Shared->NullBufferObj) {
3480b8e80941Smrg      offset = -1;
3481b8e80941Smrg      size = -1;
3482848b8605Smrg   }
3483848b8605Smrg
3484b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->UniformBuffer, bufObj);
3485b8e80941Smrg   bind_uniform_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
3486848b8605Smrg}
3487848b8605Smrg
3488848b8605Smrg/**
3489848b8605Smrg * Bind a region of a buffer object to a uniform block binding point.
3490848b8605Smrg * \param index  the uniform buffer binding point index
3491848b8605Smrg * \param bufObj  the buffer object
3492848b8605Smrg * \param offset  offset to the start of buffer object region
3493848b8605Smrg * \param size  size of the buffer object region
3494848b8605Smrg */
3495848b8605Smrgstatic void
3496b8e80941Smrgbind_buffer_range_uniform_buffer_err(struct gl_context *ctx, GLuint index,
3497b8e80941Smrg                                     struct gl_buffer_object *bufObj,
3498b8e80941Smrg                                     GLintptr offset, GLsizeiptr size)
3499848b8605Smrg{
3500848b8605Smrg   if (index >= ctx->Const.MaxUniformBufferBindings) {
3501848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
3502848b8605Smrg      return;
3503848b8605Smrg   }
3504848b8605Smrg
3505848b8605Smrg   if (offset & (ctx->Const.UniformBufferOffsetAlignment - 1)) {
3506848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3507b8e80941Smrg                  "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
3508848b8605Smrg		  ctx->Const.UniformBufferOffsetAlignment);
3509848b8605Smrg      return;
3510848b8605Smrg   }
3511848b8605Smrg
3512b8e80941Smrg   bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
3513b8e80941Smrg}
3514b8e80941Smrg
3515b8e80941Smrgstatic void
3516b8e80941Smrgbind_buffer_range_shader_storage_buffer(struct gl_context *ctx,
3517b8e80941Smrg                                        GLuint index,
3518b8e80941Smrg                                        struct gl_buffer_object *bufObj,
3519b8e80941Smrg                                        GLintptr offset,
3520b8e80941Smrg                                        GLsizeiptr size)
3521b8e80941Smrg{
3522848b8605Smrg   if (bufObj == ctx->Shared->NullBufferObj) {
3523848b8605Smrg      offset = -1;
3524848b8605Smrg      size = -1;
3525848b8605Smrg   }
3526848b8605Smrg
3527b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->ShaderStorageBuffer, bufObj);
3528b8e80941Smrg   bind_shader_storage_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
3529848b8605Smrg}
3530848b8605Smrg
3531848b8605Smrg/**
3532b8e80941Smrg * Bind a region of a buffer object to a shader storage block binding point.
3533b8e80941Smrg * \param index  the shader storage buffer binding point index
3534b8e80941Smrg * \param bufObj  the buffer object
3535b8e80941Smrg * \param offset  offset to the start of buffer object region
3536b8e80941Smrg * \param size  size of the buffer object region
3537848b8605Smrg */
3538848b8605Smrgstatic void
3539b8e80941Smrgbind_buffer_range_shader_storage_buffer_err(struct gl_context *ctx,
3540b8e80941Smrg                                            GLuint index,
3541b8e80941Smrg                                            struct gl_buffer_object *bufObj,
3542b8e80941Smrg                                            GLintptr offset, GLsizeiptr size)
3543848b8605Smrg{
3544b8e80941Smrg   if (index >= ctx->Const.MaxShaderStorageBufferBindings) {
3545b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
3546848b8605Smrg      return;
3547848b8605Smrg   }
3548848b8605Smrg
3549b8e80941Smrg   if (offset & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) {
3550b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3551b8e80941Smrg                  "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
3552b8e80941Smrg                  ctx->Const.ShaderStorageBufferOffsetAlignment);
3553b8e80941Smrg      return;
3554b8e80941Smrg   }
3555848b8605Smrg
3556b8e80941Smrg   bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset, size);
3557848b8605Smrg}
3558848b8605Smrg
3559848b8605Smrgstatic void
3560b8e80941Smrgbind_buffer_range_atomic_buffer(struct gl_context *ctx, GLuint index,
3561b8e80941Smrg                                 struct gl_buffer_object *bufObj,
3562b8e80941Smrg                                 GLintptr offset, GLsizeiptr size)
3563848b8605Smrg{
3564848b8605Smrg   if (bufObj == ctx->Shared->NullBufferObj) {
3565b8e80941Smrg      offset = -1;
3566b8e80941Smrg      size = -1;
3567848b8605Smrg   }
3568b8e80941Smrg
3569b8e80941Smrg   _mesa_reference_buffer_object(ctx, &ctx->AtomicBuffer, bufObj);
3570b8e80941Smrg   bind_atomic_buffer(ctx, index, bufObj, offset, size, GL_FALSE);
3571848b8605Smrg}
3572848b8605Smrg
3573848b8605Smrg/**
3574b8e80941Smrg * Bind a region of a buffer object to an atomic storage block binding point.
3575b8e80941Smrg * \param index  the shader storage buffer binding point index
3576b8e80941Smrg * \param bufObj  the buffer object
3577b8e80941Smrg * \param offset  offset to the start of buffer object region
3578b8e80941Smrg * \param size  size of the buffer object region
3579848b8605Smrg */
3580848b8605Smrgstatic void
3581b8e80941Smrgbind_buffer_range_atomic_buffer_err(struct gl_context *ctx,
3582b8e80941Smrg                                    GLuint index,
3583b8e80941Smrg                                    struct gl_buffer_object *bufObj,
3584b8e80941Smrg                                    GLintptr offset, GLsizeiptr size)
3585848b8605Smrg{
3586848b8605Smrg   if (index >= ctx->Const.MaxAtomicBufferBindings) {
3587b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(index=%d)", index);
3588848b8605Smrg      return;
3589848b8605Smrg   }
3590848b8605Smrg
3591848b8605Smrg   if (offset & (ATOMIC_COUNTER_SIZE - 1)) {
3592848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3593b8e80941Smrg		  "glBindBufferRange(offset misaligned %d/%d)", (int) offset,
3594b8e80941Smrg		  ATOMIC_COUNTER_SIZE);
3595848b8605Smrg      return;
3596848b8605Smrg   }
3597848b8605Smrg
3598b8e80941Smrg   bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size);
3599848b8605Smrg}
3600848b8605Smrg
3601848b8605Smrgstatic inline bool
3602848b8605Smrgbind_buffers_check_offset_and_size(struct gl_context *ctx,
3603848b8605Smrg                                   GLuint index,
3604848b8605Smrg                                   const GLintptr *offsets,
3605848b8605Smrg                                   const GLsizeiptr *sizes)
3606848b8605Smrg{
3607848b8605Smrg   if (offsets[index] < 0) {
3608b8e80941Smrg      /* The ARB_multi_bind spec says:
3609b8e80941Smrg       *
3610b8e80941Smrg       *    "An INVALID_VALUE error is generated by BindBuffersRange if any
3611b8e80941Smrg       *     value in <offsets> is less than zero (per binding)."
3612b8e80941Smrg       */
3613848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3614848b8605Smrg                  "glBindBuffersRange(offsets[%u]=%" PRId64 " < 0)",
3615848b8605Smrg                  index, (int64_t) offsets[index]);
3616848b8605Smrg      return false;
3617848b8605Smrg   }
3618848b8605Smrg
3619848b8605Smrg   if (sizes[index] <= 0) {
3620b8e80941Smrg      /* The ARB_multi_bind spec says:
3621b8e80941Smrg       *
3622b8e80941Smrg       *     "An INVALID_VALUE error is generated by BindBuffersRange if any
3623b8e80941Smrg       *      value in <sizes> is less than or equal to zero (per binding)."
3624b8e80941Smrg       */
3625848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
3626848b8605Smrg                  "glBindBuffersRange(sizes[%u]=%" PRId64 " <= 0)",
3627848b8605Smrg                  index, (int64_t) sizes[index]);
3628848b8605Smrg      return false;
3629848b8605Smrg   }
3630848b8605Smrg
3631848b8605Smrg   return true;
3632848b8605Smrg}
3633848b8605Smrg
3634848b8605Smrgstatic bool
3635848b8605Smrgerror_check_bind_uniform_buffers(struct gl_context *ctx,
3636848b8605Smrg                                 GLuint first, GLsizei count,
3637848b8605Smrg                                 const char *caller)
3638848b8605Smrg{
3639848b8605Smrg   if (!ctx->Extensions.ARB_uniform_buffer_object) {
3640848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
3641848b8605Smrg                  "%s(target=GL_UNIFORM_BUFFER)", caller);
3642848b8605Smrg      return false;
3643848b8605Smrg   }
3644848b8605Smrg
3645848b8605Smrg   /* The ARB_multi_bind_spec says:
3646848b8605Smrg    *
3647848b8605Smrg    *     "An INVALID_OPERATION error is generated if <first> + <count> is
3648848b8605Smrg    *      greater than the number of target-specific indexed binding points,
3649848b8605Smrg    *      as described in section 6.7.1."
3650848b8605Smrg    */
3651848b8605Smrg   if (first + count > ctx->Const.MaxUniformBufferBindings) {
3652848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3653848b8605Smrg                  "%s(first=%u + count=%d > the value of "
3654848b8605Smrg                  "GL_MAX_UNIFORM_BUFFER_BINDINGS=%u)",
3655848b8605Smrg                  caller, first, count,
3656848b8605Smrg                  ctx->Const.MaxUniformBufferBindings);
3657848b8605Smrg      return false;
3658848b8605Smrg   }
3659848b8605Smrg
3660848b8605Smrg   return true;
3661848b8605Smrg}
3662848b8605Smrg
3663b8e80941Smrgstatic bool
3664b8e80941Smrgerror_check_bind_shader_storage_buffers(struct gl_context *ctx,
3665b8e80941Smrg                                        GLuint first, GLsizei count,
3666b8e80941Smrg                                        const char *caller)
3667b8e80941Smrg{
3668b8e80941Smrg   if (!ctx->Extensions.ARB_shader_storage_buffer_object) {
3669b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
3670b8e80941Smrg                  "%s(target=GL_SHADER_STORAGE_BUFFER)", caller);
3671b8e80941Smrg      return false;
3672b8e80941Smrg   }
3673b8e80941Smrg
3674b8e80941Smrg   /* The ARB_multi_bind_spec says:
3675b8e80941Smrg    *
3676b8e80941Smrg    *     "An INVALID_OPERATION error is generated if <first> + <count> is
3677b8e80941Smrg    *      greater than the number of target-specific indexed binding points,
3678b8e80941Smrg    *      as described in section 6.7.1."
3679b8e80941Smrg    */
3680b8e80941Smrg   if (first + count > ctx->Const.MaxShaderStorageBufferBindings) {
3681b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3682b8e80941Smrg                  "%s(first=%u + count=%d > the value of "
3683b8e80941Smrg                  "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS=%u)",
3684b8e80941Smrg                  caller, first, count,
3685b8e80941Smrg                  ctx->Const.MaxShaderStorageBufferBindings);
3686b8e80941Smrg      return false;
3687b8e80941Smrg   }
3688b8e80941Smrg
3689b8e80941Smrg   return true;
3690b8e80941Smrg}
3691b8e80941Smrg
3692848b8605Smrg/**
3693848b8605Smrg * Unbind all uniform buffers in the range
3694848b8605Smrg * <first> through <first>+<count>-1
3695848b8605Smrg */
3696848b8605Smrgstatic void
3697848b8605Smrgunbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
3698848b8605Smrg{
3699848b8605Smrg   struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj;
3700848b8605Smrg
3701b8e80941Smrg   for (int i = 0; i < count; i++)
3702b8e80941Smrg      set_buffer_binding(ctx, &ctx->UniformBufferBindings[first + i],
3703b8e80941Smrg                         bufObj, -1, -1, GL_TRUE, 0);
3704848b8605Smrg}
3705848b8605Smrg
3706b8e80941Smrg/**
3707b8e80941Smrg * Unbind all shader storage buffers in the range
3708b8e80941Smrg * <first> through <first>+<count>-1
3709b8e80941Smrg */
3710848b8605Smrgstatic void
3711b8e80941Smrgunbind_shader_storage_buffers(struct gl_context *ctx, GLuint first,
3712b8e80941Smrg                              GLsizei count)
3713848b8605Smrg{
3714b8e80941Smrg   struct gl_buffer_object *bufObj = ctx->Shared->NullBufferObj;
3715b8e80941Smrg
3716b8e80941Smrg   for (int i = 0; i < count; i++)
3717b8e80941Smrg      set_buffer_binding(ctx, &ctx->ShaderStorageBufferBindings[first + i],
3718b8e80941Smrg                         bufObj, -1, -1, GL_TRUE, 0);
3719b8e80941Smrg}
3720848b8605Smrg
3721b8e80941Smrgstatic void
3722b8e80941Smrgbind_uniform_buffers(struct gl_context *ctx, GLuint first, GLsizei count,
3723b8e80941Smrg                     const GLuint *buffers,
3724b8e80941Smrg                     bool range,
3725b8e80941Smrg                     const GLintptr *offsets, const GLsizeiptr *sizes,
3726b8e80941Smrg                     const char *caller)
3727b8e80941Smrg{
3728b8e80941Smrg   if (!error_check_bind_uniform_buffers(ctx, first, count, caller))
3729848b8605Smrg      return;
3730848b8605Smrg
3731848b8605Smrg   /* Assume that at least one binding will be changed */
3732848b8605Smrg   FLUSH_VERTICES(ctx, 0);
3733848b8605Smrg   ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
3734848b8605Smrg
3735848b8605Smrg   if (!buffers) {
3736848b8605Smrg      /* The ARB_multi_bind spec says:
3737848b8605Smrg       *
3738b8e80941Smrg       *    "If <buffers> is NULL, all bindings from <first> through
3739b8e80941Smrg       *     <first>+<count>-1 are reset to their unbound (zero) state.
3740b8e80941Smrg       *     In this case, the offsets and sizes associated with the
3741b8e80941Smrg       *     binding points are set to default values, ignoring
3742b8e80941Smrg       *     <offsets> and <sizes>."
3743848b8605Smrg       */
3744848b8605Smrg      unbind_uniform_buffers(ctx, first, count);
3745848b8605Smrg      return;
3746848b8605Smrg   }
3747848b8605Smrg
3748848b8605Smrg   /* Note that the error semantics for multi-bind commands differ from
3749848b8605Smrg    * those of other GL commands.
3750848b8605Smrg    *
3751848b8605Smrg    * The Issues section in the ARB_multi_bind spec says:
3752848b8605Smrg    *
3753848b8605Smrg    *    "(11) Typically, OpenGL specifies that if an error is generated by a
3754848b8605Smrg    *          command, that command has no effect.  This is somewhat
3755848b8605Smrg    *          unfortunate for multi-bind commands, because it would require a
3756848b8605Smrg    *          first pass to scan the entire list of bound objects for errors
3757848b8605Smrg    *          and then a second pass to actually perform the bindings.
3758848b8605Smrg    *          Should we have different error semantics?
3759848b8605Smrg    *
3760848b8605Smrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
3761848b8605Smrg    *       one of the <count> binding points are invalid, that binding point
3762848b8605Smrg    *       is not updated and an error will be generated.  However, other
3763848b8605Smrg    *       binding points in the same command will be updated if their
3764848b8605Smrg    *       parameters are valid and no other error occurs."
3765848b8605Smrg    */
3766848b8605Smrg
3767b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->BufferObjects);
3768848b8605Smrg
3769b8e80941Smrg   for (int i = 0; i < count; i++) {
3770b8e80941Smrg      struct gl_buffer_binding *binding =
3771b8e80941Smrg         &ctx->UniformBufferBindings[first + i];
3772b8e80941Smrg      GLintptr offset = 0;
3773b8e80941Smrg      GLsizeiptr size = 0;
3774848b8605Smrg
3775b8e80941Smrg      if (range) {
3776b8e80941Smrg         if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
3777b8e80941Smrg            continue;
3778848b8605Smrg
3779b8e80941Smrg         /* The ARB_multi_bind spec says:
3780b8e80941Smrg          *
3781b8e80941Smrg          *     "An INVALID_VALUE error is generated by BindBuffersRange if any
3782b8e80941Smrg          *      pair of values in <offsets> and <sizes> does not respectively
3783b8e80941Smrg          *      satisfy the constraints described for those parameters for the
3784b8e80941Smrg          *      specified target, as described in section 6.7.1 (per binding)."
3785b8e80941Smrg          *
3786b8e80941Smrg          * Section 6.7.1 refers to table 6.5, which says:
3787b8e80941Smrg          *
3788b8e80941Smrg          *     "┌───────────────────────────────────────────────────────────────┐
3789b8e80941Smrg          *      │ Uniform buffer array bindings (see sec. 7.6)                  │
3790b8e80941Smrg          *      ├─────────────────────┬─────────────────────────────────────────┤
3791b8e80941Smrg          *      │  ...                │  ...                                    │
3792b8e80941Smrg          *      │  offset restriction │  multiple of value of UNIFORM_BUFFER_-  │
3793b8e80941Smrg          *      │                     │  OFFSET_ALIGNMENT                       │
3794b8e80941Smrg          *      │  ...                │  ...                                    │
3795b8e80941Smrg          *      │  size restriction   │  none                                   │
3796b8e80941Smrg          *      └─────────────────────┴─────────────────────────────────────────┘"
3797b8e80941Smrg          */
3798b8e80941Smrg         if (offsets[i] & (ctx->Const.UniformBufferOffsetAlignment - 1)) {
3799b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
3800b8e80941Smrg                        "glBindBuffersRange(offsets[%u]=%" PRId64
3801b8e80941Smrg                        " is misaligned; it must be a multiple of the value of "
3802b8e80941Smrg                        "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT=%u when "
3803b8e80941Smrg                        "target=GL_UNIFORM_BUFFER)",
3804b8e80941Smrg                        i, (int64_t) offsets[i],
3805b8e80941Smrg                        ctx->Const.UniformBufferOffsetAlignment);
3806b8e80941Smrg            continue;
3807b8e80941Smrg         }
3808b8e80941Smrg
3809b8e80941Smrg         offset = offsets[i];
3810b8e80941Smrg         size = sizes[i];
3811848b8605Smrg      }
3812b8e80941Smrg
3813b8e80941Smrg      set_buffer_multi_binding(ctx, buffers, i, caller,
3814b8e80941Smrg                               binding, offset, size, range,
3815b8e80941Smrg                               USAGE_UNIFORM_BUFFER);
3816848b8605Smrg   }
3817848b8605Smrg
3818b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
3819848b8605Smrg}
3820848b8605Smrg
3821848b8605Smrgstatic void
3822b8e80941Smrgbind_shader_storage_buffers(struct gl_context *ctx, GLuint first,
3823b8e80941Smrg                            GLsizei count, const GLuint *buffers,
3824b8e80941Smrg                            bool range,
3825b8e80941Smrg                            const GLintptr *offsets,
3826b8e80941Smrg                            const GLsizeiptr *sizes,
3827b8e80941Smrg                            const char *caller)
3828848b8605Smrg{
3829b8e80941Smrg   if (!error_check_bind_shader_storage_buffers(ctx, first, count, caller))
3830848b8605Smrg      return;
3831848b8605Smrg
3832848b8605Smrg   /* Assume that at least one binding will be changed */
3833848b8605Smrg   FLUSH_VERTICES(ctx, 0);
3834b8e80941Smrg   ctx->NewDriverState |= ctx->DriverFlags.NewShaderStorageBuffer;
3835848b8605Smrg
3836848b8605Smrg   if (!buffers) {
3837848b8605Smrg      /* The ARB_multi_bind spec says:
3838848b8605Smrg       *
3839848b8605Smrg       *    "If <buffers> is NULL, all bindings from <first> through
3840848b8605Smrg       *     <first>+<count>-1 are reset to their unbound (zero) state.
3841848b8605Smrg       *     In this case, the offsets and sizes associated with the
3842848b8605Smrg       *     binding points are set to default values, ignoring
3843848b8605Smrg       *     <offsets> and <sizes>."
3844848b8605Smrg       */
3845b8e80941Smrg      unbind_shader_storage_buffers(ctx, first, count);
3846848b8605Smrg      return;
3847848b8605Smrg   }
3848848b8605Smrg
3849848b8605Smrg   /* Note that the error semantics for multi-bind commands differ from
3850848b8605Smrg    * those of other GL commands.
3851848b8605Smrg    *
3852848b8605Smrg    * The Issues section in the ARB_multi_bind spec says:
3853848b8605Smrg    *
3854848b8605Smrg    *    "(11) Typically, OpenGL specifies that if an error is generated by a
3855848b8605Smrg    *          command, that command has no effect.  This is somewhat
3856848b8605Smrg    *          unfortunate for multi-bind commands, because it would require a
3857848b8605Smrg    *          first pass to scan the entire list of bound objects for errors
3858848b8605Smrg    *          and then a second pass to actually perform the bindings.
3859848b8605Smrg    *          Should we have different error semantics?
3860848b8605Smrg    *
3861848b8605Smrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
3862848b8605Smrg    *       one of the <count> binding points are invalid, that binding point
3863848b8605Smrg    *       is not updated and an error will be generated.  However, other
3864848b8605Smrg    *       binding points in the same command will be updated if their
3865848b8605Smrg    *       parameters are valid and no other error occurs."
3866848b8605Smrg    */
3867848b8605Smrg
3868b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->BufferObjects);
3869848b8605Smrg
3870b8e80941Smrg   for (int i = 0; i < count; i++) {
3871b8e80941Smrg      struct gl_buffer_binding *binding =
3872b8e80941Smrg         &ctx->ShaderStorageBufferBindings[first + i];
3873b8e80941Smrg      GLintptr offset = 0;
3874b8e80941Smrg      GLsizeiptr size = 0;
3875b8e80941Smrg
3876b8e80941Smrg      if (range) {
3877b8e80941Smrg         if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
3878b8e80941Smrg            continue;
3879b8e80941Smrg
3880b8e80941Smrg         /* The ARB_multi_bind spec says:
3881b8e80941Smrg         *
3882b8e80941Smrg         *     "An INVALID_VALUE error is generated by BindBuffersRange if any
3883b8e80941Smrg         *      pair of values in <offsets> and <sizes> does not respectively
3884b8e80941Smrg         *      satisfy the constraints described for those parameters for the
3885b8e80941Smrg         *      specified target, as described in section 6.7.1 (per binding)."
3886b8e80941Smrg         *
3887b8e80941Smrg         * Section 6.7.1 refers to table 6.5, which says:
3888b8e80941Smrg         *
3889b8e80941Smrg         *     "┌───────────────────────────────────────────────────────────────┐
3890b8e80941Smrg         *      │ Shader storage buffer array bindings (see sec. 7.8)           │
3891b8e80941Smrg         *      ├─────────────────────┬─────────────────────────────────────────┤
3892b8e80941Smrg         *      │  ...                │  ...                                    │
3893b8e80941Smrg         *      │  offset restriction │  multiple of value of SHADER_STORAGE_-  │
3894b8e80941Smrg         *      │                     │  BUFFER_OFFSET_ALIGNMENT                │
3895b8e80941Smrg         *      │  ...                │  ...                                    │
3896b8e80941Smrg         *      │  size restriction   │  none                                   │
3897b8e80941Smrg         *      └─────────────────────┴─────────────────────────────────────────┘"
3898b8e80941Smrg         */
3899b8e80941Smrg         if (offsets[i] & (ctx->Const.ShaderStorageBufferOffsetAlignment - 1)) {
3900b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
3901b8e80941Smrg                        "glBindBuffersRange(offsets[%u]=%" PRId64
3902b8e80941Smrg                        " is misaligned; it must be a multiple of the value of "
3903b8e80941Smrg                        "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT=%u when "
3904b8e80941Smrg                        "target=GL_SHADER_STORAGE_BUFFER)",
3905b8e80941Smrg                        i, (int64_t) offsets[i],
3906b8e80941Smrg                        ctx->Const.ShaderStorageBufferOffsetAlignment);
3907b8e80941Smrg            continue;
3908b8e80941Smrg         }
3909848b8605Smrg
3910b8e80941Smrg         offset = offsets[i];
3911b8e80941Smrg         size = sizes[i];
3912848b8605Smrg      }
3913848b8605Smrg
3914b8e80941Smrg      set_buffer_multi_binding(ctx, buffers, i, caller,
3915b8e80941Smrg                               binding, offset, size, range,
3916b8e80941Smrg                               USAGE_SHADER_STORAGE_BUFFER);
3917848b8605Smrg   }
3918848b8605Smrg
3919b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
3920848b8605Smrg}
3921848b8605Smrg
3922848b8605Smrgstatic bool
3923848b8605Smrgerror_check_bind_xfb_buffers(struct gl_context *ctx,
3924848b8605Smrg                             struct gl_transform_feedback_object *tfObj,
3925848b8605Smrg                             GLuint first, GLsizei count, const char *caller)
3926848b8605Smrg{
3927848b8605Smrg   if (!ctx->Extensions.EXT_transform_feedback) {
3928848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
3929848b8605Smrg                  "%s(target=GL_TRANSFORM_FEEDBACK_BUFFER)", caller);
3930848b8605Smrg      return false;
3931848b8605Smrg   }
3932848b8605Smrg
3933848b8605Smrg   /* Page 398 of the PDF of the OpenGL 4.4 (Core Profile) spec says:
3934848b8605Smrg    *
3935848b8605Smrg    *     "An INVALID_OPERATION error is generated :
3936848b8605Smrg    *
3937848b8605Smrg    *     ...
3938848b8605Smrg    *     • by BindBufferRange or BindBufferBase if target is TRANSFORM_-
3939b8e80941Smrg    *       FEEDBACK_BUFFER and transform feedback is currently active."
3940b8e80941Smrg    *
3941b8e80941Smrg    * We assume that this is also meant to apply to BindBuffersRange
3942b8e80941Smrg    * and BindBuffersBase.
3943848b8605Smrg    */
3944b8e80941Smrg   if (tfObj->Active) {
3945b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3946b8e80941Smrg                  "%s(Changing transform feedback buffers while "
3947b8e80941Smrg                  "transform feedback is active)", caller);
3948b8e80941Smrg      return false;
3949b8e80941Smrg   }
3950848b8605Smrg
3951b8e80941Smrg   /* The ARB_multi_bind_spec says:
3952b8e80941Smrg    *
3953b8e80941Smrg    *     "An INVALID_OPERATION error is generated if <first> + <count> is
3954b8e80941Smrg    *      greater than the number of target-specific indexed binding points,
3955b8e80941Smrg    *      as described in section 6.7.1."
3956b8e80941Smrg    */
3957b8e80941Smrg   if (first + count > ctx->Const.MaxTransformFeedbackBuffers) {
3958b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3959b8e80941Smrg                  "%s(first=%u + count=%d > the value of "
3960b8e80941Smrg                  "GL_MAX_TRANSFORM_FEEDBACK_BUFFERS=%u)",
3961b8e80941Smrg                  caller, first, count,
3962b8e80941Smrg                  ctx->Const.MaxTransformFeedbackBuffers);
3963b8e80941Smrg      return false;
3964b8e80941Smrg   }
3965848b8605Smrg
3966b8e80941Smrg   return true;
3967b8e80941Smrg}
3968848b8605Smrg
3969b8e80941Smrg/**
3970b8e80941Smrg * Unbind all transform feedback buffers in the range
3971b8e80941Smrg * <first> through <first>+<count>-1
3972b8e80941Smrg */
3973b8e80941Smrgstatic void
3974b8e80941Smrgunbind_xfb_buffers(struct gl_context *ctx,
3975b8e80941Smrg                   struct gl_transform_feedback_object *tfObj,
3976b8e80941Smrg                   GLuint first, GLsizei count)
3977b8e80941Smrg{
3978b8e80941Smrg   struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj;
3979848b8605Smrg
3980b8e80941Smrg   for (int i = 0; i < count; i++)
3981b8e80941Smrg      _mesa_set_transform_feedback_binding(ctx, tfObj, first + i,
3982b8e80941Smrg                                           bufObj, 0, 0);
3983848b8605Smrg}
3984848b8605Smrg
3985848b8605Smrgstatic void
3986b8e80941Smrgbind_xfb_buffers(struct gl_context *ctx,
3987b8e80941Smrg                 GLuint first, GLsizei count,
3988b8e80941Smrg                 const GLuint *buffers,
3989b8e80941Smrg                 bool range,
3990b8e80941Smrg                 const GLintptr *offsets,
3991b8e80941Smrg                 const GLsizeiptr *sizes,
3992b8e80941Smrg                 const char *caller)
3993848b8605Smrg{
3994848b8605Smrg   struct gl_transform_feedback_object *tfObj =
3995848b8605Smrg       ctx->TransformFeedback.CurrentObject;
3996848b8605Smrg
3997b8e80941Smrg   if (!error_check_bind_xfb_buffers(ctx, tfObj, first, count, caller))
3998848b8605Smrg      return;
3999848b8605Smrg
4000848b8605Smrg   /* Assume that at least one binding will be changed */
4001848b8605Smrg   FLUSH_VERTICES(ctx, 0);
4002848b8605Smrg   ctx->NewDriverState |= ctx->DriverFlags.NewTransformFeedback;
4003848b8605Smrg
4004848b8605Smrg   if (!buffers) {
4005848b8605Smrg      /* The ARB_multi_bind spec says:
4006848b8605Smrg       *
4007848b8605Smrg       *    "If <buffers> is NULL, all bindings from <first> through
4008848b8605Smrg       *     <first>+<count>-1 are reset to their unbound (zero) state.
4009848b8605Smrg       *     In this case, the offsets and sizes associated with the
4010848b8605Smrg       *     binding points are set to default values, ignoring
4011848b8605Smrg       *     <offsets> and <sizes>."
4012848b8605Smrg       */
4013848b8605Smrg      unbind_xfb_buffers(ctx, tfObj, first, count);
4014848b8605Smrg      return;
4015848b8605Smrg   }
4016848b8605Smrg
4017848b8605Smrg   /* Note that the error semantics for multi-bind commands differ from
4018848b8605Smrg    * those of other GL commands.
4019848b8605Smrg    *
4020848b8605Smrg    * The Issues section in the ARB_multi_bind spec says:
4021848b8605Smrg    *
4022848b8605Smrg    *    "(11) Typically, OpenGL specifies that if an error is generated by a
4023848b8605Smrg    *          command, that command has no effect.  This is somewhat
4024848b8605Smrg    *          unfortunate for multi-bind commands, because it would require a
4025848b8605Smrg    *          first pass to scan the entire list of bound objects for errors
4026848b8605Smrg    *          and then a second pass to actually perform the bindings.
4027848b8605Smrg    *          Should we have different error semantics?
4028848b8605Smrg    *
4029848b8605Smrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
4030848b8605Smrg    *       one of the <count> binding points are invalid, that binding point
4031848b8605Smrg    *       is not updated and an error will be generated.  However, other
4032848b8605Smrg    *       binding points in the same command will be updated if their
4033848b8605Smrg    *       parameters are valid and no other error occurs."
4034848b8605Smrg    */
4035848b8605Smrg
4036b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->BufferObjects);
4037848b8605Smrg
4038b8e80941Smrg   for (int i = 0; i < count; i++) {
4039848b8605Smrg      const GLuint index = first + i;
4040848b8605Smrg      struct gl_buffer_object * const boundBufObj = tfObj->Buffers[index];
4041848b8605Smrg      struct gl_buffer_object *bufObj;
4042b8e80941Smrg      GLintptr offset = 0;
4043b8e80941Smrg      GLsizeiptr size = 0;
4044848b8605Smrg
4045b8e80941Smrg      if (range) {
4046b8e80941Smrg         if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
4047b8e80941Smrg            continue;
4048848b8605Smrg
4049b8e80941Smrg         /* The ARB_multi_bind spec says:
4050b8e80941Smrg          *
4051b8e80941Smrg          *     "An INVALID_VALUE error is generated by BindBuffersRange if any
4052b8e80941Smrg          *      pair of values in <offsets> and <sizes> does not respectively
4053b8e80941Smrg          *      satisfy the constraints described for those parameters for the
4054b8e80941Smrg          *      specified target, as described in section 6.7.1 (per binding)."
4055b8e80941Smrg          *
4056b8e80941Smrg          * Section 6.7.1 refers to table 6.5, which says:
4057b8e80941Smrg          *
4058b8e80941Smrg          *     "┌───────────────────────────────────────────────────────────────┐
4059b8e80941Smrg          *      │ Transform feedback array bindings (see sec. 13.2.2)           │
4060b8e80941Smrg          *      ├───────────────────────┬───────────────────────────────────────┤
4061b8e80941Smrg          *      │    ...                │    ...                                │
4062b8e80941Smrg          *      │    offset restriction │    multiple of 4                      │
4063b8e80941Smrg          *      │    ...                │    ...                                │
4064b8e80941Smrg          *      │    size restriction   │    multiple of 4                      │
4065b8e80941Smrg          *      └───────────────────────┴───────────────────────────────────────┘"
4066b8e80941Smrg          */
4067b8e80941Smrg         if (offsets[i] & 0x3) {
4068b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
4069b8e80941Smrg                        "glBindBuffersRange(offsets[%u]=%" PRId64
4070b8e80941Smrg                        " is misaligned; it must be a multiple of 4 when "
4071b8e80941Smrg                        "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
4072b8e80941Smrg                        i, (int64_t) offsets[i]);
4073b8e80941Smrg            continue;
4074b8e80941Smrg         }
4075848b8605Smrg
4076b8e80941Smrg         if (sizes[i] & 0x3) {
4077b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
4078b8e80941Smrg                        "glBindBuffersRange(sizes[%u]=%" PRId64
4079b8e80941Smrg                        " is misaligned; it must be a multiple of 4 when "
4080b8e80941Smrg                        "target=GL_TRANSFORM_FEEDBACK_BUFFER)",
4081b8e80941Smrg                        i, (int64_t) sizes[i]);
4082b8e80941Smrg            continue;
4083b8e80941Smrg         }
4084b8e80941Smrg
4085b8e80941Smrg         offset = offsets[i];
4086b8e80941Smrg         size = sizes[i];
4087848b8605Smrg      }
4088848b8605Smrg
4089848b8605Smrg      if (boundBufObj && boundBufObj->Name == buffers[i])
4090848b8605Smrg         bufObj = boundBufObj;
4091848b8605Smrg      else
4092b8e80941Smrg         bufObj = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, caller);
4093848b8605Smrg
4094848b8605Smrg      if (bufObj)
4095848b8605Smrg         _mesa_set_transform_feedback_binding(ctx, tfObj, index, bufObj,
4096b8e80941Smrg                                              offset, size);
4097848b8605Smrg   }
4098848b8605Smrg
4099b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
4100848b8605Smrg}
4101848b8605Smrg
4102848b8605Smrgstatic bool
4103848b8605Smrgerror_check_bind_atomic_buffers(struct gl_context *ctx,
4104848b8605Smrg                                GLuint first, GLsizei count,
4105848b8605Smrg                                const char *caller)
4106848b8605Smrg{
4107848b8605Smrg   if (!ctx->Extensions.ARB_shader_atomic_counters) {
4108848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM,
4109848b8605Smrg                  "%s(target=GL_ATOMIC_COUNTER_BUFFER)", caller);
4110848b8605Smrg      return false;
4111848b8605Smrg   }
4112848b8605Smrg
4113848b8605Smrg   /* The ARB_multi_bind_spec says:
4114848b8605Smrg    *
4115848b8605Smrg    *     "An INVALID_OPERATION error is generated if <first> + <count> is
4116848b8605Smrg    *      greater than the number of target-specific indexed binding points,
4117848b8605Smrg    *      as described in section 6.7.1."
4118848b8605Smrg    */
4119848b8605Smrg   if (first + count > ctx->Const.MaxAtomicBufferBindings) {
4120848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
4121848b8605Smrg                  "%s(first=%u + count=%d > the value of "
4122848b8605Smrg                  "GL_MAX_ATOMIC_BUFFER_BINDINGS=%u)",
4123848b8605Smrg                  caller, first, count, ctx->Const.MaxAtomicBufferBindings);
4124848b8605Smrg      return false;
4125848b8605Smrg   }
4126848b8605Smrg
4127848b8605Smrg   return true;
4128848b8605Smrg}
4129848b8605Smrg
4130848b8605Smrg/**
4131848b8605Smrg * Unbind all atomic counter buffers in the range
4132848b8605Smrg * <first> through <first>+<count>-1
4133848b8605Smrg */
4134848b8605Smrgstatic void
4135848b8605Smrgunbind_atomic_buffers(struct gl_context *ctx, GLuint first, GLsizei count)
4136848b8605Smrg{
4137848b8605Smrg   struct gl_buffer_object * const bufObj = ctx->Shared->NullBufferObj;
4138848b8605Smrg
4139b8e80941Smrg   for (int i = 0; i < count; i++)
4140b8e80941Smrg      set_buffer_binding(ctx, &ctx->AtomicBufferBindings[first + i],
4141b8e80941Smrg                         bufObj, -1, -1, GL_TRUE, 0);
4142848b8605Smrg}
4143848b8605Smrg
4144848b8605Smrgstatic void
4145b8e80941Smrgbind_atomic_buffers(struct gl_context *ctx,
4146b8e80941Smrg                    GLuint first,
4147b8e80941Smrg                    GLsizei count,
4148b8e80941Smrg                    const GLuint *buffers,
4149b8e80941Smrg                    bool range,
4150b8e80941Smrg                    const GLintptr *offsets,
4151b8e80941Smrg                    const GLsizeiptr *sizes,
4152b8e80941Smrg                    const char *caller)
4153848b8605Smrg{
4154b8e80941Smrg   if (!error_check_bind_atomic_buffers(ctx, first, count, caller))
4155848b8605Smrg     return;
4156848b8605Smrg
4157848b8605Smrg   /* Assume that at least one binding will be changed */
4158848b8605Smrg   FLUSH_VERTICES(ctx, 0);
4159848b8605Smrg   ctx->NewDriverState |= ctx->DriverFlags.NewAtomicBuffer;
4160848b8605Smrg
4161848b8605Smrg   if (!buffers) {
4162848b8605Smrg      /* The ARB_multi_bind spec says:
4163848b8605Smrg       *
4164848b8605Smrg       *    "If <buffers> is NULL, all bindings from <first> through
4165848b8605Smrg       *     <first>+<count>-1 are reset to their unbound (zero) state.
4166848b8605Smrg       *     In this case, the offsets and sizes associated with the
4167848b8605Smrg       *     binding points are set to default values, ignoring
4168848b8605Smrg       *     <offsets> and <sizes>."
4169848b8605Smrg       */
4170848b8605Smrg      unbind_atomic_buffers(ctx, first, count);
4171848b8605Smrg      return;
4172848b8605Smrg   }
4173848b8605Smrg
4174848b8605Smrg   /* Note that the error semantics for multi-bind commands differ from
4175848b8605Smrg    * those of other GL commands.
4176848b8605Smrg    *
4177848b8605Smrg    * The Issues section in the ARB_multi_bind spec says:
4178848b8605Smrg    *
4179848b8605Smrg    *    "(11) Typically, OpenGL specifies that if an error is generated by a
4180848b8605Smrg    *          command, that command has no effect.  This is somewhat
4181848b8605Smrg    *          unfortunate for multi-bind commands, because it would require a
4182848b8605Smrg    *          first pass to scan the entire list of bound objects for errors
4183848b8605Smrg    *          and then a second pass to actually perform the bindings.
4184848b8605Smrg    *          Should we have different error semantics?
4185848b8605Smrg    *
4186848b8605Smrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
4187848b8605Smrg    *       one of the <count> binding points are invalid, that binding point
4188848b8605Smrg    *       is not updated and an error will be generated.  However, other
4189848b8605Smrg    *       binding points in the same command will be updated if their
4190848b8605Smrg    *       parameters are valid and no other error occurs."
4191848b8605Smrg    */
4192848b8605Smrg
4193b8e80941Smrg   _mesa_HashLockMutex(ctx->Shared->BufferObjects);
4194848b8605Smrg
4195b8e80941Smrg   for (int i = 0; i < count; i++) {
4196b8e80941Smrg      struct gl_buffer_binding *binding =
4197848b8605Smrg         &ctx->AtomicBufferBindings[first + i];
4198b8e80941Smrg      GLintptr offset = 0;
4199b8e80941Smrg      GLsizeiptr size = 0;
4200848b8605Smrg
4201b8e80941Smrg      if (range) {
4202b8e80941Smrg         if (!bind_buffers_check_offset_and_size(ctx, i, offsets, sizes))
4203b8e80941Smrg            continue;
4204848b8605Smrg
4205b8e80941Smrg         /* The ARB_multi_bind spec says:
4206b8e80941Smrg          *
4207b8e80941Smrg          *     "An INVALID_VALUE error is generated by BindBuffersRange if any
4208b8e80941Smrg          *      pair of values in <offsets> and <sizes> does not respectively
4209b8e80941Smrg          *      satisfy the constraints described for those parameters for the
4210b8e80941Smrg          *      specified target, as described in section 6.7.1 (per binding)."
4211b8e80941Smrg          *
4212b8e80941Smrg          * Section 6.7.1 refers to table 6.5, which says:
4213b8e80941Smrg          *
4214b8e80941Smrg          *     "┌───────────────────────────────────────────────────────────────┐
4215b8e80941Smrg          *      │ Atomic counter array bindings (see sec. 7.7.2)                │
4216b8e80941Smrg          *      ├───────────────────────┬───────────────────────────────────────┤
4217b8e80941Smrg          *      │    ...                │    ...                                │
4218b8e80941Smrg          *      │    offset restriction │    multiple of 4                      │
4219b8e80941Smrg          *      │    ...                │    ...                                │
4220b8e80941Smrg          *      │    size restriction   │    none                               │
4221b8e80941Smrg          *      └───────────────────────┴───────────────────────────────────────┘"
4222b8e80941Smrg          */
4223b8e80941Smrg         if (offsets[i] & (ATOMIC_COUNTER_SIZE - 1)) {
4224b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
4225b8e80941Smrg                        "glBindBuffersRange(offsets[%u]=%" PRId64
4226b8e80941Smrg                        " is misaligned; it must be a multiple of %d when "
4227b8e80941Smrg                        "target=GL_ATOMIC_COUNTER_BUFFER)",
4228b8e80941Smrg                        i, (int64_t) offsets[i], ATOMIC_COUNTER_SIZE);
4229b8e80941Smrg            continue;
4230b8e80941Smrg         }
4231848b8605Smrg
4232b8e80941Smrg         offset = offsets[i];
4233b8e80941Smrg         size = sizes[i];
4234b8e80941Smrg      }
4235848b8605Smrg
4236b8e80941Smrg      set_buffer_multi_binding(ctx, buffers, i, caller,
4237b8e80941Smrg                               binding, offset, size, range,
4238b8e80941Smrg                               USAGE_ATOMIC_COUNTER_BUFFER);
4239848b8605Smrg   }
4240848b8605Smrg
4241b8e80941Smrg   _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
4242848b8605Smrg}
4243848b8605Smrg
4244b8e80941Smrgstatic ALWAYS_INLINE void
4245b8e80941Smrgbind_buffer_range(GLenum target, GLuint index, GLuint buffer, GLintptr offset,
4246b8e80941Smrg                  GLsizeiptr size, bool no_error)
4247848b8605Smrg{
4248848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
4249848b8605Smrg   struct gl_buffer_object *bufObj;
4250848b8605Smrg
4251b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
4252b8e80941Smrg      _mesa_debug(ctx, "glBindBufferRange(%s, %u, %u, %lu, %lu)\n",
4253b8e80941Smrg                  _mesa_enum_to_string(target), index, buffer,
4254b8e80941Smrg                  (unsigned long) offset, (unsigned long) size);
4255b8e80941Smrg   }
4256b8e80941Smrg
4257848b8605Smrg   if (buffer == 0) {
4258848b8605Smrg      bufObj = ctx->Shared->NullBufferObj;
4259848b8605Smrg   } else {
4260848b8605Smrg      bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4261b8e80941Smrg      if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
4262b8e80941Smrg                                        &bufObj, "glBindBufferRange"))
4263b8e80941Smrg         return;
4264848b8605Smrg
4265b8e80941Smrg      if (!no_error && !bufObj) {
4266b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
4267b8e80941Smrg                     "glBindBufferRange(invalid buffer=%u)", buffer);
4268b8e80941Smrg         return;
4269b8e80941Smrg      }
4270848b8605Smrg   }
4271848b8605Smrg
4272b8e80941Smrg   if (no_error) {
4273b8e80941Smrg      switch (target) {
4274b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
4275b8e80941Smrg         _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject,
4276b8e80941Smrg                                     index, bufObj, offset, size);
4277848b8605Smrg         return;
4278b8e80941Smrg      case GL_UNIFORM_BUFFER:
4279b8e80941Smrg         bind_buffer_range_uniform_buffer(ctx, index, bufObj, offset, size);
4280b8e80941Smrg         return;
4281b8e80941Smrg      case GL_SHADER_STORAGE_BUFFER:
4282b8e80941Smrg         bind_buffer_range_shader_storage_buffer(ctx, index, bufObj, offset,
4283b8e80941Smrg                                                 size);
4284b8e80941Smrg         return;
4285b8e80941Smrg      case GL_ATOMIC_COUNTER_BUFFER:
4286b8e80941Smrg         bind_buffer_range_atomic_buffer(ctx, index, bufObj, offset, size);
4287b8e80941Smrg         return;
4288b8e80941Smrg      default:
4289b8e80941Smrg         unreachable("invalid BindBufferRange target with KHR_no_error");
4290b8e80941Smrg      }
4291b8e80941Smrg   } else {
4292b8e80941Smrg      if (buffer != 0) {
4293b8e80941Smrg         if (size <= 0) {
4294b8e80941Smrg            _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)",
4295b8e80941Smrg                        (int) size);
4296b8e80941Smrg            return;
4297b8e80941Smrg         }
4298848b8605Smrg      }
4299848b8605Smrg
4300b8e80941Smrg      switch (target) {
4301b8e80941Smrg      case GL_TRANSFORM_FEEDBACK_BUFFER:
4302b8e80941Smrg         if (!_mesa_validate_buffer_range_xfb(ctx,
4303b8e80941Smrg                                              ctx->TransformFeedback.CurrentObject,
4304b8e80941Smrg                                              index, bufObj, offset, size,
4305b8e80941Smrg                                              false))
4306b8e80941Smrg            return;
4307b8e80941Smrg
4308b8e80941Smrg         _mesa_bind_buffer_range_xfb(ctx, ctx->TransformFeedback.CurrentObject,
4309b8e80941Smrg                                     index, bufObj, offset, size);
4310b8e80941Smrg         return;
4311b8e80941Smrg      case GL_UNIFORM_BUFFER:
4312b8e80941Smrg         bind_buffer_range_uniform_buffer_err(ctx, index, bufObj, offset,
4313b8e80941Smrg                                              size);
4314b8e80941Smrg         return;
4315b8e80941Smrg      case GL_SHADER_STORAGE_BUFFER:
4316b8e80941Smrg         bind_buffer_range_shader_storage_buffer_err(ctx, index, bufObj,
4317b8e80941Smrg                                                     offset, size);
4318b8e80941Smrg         return;
4319b8e80941Smrg      case GL_ATOMIC_COUNTER_BUFFER:
4320b8e80941Smrg         bind_buffer_range_atomic_buffer_err(ctx, index, bufObj,
4321b8e80941Smrg                                             offset, size);
4322b8e80941Smrg         return;
4323b8e80941Smrg      default:
4324b8e80941Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferRange(target)");
4325b8e80941Smrg         return;
4326b8e80941Smrg      }
4327848b8605Smrg   }
4328848b8605Smrg}
4329848b8605Smrg
4330b8e80941Smrgvoid GLAPIENTRY
4331b8e80941Smrg_mesa_BindBufferRange_no_error(GLenum target, GLuint index, GLuint buffer,
4332b8e80941Smrg                               GLintptr offset, GLsizeiptr size)
4333b8e80941Smrg{
4334b8e80941Smrg   bind_buffer_range(target, index, buffer, offset, size, true);
4335b8e80941Smrg}
4336b8e80941Smrg
4337b8e80941Smrgvoid GLAPIENTRY
4338b8e80941Smrg_mesa_BindBufferRange(GLenum target, GLuint index,
4339b8e80941Smrg                      GLuint buffer, GLintptr offset, GLsizeiptr size)
4340b8e80941Smrg{
4341b8e80941Smrg   bind_buffer_range(target, index, buffer, offset, size, false);
4342b8e80941Smrg}
4343b8e80941Smrg
4344848b8605Smrgvoid GLAPIENTRY
4345848b8605Smrg_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
4346848b8605Smrg{
4347848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
4348848b8605Smrg   struct gl_buffer_object *bufObj;
4349848b8605Smrg
4350b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
4351b8e80941Smrg      _mesa_debug(ctx, "glBindBufferBase(%s, %u, %u)\n",
4352b8e80941Smrg                  _mesa_enum_to_string(target), index, buffer);
4353b8e80941Smrg   }
4354b8e80941Smrg
4355848b8605Smrg   if (buffer == 0) {
4356848b8605Smrg      bufObj = ctx->Shared->NullBufferObj;
4357848b8605Smrg   } else {
4358848b8605Smrg      bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4359b8e80941Smrg      if (!_mesa_handle_bind_buffer_gen(ctx, buffer,
4360b8e80941Smrg                                        &bufObj, "glBindBufferBase"))
4361b8e80941Smrg         return;
4362848b8605Smrg
4363b8e80941Smrg      if (!bufObj) {
4364b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
4365b8e80941Smrg                     "glBindBufferBase(invalid buffer=%u)", buffer);
4366b8e80941Smrg         return;
4367b8e80941Smrg      }
4368848b8605Smrg   }
4369848b8605Smrg
4370848b8605Smrg   /* Note that there's some oddness in the GL 3.1-GL 3.3 specifications with
4371848b8605Smrg    * regards to BindBufferBase.  It says (GL 3.1 core spec, page 63):
4372848b8605Smrg    *
4373848b8605Smrg    *     "BindBufferBase is equivalent to calling BindBufferRange with offset
4374848b8605Smrg    *      zero and size equal to the size of buffer."
4375848b8605Smrg    *
4376848b8605Smrg    * but it says for glGetIntegeri_v (GL 3.1 core spec, page 230):
4377848b8605Smrg    *
4378848b8605Smrg    *     "If the parameter (starting offset or size) was not specified when the
4379848b8605Smrg    *      buffer object was bound, zero is returned."
4380848b8605Smrg    *
4381848b8605Smrg    * What happens if the size of the buffer changes?  Does the size of the
4382848b8605Smrg    * buffer at the moment glBindBufferBase was called still play a role, like
4383848b8605Smrg    * the first quote would imply, or is the size meaningless in the
4384848b8605Smrg    * glBindBufferBase case like the second quote would suggest?  The GL 4.1
4385848b8605Smrg    * core spec page 45 says:
4386848b8605Smrg    *
4387848b8605Smrg    *     "It is equivalent to calling BindBufferRange with offset zero, while
4388848b8605Smrg    *      size is determined by the size of the bound buffer at the time the
4389848b8605Smrg    *      binding is used."
4390848b8605Smrg    *
4391848b8605Smrg    * My interpretation is that the GL 4.1 spec was a clarification of the
4392848b8605Smrg    * behavior, not a change.  In particular, this choice will only make
4393848b8605Smrg    * rendering work in cases where it would have had undefined results.
4394848b8605Smrg    */
4395848b8605Smrg
4396848b8605Smrg   switch (target) {
4397848b8605Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
4398b8e80941Smrg      _mesa_bind_buffer_base_transform_feedback(ctx,
4399b8e80941Smrg                                                ctx->TransformFeedback.CurrentObject,
4400b8e80941Smrg                                                index, bufObj, false);
4401848b8605Smrg      return;
4402848b8605Smrg   case GL_UNIFORM_BUFFER:
4403848b8605Smrg      bind_buffer_base_uniform_buffer(ctx, index, bufObj);
4404848b8605Smrg      return;
4405b8e80941Smrg   case GL_SHADER_STORAGE_BUFFER:
4406b8e80941Smrg      bind_buffer_base_shader_storage_buffer(ctx, index, bufObj);
4407b8e80941Smrg      return;
4408848b8605Smrg   case GL_ATOMIC_COUNTER_BUFFER:
4409b8e80941Smrg      bind_buffer_base_atomic_buffer(ctx, index, bufObj);
4410848b8605Smrg      return;
4411848b8605Smrg   default:
4412848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferBase(target)");
4413848b8605Smrg      return;
4414848b8605Smrg   }
4415848b8605Smrg}
4416848b8605Smrg
4417848b8605Smrgvoid GLAPIENTRY
4418848b8605Smrg_mesa_BindBuffersRange(GLenum target, GLuint first, GLsizei count,
4419848b8605Smrg                       const GLuint *buffers,
4420848b8605Smrg                       const GLintptr *offsets, const GLsizeiptr *sizes)
4421848b8605Smrg{
4422848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
4423848b8605Smrg
4424b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
4425b8e80941Smrg      _mesa_debug(ctx, "glBindBuffersRange(%s, %u, %d, %p, %p, %p)\n",
4426b8e80941Smrg                  _mesa_enum_to_string(target), first, count,
4427b8e80941Smrg                  buffers, offsets, sizes);
4428b8e80941Smrg   }
4429b8e80941Smrg
4430848b8605Smrg   switch (target) {
4431848b8605Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
4432b8e80941Smrg      bind_xfb_buffers(ctx, first, count, buffers, true, offsets, sizes,
4433b8e80941Smrg                       "glBindBuffersRange");
4434848b8605Smrg      return;
4435848b8605Smrg   case GL_UNIFORM_BUFFER:
4436b8e80941Smrg      bind_uniform_buffers(ctx, first, count, buffers, true, offsets, sizes,
4437b8e80941Smrg                           "glBindBuffersRange");
4438b8e80941Smrg      return;
4439b8e80941Smrg   case GL_SHADER_STORAGE_BUFFER:
4440b8e80941Smrg      bind_shader_storage_buffers(ctx, first, count, buffers, true, offsets, sizes,
4441b8e80941Smrg                                  "glBindBuffersRange");
4442848b8605Smrg      return;
4443848b8605Smrg   case GL_ATOMIC_COUNTER_BUFFER:
4444b8e80941Smrg      bind_atomic_buffers(ctx, first, count, buffers, true, offsets, sizes,
4445b8e80941Smrg                          "glBindBuffersRange");
4446848b8605Smrg      return;
4447848b8605Smrg   default:
4448848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersRange(target=%s)",
4449b8e80941Smrg                  _mesa_enum_to_string(target));
4450848b8605Smrg      break;
4451848b8605Smrg   }
4452848b8605Smrg}
4453848b8605Smrg
4454848b8605Smrgvoid GLAPIENTRY
4455848b8605Smrg_mesa_BindBuffersBase(GLenum target, GLuint first, GLsizei count,
4456848b8605Smrg                      const GLuint *buffers)
4457848b8605Smrg{
4458848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
4459848b8605Smrg
4460b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_API) {
4461b8e80941Smrg      _mesa_debug(ctx, "glBindBuffersBase(%s, %u, %d, %p)\n",
4462b8e80941Smrg                  _mesa_enum_to_string(target), first, count, buffers);
4463b8e80941Smrg   }
4464b8e80941Smrg
4465848b8605Smrg   switch (target) {
4466848b8605Smrg   case GL_TRANSFORM_FEEDBACK_BUFFER:
4467b8e80941Smrg      bind_xfb_buffers(ctx, first, count, buffers, false, NULL, NULL,
4468b8e80941Smrg                       "glBindBuffersBase");
4469848b8605Smrg      return;
4470848b8605Smrg   case GL_UNIFORM_BUFFER:
4471b8e80941Smrg      bind_uniform_buffers(ctx, first, count, buffers, false, NULL, NULL,
4472b8e80941Smrg                           "glBindBuffersBase");
4473b8e80941Smrg      return;
4474b8e80941Smrg   case GL_SHADER_STORAGE_BUFFER:
4475b8e80941Smrg      bind_shader_storage_buffers(ctx, first, count, buffers, false, NULL, NULL,
4476b8e80941Smrg                                  "glBindBuffersBase");
4477848b8605Smrg      return;
4478848b8605Smrg   case GL_ATOMIC_COUNTER_BUFFER:
4479b8e80941Smrg      bind_atomic_buffers(ctx, first, count, buffers, false, NULL, NULL,
4480b8e80941Smrg                          "glBindBuffersBase");
4481848b8605Smrg      return;
4482848b8605Smrg   default:
4483848b8605Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glBindBuffersBase(target=%s)",
4484b8e80941Smrg                  _mesa_enum_to_string(target));
4485848b8605Smrg      break;
4486848b8605Smrg   }
4487848b8605Smrg}
4488848b8605Smrg
4489b8e80941Smrgstatic ALWAYS_INLINE void
4490b8e80941Smrginvalidate_buffer_subdata(struct gl_context *ctx,
4491b8e80941Smrg                          struct gl_buffer_object *bufObj, GLintptr offset,
4492b8e80941Smrg                          GLsizeiptr length)
4493b8e80941Smrg{
4494b8e80941Smrg   if (ctx->Driver.InvalidateBufferSubData)
4495b8e80941Smrg      ctx->Driver.InvalidateBufferSubData(ctx, bufObj, offset, length);
4496b8e80941Smrg}
4497b8e80941Smrg
4498b8e80941Smrgvoid GLAPIENTRY
4499b8e80941Smrg_mesa_InvalidateBufferSubData_no_error(GLuint buffer, GLintptr offset,
4500b8e80941Smrg                                       GLsizeiptr length)
4501b8e80941Smrg{
4502b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
4503b8e80941Smrg
4504b8e80941Smrg   struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4505b8e80941Smrg   invalidate_buffer_subdata(ctx, bufObj, offset, length);
4506b8e80941Smrg}
4507b8e80941Smrg
4508848b8605Smrgvoid GLAPIENTRY
4509848b8605Smrg_mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset,
4510848b8605Smrg                              GLsizeiptr length)
4511848b8605Smrg{
4512848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
4513848b8605Smrg   struct gl_buffer_object *bufObj;
4514848b8605Smrg   const GLintptr end = offset + length;
4515848b8605Smrg
4516b8e80941Smrg   /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
4517b8e80941Smrg    * Profile) spec says:
4518b8e80941Smrg    *
4519b8e80941Smrg    *     "An INVALID_VALUE error is generated if buffer is zero or is not the
4520b8e80941Smrg    *     name of an existing buffer object."
4521b8e80941Smrg    */
4522848b8605Smrg   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4523b8e80941Smrg   if (!bufObj || bufObj == &DummyBufferObject) {
4524848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
4525b8e80941Smrg                  "glInvalidateBufferSubData(name = %u) invalid object",
4526848b8605Smrg                  buffer);
4527848b8605Smrg      return;
4528848b8605Smrg   }
4529848b8605Smrg
4530848b8605Smrg   /* The GL_ARB_invalidate_subdata spec says:
4531848b8605Smrg    *
4532848b8605Smrg    *     "An INVALID_VALUE error is generated if <offset> or <length> is
4533848b8605Smrg    *     negative, or if <offset> + <length> is greater than the value of
4534848b8605Smrg    *     BUFFER_SIZE."
4535848b8605Smrg    */
4536b8e80941Smrg   if (offset < 0 || length < 0 || end > bufObj->Size) {
4537848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
4538848b8605Smrg                  "glInvalidateBufferSubData(invalid offset or length)");
4539848b8605Smrg      return;
4540848b8605Smrg   }
4541848b8605Smrg
4542848b8605Smrg   /* The OpenGL 4.4 (Core Profile) spec says:
4543848b8605Smrg    *
4544848b8605Smrg    *     "An INVALID_OPERATION error is generated if buffer is currently
4545848b8605Smrg    *     mapped by MapBuffer or if the invalidate range intersects the range
4546848b8605Smrg    *     currently mapped by MapBufferRange, unless it was mapped
4547848b8605Smrg    *     with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
4548848b8605Smrg    */
4549848b8605Smrg   if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) &&
4550848b8605Smrg       bufferobj_range_mapped(bufObj, offset, length)) {
4551848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
4552848b8605Smrg                  "glInvalidateBufferSubData(intersection with mapped "
4553848b8605Smrg                  "range)");
4554848b8605Smrg      return;
4555848b8605Smrg   }
4556848b8605Smrg
4557b8e80941Smrg   invalidate_buffer_subdata(ctx, bufObj, offset, length);
4558b8e80941Smrg}
4559b8e80941Smrg
4560b8e80941Smrgvoid GLAPIENTRY
4561b8e80941Smrg_mesa_InvalidateBufferData_no_error(GLuint buffer)
4562b8e80941Smrg{
4563b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
4564b8e80941Smrg
4565b8e80941Smrg   struct gl_buffer_object *bufObj =_mesa_lookup_bufferobj(ctx, buffer);
4566b8e80941Smrg   invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size);
4567848b8605Smrg}
4568848b8605Smrg
4569848b8605Smrgvoid GLAPIENTRY
4570848b8605Smrg_mesa_InvalidateBufferData(GLuint buffer)
4571848b8605Smrg{
4572848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
4573848b8605Smrg   struct gl_buffer_object *bufObj;
4574848b8605Smrg
4575b8e80941Smrg   /* Section 6.5 (Invalidating Buffer Data) of the OpenGL 4.5 (Compatibility
4576b8e80941Smrg    * Profile) spec says:
4577b8e80941Smrg    *
4578b8e80941Smrg    *     "An INVALID_VALUE error is generated if buffer is zero or is not the
4579b8e80941Smrg    *     name of an existing buffer object."
4580b8e80941Smrg    */
4581848b8605Smrg   bufObj = _mesa_lookup_bufferobj(ctx, buffer);
4582b8e80941Smrg   if (!bufObj || bufObj == &DummyBufferObject) {
4583848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
4584b8e80941Smrg                  "glInvalidateBufferData(name = %u) invalid object",
4585848b8605Smrg                  buffer);
4586848b8605Smrg      return;
4587848b8605Smrg   }
4588848b8605Smrg
4589848b8605Smrg   /* The OpenGL 4.4 (Core Profile) spec says:
4590848b8605Smrg    *
4591848b8605Smrg    *     "An INVALID_OPERATION error is generated if buffer is currently
4592848b8605Smrg    *     mapped by MapBuffer or if the invalidate range intersects the range
4593848b8605Smrg    *     currently mapped by MapBufferRange, unless it was mapped
4594848b8605Smrg    *     with MAP_PERSISTENT_BIT set in the MapBufferRange access flags."
4595848b8605Smrg    */
4596848b8605Smrg   if (_mesa_check_disallowed_mapping(bufObj)) {
4597848b8605Smrg      _mesa_error(ctx, GL_INVALID_OPERATION,
4598848b8605Smrg                  "glInvalidateBufferData(intersection with mapped "
4599848b8605Smrg                  "range)");
4600848b8605Smrg      return;
4601848b8605Smrg   }
4602848b8605Smrg
4603b8e80941Smrg   invalidate_buffer_subdata(ctx, bufObj, 0, bufObj->Size);
4604b8e80941Smrg}
4605b8e80941Smrg
4606b8e80941Smrgstatic void
4607b8e80941Smrgbuffer_page_commitment(struct gl_context *ctx,
4608b8e80941Smrg                       struct gl_buffer_object *bufferObj,
4609b8e80941Smrg                       GLintptr offset, GLsizeiptr size,
4610b8e80941Smrg                       GLboolean commit, const char *func)
4611b8e80941Smrg{
4612b8e80941Smrg   if (!(bufferObj->StorageFlags & GL_SPARSE_STORAGE_BIT_ARB)) {
4613b8e80941Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(not a sparse buffer object)",
4614b8e80941Smrg                  func);
4615b8e80941Smrg      return;
4616b8e80941Smrg   }
4617b8e80941Smrg
4618b8e80941Smrg   if (size < 0 || size > bufferObj->Size ||
4619b8e80941Smrg       offset < 0 || offset > bufferObj->Size - size) {
4620b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(out of bounds)",
4621b8e80941Smrg                  func);
4622b8e80941Smrg      return;
4623b8e80941Smrg   }
4624b8e80941Smrg
4625b8e80941Smrg   /* The GL_ARB_sparse_buffer extension specification says:
4626b8e80941Smrg    *
4627b8e80941Smrg    *     "INVALID_VALUE is generated by BufferPageCommitmentARB if <offset> is
4628b8e80941Smrg    *     not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB, or if <size>
4629b8e80941Smrg    *     is not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB and does
4630b8e80941Smrg    *     not extend to the end of the buffer's data store."
4631848b8605Smrg    */
4632b8e80941Smrg   if (offset % ctx->Const.SparseBufferPageSize != 0) {
4633b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset not aligned to page size)",
4634b8e80941Smrg                  func);
4635b8e80941Smrg      return;
4636b8e80941Smrg   }
4637b8e80941Smrg
4638b8e80941Smrg   if (size % ctx->Const.SparseBufferPageSize != 0 &&
4639b8e80941Smrg       offset + size != bufferObj->Size) {
4640b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size not aligned to page size)",
4641b8e80941Smrg                  func);
4642b8e80941Smrg      return;
4643b8e80941Smrg   }
4644b8e80941Smrg
4645b8e80941Smrg   ctx->Driver.BufferPageCommitment(ctx, bufferObj, offset, size, commit);
4646b8e80941Smrg}
4647b8e80941Smrg
4648b8e80941Smrgvoid GLAPIENTRY
4649b8e80941Smrg_mesa_BufferPageCommitmentARB(GLenum target, GLintptr offset, GLsizeiptr size,
4650b8e80941Smrg                              GLboolean commit)
4651b8e80941Smrg{
4652b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
4653b8e80941Smrg   struct gl_buffer_object *bufferObj;
4654b8e80941Smrg
4655b8e80941Smrg   bufferObj = get_buffer(ctx, "glBufferPageCommitmentARB", target,
4656b8e80941Smrg                          GL_INVALID_ENUM);
4657b8e80941Smrg   if (!bufferObj)
4658b8e80941Smrg      return;
4659b8e80941Smrg
4660b8e80941Smrg   buffer_page_commitment(ctx, bufferObj, offset, size, commit,
4661b8e80941Smrg                          "glBufferPageCommitmentARB");
4662b8e80941Smrg}
4663b8e80941Smrg
4664b8e80941Smrgvoid GLAPIENTRY
4665b8e80941Smrg_mesa_NamedBufferPageCommitmentARB(GLuint buffer, GLintptr offset,
4666b8e80941Smrg                                   GLsizeiptr size, GLboolean commit)
4667b8e80941Smrg{
4668b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
4669b8e80941Smrg   struct gl_buffer_object *bufferObj;
4670b8e80941Smrg
4671b8e80941Smrg   bufferObj = _mesa_lookup_bufferobj(ctx, buffer);
4672b8e80941Smrg   if (!bufferObj || bufferObj == &DummyBufferObject) {
4673b8e80941Smrg      /* Note: the extension spec is not clear about the excpected error value. */
4674b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
4675b8e80941Smrg                  "glNamedBufferPageCommitmentARB(name = %u) invalid object",
4676b8e80941Smrg                  buffer);
4677b8e80941Smrg      return;
4678b8e80941Smrg   }
4679b8e80941Smrg
4680b8e80941Smrg   buffer_page_commitment(ctx, bufferObj, offset, size, commit,
4681b8e80941Smrg                          "glNamedBufferPageCommitmentARB");
4682848b8605Smrg}
4683