arrayobj.c revision 7ec681f3
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5 * (C) Copyright IBM Corporation 2006
6 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/**
29 * \file arrayobj.c
30 *
31 * Implementation of Vertex Array Objects (VAOs), from OpenGL 3.1+ /
32 * the GL_ARB_vertex_array_object extension.
33 *
34 * \todo
35 * The code in this file borrows a lot from bufferobj.c.  There's a certain
36 * amount of cruft left over from that origin that may be unnecessary.
37 *
38 * \author Ian Romanick <idr@us.ibm.com>
39 * \author Brian Paul
40 */
41
42
43#include "glheader.h"
44#include "hash.h"
45#include "image.h"
46
47#include "context.h"
48#include "bufferobj.h"
49#include "arrayobj.h"
50#include "draw_validate.h"
51#include "macros.h"
52#include "mtypes.h"
53#include "state.h"
54#include "varray.h"
55#include "util/bitscan.h"
56#include "util/u_atomic.h"
57#include "util/u_math.h"
58#include "util/u_memory.h"
59
60
61const GLubyte
62_mesa_vao_attribute_map[ATTRIBUTE_MAP_MODE_MAX][VERT_ATTRIB_MAX] =
63{
64   /* ATTRIBUTE_MAP_MODE_IDENTITY
65    *
66    * Grab vertex processing attribute VERT_ATTRIB_POS from
67    * the VAO attribute VERT_ATTRIB_POS, and grab vertex processing
68    * attribute VERT_ATTRIB_GENERIC0 from the VAO attribute
69    * VERT_ATTRIB_GENERIC0.
70    */
71   {
72      VERT_ATTRIB_POS,                 /* VERT_ATTRIB_POS */
73      VERT_ATTRIB_NORMAL,              /* VERT_ATTRIB_NORMAL */
74      VERT_ATTRIB_COLOR0,              /* VERT_ATTRIB_COLOR0 */
75      VERT_ATTRIB_COLOR1,              /* VERT_ATTRIB_COLOR1 */
76      VERT_ATTRIB_FOG,                 /* VERT_ATTRIB_FOG */
77      VERT_ATTRIB_COLOR_INDEX,         /* VERT_ATTRIB_COLOR_INDEX */
78      VERT_ATTRIB_TEX0,                /* VERT_ATTRIB_TEX0 */
79      VERT_ATTRIB_TEX1,                /* VERT_ATTRIB_TEX1 */
80      VERT_ATTRIB_TEX2,                /* VERT_ATTRIB_TEX2 */
81      VERT_ATTRIB_TEX3,                /* VERT_ATTRIB_TEX3 */
82      VERT_ATTRIB_TEX4,                /* VERT_ATTRIB_TEX4 */
83      VERT_ATTRIB_TEX5,                /* VERT_ATTRIB_TEX5 */
84      VERT_ATTRIB_TEX6,                /* VERT_ATTRIB_TEX6 */
85      VERT_ATTRIB_TEX7,                /* VERT_ATTRIB_TEX7 */
86      VERT_ATTRIB_POINT_SIZE,          /* VERT_ATTRIB_POINT_SIZE */
87      VERT_ATTRIB_GENERIC0,            /* VERT_ATTRIB_GENERIC0 */
88      VERT_ATTRIB_GENERIC1,            /* VERT_ATTRIB_GENERIC1 */
89      VERT_ATTRIB_GENERIC2,            /* VERT_ATTRIB_GENERIC2 */
90      VERT_ATTRIB_GENERIC3,            /* VERT_ATTRIB_GENERIC3 */
91      VERT_ATTRIB_GENERIC4,            /* VERT_ATTRIB_GENERIC4 */
92      VERT_ATTRIB_GENERIC5,            /* VERT_ATTRIB_GENERIC5 */
93      VERT_ATTRIB_GENERIC6,            /* VERT_ATTRIB_GENERIC6 */
94      VERT_ATTRIB_GENERIC7,            /* VERT_ATTRIB_GENERIC7 */
95      VERT_ATTRIB_GENERIC8,            /* VERT_ATTRIB_GENERIC8 */
96      VERT_ATTRIB_GENERIC9,            /* VERT_ATTRIB_GENERIC9 */
97      VERT_ATTRIB_GENERIC10,           /* VERT_ATTRIB_GENERIC10 */
98      VERT_ATTRIB_GENERIC11,           /* VERT_ATTRIB_GENERIC11 */
99      VERT_ATTRIB_GENERIC12,           /* VERT_ATTRIB_GENERIC12 */
100      VERT_ATTRIB_GENERIC13,           /* VERT_ATTRIB_GENERIC13 */
101      VERT_ATTRIB_GENERIC14,           /* VERT_ATTRIB_GENERIC14 */
102      VERT_ATTRIB_GENERIC15,           /* VERT_ATTRIB_GENERIC15 */
103      VERT_ATTRIB_EDGEFLAG,            /* VERT_ATTRIB_EDGEFLAG */
104   },
105
106   /* ATTRIBUTE_MAP_MODE_POSITION
107    *
108    * Grab vertex processing attribute VERT_ATTRIB_POS as well as
109    * vertex processing attribute VERT_ATTRIB_GENERIC0 from the
110    * VAO attribute VERT_ATTRIB_POS.
111    */
112   {
113      VERT_ATTRIB_POS,                 /* VERT_ATTRIB_POS */
114      VERT_ATTRIB_NORMAL,              /* VERT_ATTRIB_NORMAL */
115      VERT_ATTRIB_COLOR0,              /* VERT_ATTRIB_COLOR0 */
116      VERT_ATTRIB_COLOR1,              /* VERT_ATTRIB_COLOR1 */
117      VERT_ATTRIB_FOG,                 /* VERT_ATTRIB_FOG */
118      VERT_ATTRIB_COLOR_INDEX,         /* VERT_ATTRIB_COLOR_INDEX */
119      VERT_ATTRIB_TEX0,                /* VERT_ATTRIB_TEX0 */
120      VERT_ATTRIB_TEX1,                /* VERT_ATTRIB_TEX1 */
121      VERT_ATTRIB_TEX2,                /* VERT_ATTRIB_TEX2 */
122      VERT_ATTRIB_TEX3,                /* VERT_ATTRIB_TEX3 */
123      VERT_ATTRIB_TEX4,                /* VERT_ATTRIB_TEX4 */
124      VERT_ATTRIB_TEX5,                /* VERT_ATTRIB_TEX5 */
125      VERT_ATTRIB_TEX6,                /* VERT_ATTRIB_TEX6 */
126      VERT_ATTRIB_TEX7,                /* VERT_ATTRIB_TEX7 */
127      VERT_ATTRIB_POINT_SIZE,          /* VERT_ATTRIB_POINT_SIZE */
128      VERT_ATTRIB_POS,                 /* VERT_ATTRIB_GENERIC0 */
129      VERT_ATTRIB_GENERIC1,            /* VERT_ATTRIB_GENERIC1 */
130      VERT_ATTRIB_GENERIC2,            /* VERT_ATTRIB_GENERIC2 */
131      VERT_ATTRIB_GENERIC3,            /* VERT_ATTRIB_GENERIC3 */
132      VERT_ATTRIB_GENERIC4,            /* VERT_ATTRIB_GENERIC4 */
133      VERT_ATTRIB_GENERIC5,            /* VERT_ATTRIB_GENERIC5 */
134      VERT_ATTRIB_GENERIC6,            /* VERT_ATTRIB_GENERIC6 */
135      VERT_ATTRIB_GENERIC7,            /* VERT_ATTRIB_GENERIC7 */
136      VERT_ATTRIB_GENERIC8,            /* VERT_ATTRIB_GENERIC8 */
137      VERT_ATTRIB_GENERIC9,            /* VERT_ATTRIB_GENERIC9 */
138      VERT_ATTRIB_GENERIC10,           /* VERT_ATTRIB_GENERIC10 */
139      VERT_ATTRIB_GENERIC11,           /* VERT_ATTRIB_GENERIC11 */
140      VERT_ATTRIB_GENERIC12,           /* VERT_ATTRIB_GENERIC12 */
141      VERT_ATTRIB_GENERIC13,           /* VERT_ATTRIB_GENERIC13 */
142      VERT_ATTRIB_GENERIC14,           /* VERT_ATTRIB_GENERIC14 */
143      VERT_ATTRIB_GENERIC15,           /* VERT_ATTRIB_GENERIC15 */
144      VERT_ATTRIB_EDGEFLAG,            /* VERT_ATTRIB_EDGEFLAG */
145   },
146
147   /* ATTRIBUTE_MAP_MODE_GENERIC0
148    *
149    * Grab vertex processing attribute VERT_ATTRIB_POS as well as
150    * vertex processing attribute VERT_ATTRIB_GENERIC0 from the
151    * VAO attribute VERT_ATTRIB_GENERIC0.
152    */
153   {
154      VERT_ATTRIB_GENERIC0,            /* VERT_ATTRIB_POS */
155      VERT_ATTRIB_NORMAL,              /* VERT_ATTRIB_NORMAL */
156      VERT_ATTRIB_COLOR0,              /* VERT_ATTRIB_COLOR0 */
157      VERT_ATTRIB_COLOR1,              /* VERT_ATTRIB_COLOR1 */
158      VERT_ATTRIB_FOG,                 /* VERT_ATTRIB_FOG */
159      VERT_ATTRIB_COLOR_INDEX,         /* VERT_ATTRIB_COLOR_INDEX */
160      VERT_ATTRIB_TEX0,                /* VERT_ATTRIB_TEX0 */
161      VERT_ATTRIB_TEX1,                /* VERT_ATTRIB_TEX1 */
162      VERT_ATTRIB_TEX2,                /* VERT_ATTRIB_TEX2 */
163      VERT_ATTRIB_TEX3,                /* VERT_ATTRIB_TEX3 */
164      VERT_ATTRIB_TEX4,                /* VERT_ATTRIB_TEX4 */
165      VERT_ATTRIB_TEX5,                /* VERT_ATTRIB_TEX5 */
166      VERT_ATTRIB_TEX6,                /* VERT_ATTRIB_TEX6 */
167      VERT_ATTRIB_TEX7,                /* VERT_ATTRIB_TEX7 */
168      VERT_ATTRIB_POINT_SIZE,          /* VERT_ATTRIB_POINT_SIZE */
169      VERT_ATTRIB_GENERIC0,            /* VERT_ATTRIB_GENERIC0 */
170      VERT_ATTRIB_GENERIC1,            /* VERT_ATTRIB_GENERIC1 */
171      VERT_ATTRIB_GENERIC2,            /* VERT_ATTRIB_GENERIC2 */
172      VERT_ATTRIB_GENERIC3,            /* VERT_ATTRIB_GENERIC3 */
173      VERT_ATTRIB_GENERIC4,            /* VERT_ATTRIB_GENERIC4 */
174      VERT_ATTRIB_GENERIC5,            /* VERT_ATTRIB_GENERIC5 */
175      VERT_ATTRIB_GENERIC6,            /* VERT_ATTRIB_GENERIC6 */
176      VERT_ATTRIB_GENERIC7,            /* VERT_ATTRIB_GENERIC7 */
177      VERT_ATTRIB_GENERIC8,            /* VERT_ATTRIB_GENERIC8 */
178      VERT_ATTRIB_GENERIC9,            /* VERT_ATTRIB_GENERIC9 */
179      VERT_ATTRIB_GENERIC10,           /* VERT_ATTRIB_GENERIC10 */
180      VERT_ATTRIB_GENERIC11,           /* VERT_ATTRIB_GENERIC11 */
181      VERT_ATTRIB_GENERIC12,           /* VERT_ATTRIB_GENERIC12 */
182      VERT_ATTRIB_GENERIC13,           /* VERT_ATTRIB_GENERIC13 */
183      VERT_ATTRIB_GENERIC14,           /* VERT_ATTRIB_GENERIC14 */
184      VERT_ATTRIB_GENERIC15,           /* VERT_ATTRIB_GENERIC15 */
185      VERT_ATTRIB_EDGEFLAG,            /* VERT_ATTRIB_EDGEFLAG */
186   }
187};
188
189
190/**
191 * Look up the array object for the given ID.
192 *
193 * \returns
194 * Either a pointer to the array object with the specified ID or \c NULL for
195 * a non-existent ID.  The spec defines ID 0 as being technically
196 * non-existent.
197 */
198
199struct gl_vertex_array_object *
200_mesa_lookup_vao(struct gl_context *ctx, GLuint id)
201{
202   /* The ARB_direct_state_access specification says:
203    *
204    *    "<vaobj> is [compatibility profile:
205    *     zero, indicating the default vertex array object, or]
206    *     the name of the vertex array object."
207    */
208   if (id == 0) {
209      if (ctx->API == API_OPENGL_COMPAT)
210         return ctx->Array.DefaultVAO;
211
212      return NULL;
213   } else {
214      struct gl_vertex_array_object *vao;
215
216      if (ctx->Array.LastLookedUpVAO &&
217          ctx->Array.LastLookedUpVAO->Name == id) {
218         vao = ctx->Array.LastLookedUpVAO;
219      } else {
220         vao = (struct gl_vertex_array_object *)
221            _mesa_HashLookupLocked(ctx->Array.Objects, id);
222
223         _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao);
224      }
225
226      return vao;
227   }
228}
229
230
231/**
232 * Looks up the array object for the given ID.
233 *
234 * While _mesa_lookup_vao doesn't generate an error if the object does not
235 * exist, this function comes in two variants.
236 * If is_ext_dsa is false, this function generates a GL_INVALID_OPERATION
237 * error if the array object does not exist. It also returns the default
238 * array object when ctx is a compatibility profile context and id is zero.
239 * If is_ext_dsa is true, 0 is not a valid name. If the name exists but
240 * the object has never been bound, it is initialized.
241 */
242struct gl_vertex_array_object *
243_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id,
244                     bool is_ext_dsa, const char *caller)
245{
246   /* The ARB_direct_state_access specification says:
247    *
248    *    "<vaobj> is [compatibility profile:
249    *     zero, indicating the default vertex array object, or]
250    *     the name of the vertex array object."
251    */
252   if (id == 0) {
253      if (is_ext_dsa || ctx->API == API_OPENGL_CORE) {
254         _mesa_error(ctx, GL_INVALID_OPERATION,
255                     "%s(zero is not valid vaobj name%s)",
256                     caller,
257                     is_ext_dsa ? "" : " in a core profile context");
258         return NULL;
259      }
260
261      return ctx->Array.DefaultVAO;
262   } else {
263      struct gl_vertex_array_object *vao;
264
265      if (ctx->Array.LastLookedUpVAO &&
266          ctx->Array.LastLookedUpVAO->Name == id) {
267         vao = ctx->Array.LastLookedUpVAO;
268      } else {
269         vao = (struct gl_vertex_array_object *)
270            _mesa_HashLookupLocked(ctx->Array.Objects, id);
271
272         /* The ARB_direct_state_access specification says:
273          *
274          *    "An INVALID_OPERATION error is generated if <vaobj> is not
275          *     [compatibility profile: zero or] the name of an existing
276          *     vertex array object."
277          */
278         if (!vao || (!is_ext_dsa && !vao->EverBound)) {
279            _mesa_error(ctx, GL_INVALID_OPERATION,
280                        "%s(non-existent vaobj=%u)", caller, id);
281            return NULL;
282         }
283
284         /* The EXT_direct_state_access specification says:
285         *
286         *    "If the vertex array object named by the vaobj parameter has not
287         *     been previously bound but has been generated (without subsequent
288         *     deletion) by GenVertexArrays, the GL first creates a new state
289         *     vector in the same manner as when BindVertexArray creates a new
290         *     vertex array object."
291         */
292         if (vao && is_ext_dsa && !vao->EverBound)
293            vao->EverBound = true;
294
295         _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao);
296      }
297
298      return vao;
299   }
300}
301
302
303/**
304 * For all the vertex binding points in the array object, unbind any pointers
305 * to any buffer objects (VBOs).
306 * This is done just prior to array object destruction.
307 */
308void
309_mesa_unbind_array_object_vbos(struct gl_context *ctx,
310                               struct gl_vertex_array_object *obj)
311{
312   GLuint i;
313
314   for (i = 0; i < ARRAY_SIZE(obj->BufferBinding); i++)
315      _mesa_reference_buffer_object(ctx, &obj->BufferBinding[i].BufferObj, NULL);
316}
317
318
319/**
320 * Allocate and initialize a new vertex array object.
321 */
322struct gl_vertex_array_object *
323_mesa_new_vao(struct gl_context *ctx, GLuint name)
324{
325   struct gl_vertex_array_object *obj = MALLOC_STRUCT(gl_vertex_array_object);
326   if (obj)
327      _mesa_initialize_vao(ctx, obj, name);
328   return obj;
329}
330
331
332/**
333 * Delete an array object.
334 */
335void
336_mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj)
337{
338   _mesa_unbind_array_object_vbos(ctx, obj);
339   _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL);
340   free(obj->Label);
341   free(obj);
342}
343
344
345/**
346 * Set ptr to vao w/ reference counting.
347 * Note: this should only be called from the _mesa_reference_vao()
348 * inline function.
349 */
350void
351_mesa_reference_vao_(struct gl_context *ctx,
352                     struct gl_vertex_array_object **ptr,
353                     struct gl_vertex_array_object *vao)
354{
355   assert(*ptr != vao);
356
357   if (*ptr) {
358      /* Unreference the old array object */
359      struct gl_vertex_array_object *oldObj = *ptr;
360
361      bool deleteFlag;
362      if (oldObj->SharedAndImmutable) {
363         deleteFlag = p_atomic_dec_zero(&oldObj->RefCount);
364      } else {
365         assert(oldObj->RefCount > 0);
366         oldObj->RefCount--;
367         deleteFlag = (oldObj->RefCount == 0);
368      }
369
370      if (deleteFlag)
371         _mesa_delete_vao(ctx, oldObj);
372
373      *ptr = NULL;
374   }
375   assert(!*ptr);
376
377   if (vao) {
378      /* reference new array object */
379      if (vao->SharedAndImmutable) {
380         p_atomic_inc(&vao->RefCount);
381      } else {
382         assert(vao->RefCount > 0);
383         vao->RefCount++;
384      }
385
386      *ptr = vao;
387   }
388}
389
390
391/**
392 * Initialize a gl_vertex_array_object's arrays.
393 */
394void
395_mesa_initialize_vao(struct gl_context *ctx,
396                     struct gl_vertex_array_object *vao,
397                     GLuint name)
398{
399   memcpy(vao, &ctx->Array.DefaultVAOState, sizeof(*vao));
400   vao->Name = name;
401}
402
403
404/**
405 * Compute the offset range for the provided binding.
406 *
407 * This is a helper function for the below.
408 */
409static void
410compute_vbo_offset_range(const struct gl_vertex_array_object *vao,
411                         const struct gl_vertex_buffer_binding *binding,
412                         GLsizeiptr* min, GLsizeiptr* max)
413{
414   /* The function is meant to work on VBO bindings */
415   assert(binding->BufferObj);
416
417   /* Start with an inverted range of relative offsets. */
418   GLuint min_offset = ~(GLuint)0;
419   GLuint max_offset = 0;
420
421   /* We work on the unmapped originaly VAO array entries. */
422   GLbitfield mask = vao->Enabled & binding->_BoundArrays;
423   /* The binding should be active somehow, not to return inverted ranges */
424   assert(mask);
425   while (mask) {
426      const int i = u_bit_scan(&mask);
427      const GLuint off = vao->VertexAttrib[i].RelativeOffset;
428      min_offset = MIN2(off, min_offset);
429      max_offset = MAX2(off, max_offset);
430   }
431
432   *min = binding->Offset + (GLsizeiptr)min_offset;
433   *max = binding->Offset + (GLsizeiptr)max_offset;
434}
435
436
437/**
438 * Update the unique binding and pos/generic0 map tracking in the vao.
439 *
440 * The idea is to build up information in the vao so that a consuming
441 * backend can execute the following to set up buffer and vertex element
442 * information:
443 *
444 * const GLbitfield inputs_read = VERT_BIT_ALL; // backend vp inputs
445 *
446 * // Attribute data is in a VBO.
447 * GLbitfield vbomask = inputs_read & _mesa_draw_vbo_array_bits(ctx);
448 * while (vbomask) {
449 *    // The attribute index to start pulling a binding
450 *    const gl_vert_attrib i = ffs(vbomask) - 1;
451 *    const struct gl_vertex_buffer_binding *const binding
452 *       = _mesa_draw_buffer_binding(vao, i);
453 *
454 *    <insert code to handle the vertex buffer object at binding>
455 *
456 *    const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
457 *    GLbitfield attrmask = vbomask & boundmask;
458 *    assert(attrmask);
459 *    // Walk attributes belonging to the binding
460 *    while (attrmask) {
461 *       const gl_vert_attrib attr = u_bit_scan(&attrmask);
462 *       const struct gl_array_attributes *const attrib
463 *          = _mesa_draw_array_attrib(vao, attr);
464 *
465 *       <insert code to handle the vertex element refering to the binding>
466 *    }
467 *    vbomask &= ~boundmask;
468 * }
469 *
470 * // Process user space buffers
471 * GLbitfield usermask = inputs_read & _mesa_draw_user_array_bits(ctx);
472 * while (usermask) {
473 *    // The attribute index to start pulling a binding
474 *    const gl_vert_attrib i = ffs(usermask) - 1;
475 *    const struct gl_vertex_buffer_binding *const binding
476 *       = _mesa_draw_buffer_binding(vao, i);
477 *
478 *    <insert code to handle a set of interleaved user space arrays at binding>
479 *
480 *    const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
481 *    GLbitfield attrmask = usermask & boundmask;
482 *    assert(attrmask);
483 *    // Walk interleaved attributes with a common stride and instance divisor
484 *    while (attrmask) {
485 *       const gl_vert_attrib attr = u_bit_scan(&attrmask);
486 *       const struct gl_array_attributes *const attrib
487 *          = _mesa_draw_array_attrib(vao, attr);
488 *
489 *       <insert code to handle non vbo vertex arrays>
490 *    }
491 *    usermask &= ~boundmask;
492 * }
493 *
494 * // Process values that should have better been uniforms in the application
495 * GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
496 * while (curmask) {
497 *    const gl_vert_attrib attr = u_bit_scan(&curmask);
498 *    const struct gl_array_attributes *const attrib
499 *       = _mesa_draw_current_attrib(ctx, attr);
500 *
501 *    <insert code to handle current values>
502 * }
503 *
504 *
505 * Note that the scan below must not incoporate any context state.
506 * The rationale is that once a VAO is finalized it should not
507 * be touched anymore. That means, do not incorporate the
508 * gl_context::Array._DrawVAOEnabledAttribs bitmask into this scan.
509 * A backend driver may further reduce the handled vertex processing
510 * inputs based on their vertex shader inputs. But scanning for
511 * collapsable binding points to reduce relocs is done based on the
512 * enabled arrays.
513 * Also VAOs may be shared between contexts due to their use in dlists
514 * thus no context state should bleed into the VAO.
515 */
516void
517_mesa_update_vao_derived_arrays(struct gl_context *ctx,
518                                struct gl_vertex_array_object *vao)
519{
520   /* Make sure we do not run into problems with shared objects */
521   assert(!vao->SharedAndImmutable || vao->NewArrays == 0);
522
523   /* Limit used for common binding scanning below. */
524   const GLsizeiptr MaxRelativeOffset =
525      ctx->Const.MaxVertexAttribRelativeOffset;
526
527   /* The gl_vertex_array_object::_AttributeMapMode denotes the way
528    * VERT_ATTRIB_{POS,GENERIC0} mapping is done.
529    *
530    * This mapping is used to map between the OpenGL api visible
531    * VERT_ATTRIB_* arrays to mesa driver arrayinputs or shader inputs.
532    * The mapping only depends on the enabled bits of the
533    * VERT_ATTRIB_{POS,GENERIC0} arrays and is tracked in the VAO.
534    *
535    * This map needs to be applied when finally translating to the bitmasks
536    * as consumed by the driver backends. The duplicate scanning is here
537    * can as well be done in the OpenGL API numbering without this map.
538    */
539   const gl_attribute_map_mode mode = vao->_AttributeMapMode;
540   /* Enabled array bits. */
541   const GLbitfield enabled = vao->Enabled;
542   /* VBO array bits. */
543   const GLbitfield vbos = vao->VertexAttribBufferMask;
544   const GLbitfield divisor_is_nonzero = vao->NonZeroDivisorMask;
545
546   /* Compute and store effectively enabled and mapped vbo arrays */
547   vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos);
548   vao->_EffEnabledNonZeroDivisor =
549      _mesa_vao_enable_to_vp_inputs(mode, enabled & divisor_is_nonzero);
550
551   /* Fast path when the VAO is updated too often. */
552   if (vao->IsDynamic)
553      return;
554
555   /* More than 4 updates turn the VAO to dynamic. */
556   if (ctx->Const.AllowDynamicVAOFastPath && ++vao->NumUpdates > 4) {
557      vao->IsDynamic = true;
558      return;
559   }
560
561   /* Walk those enabled arrays that have a real vbo attached */
562   GLbitfield mask = enabled;
563   while (mask) {
564      /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
565      const int i = ffs(mask) - 1;
566      /* The binding from the first to be processed attribute. */
567      const GLuint bindex = vao->VertexAttrib[i].BufferBindingIndex;
568      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
569
570      /* The scan goes different for user space arrays than vbos */
571      if (binding->BufferObj) {
572         /* The bound arrays. */
573         const GLbitfield bound = enabled & binding->_BoundArrays;
574
575         /* Start this current effective binding with the actual bound arrays */
576         GLbitfield eff_bound_arrays = bound;
577
578         /*
579          * If there is nothing left to scan just update the effective binding
580          * information. If the VAO is already only using a single binding point
581          * we end up here. So the overhead of this scan for an application
582          * carefully preparing the VAO for draw is low.
583          */
584
585         GLbitfield scanmask = mask & vbos & ~bound;
586         /* Is there something left to scan? */
587         if (scanmask == 0) {
588            /* Just update the back reference from the attrib to the binding and
589             * the effective offset.
590             */
591            GLbitfield attrmask = eff_bound_arrays;
592            while (attrmask) {
593               const int j = u_bit_scan(&attrmask);
594               struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
595
596               /* Update the index into the common binding point and offset */
597               attrib2->_EffBufferBindingIndex = bindex;
598               attrib2->_EffRelativeOffset = attrib2->RelativeOffset;
599               assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
600            }
601            /* Finally this is the set of effectively bound arrays with the
602             * original binding offset.
603             */
604            binding->_EffOffset = binding->Offset;
605            /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
606            binding->_EffBoundArrays =
607               _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
608
609         } else {
610            /* In the VBO case, scan for attribute/binding
611             * combinations with relative bindings in the range of
612             * [0, ctx->Const.MaxVertexAttribRelativeOffset].
613             * Note that this does also go beyond just interleaved arrays
614             * as long as they use the same VBO, binding parameters and the
615             * offsets stay within bounds that the backend still can handle.
616             */
617
618            GLsizeiptr min_offset, max_offset;
619            compute_vbo_offset_range(vao, binding, &min_offset, &max_offset);
620            assert(max_offset <= min_offset + MaxRelativeOffset);
621
622            /* Now scan. */
623            while (scanmask) {
624               /* Do not use u_bit_scan as we can walk multiple
625                * attrib arrays at once
626                */
627               const int j = ffs(scanmask) - 1;
628               const struct gl_array_attributes *attrib2 =
629                  &vao->VertexAttrib[j];
630               const struct gl_vertex_buffer_binding *binding2 =
631                  &vao->BufferBinding[attrib2->BufferBindingIndex];
632
633               /* Remove those attrib bits from the mask that are bound to the
634                * same effective binding point.
635                */
636               const GLbitfield bound2 = enabled & binding2->_BoundArrays;
637               scanmask &= ~bound2;
638
639               /* Check if we have an identical binding */
640               if (binding->Stride != binding2->Stride)
641                  continue;
642               if (binding->InstanceDivisor != binding2->InstanceDivisor)
643                  continue;
644               if (binding->BufferObj != binding2->BufferObj)
645                  continue;
646               /* Check if we can fold both bindings into a common binding */
647               GLsizeiptr min_offset2, max_offset2;
648               compute_vbo_offset_range(vao, binding2,
649                                        &min_offset2, &max_offset2);
650               /* If the relative offset is within the limits ... */
651               if (min_offset + MaxRelativeOffset < max_offset2)
652                  continue;
653               if (min_offset2 + MaxRelativeOffset < max_offset)
654                  continue;
655               /* ... add this array to the effective binding */
656               eff_bound_arrays |= bound2;
657               min_offset = MIN2(min_offset, min_offset2);
658               max_offset = MAX2(max_offset, max_offset2);
659               assert(max_offset <= min_offset + MaxRelativeOffset);
660            }
661
662            /* Update the back reference from the attrib to the binding */
663            GLbitfield attrmask = eff_bound_arrays;
664            while (attrmask) {
665               const int j = u_bit_scan(&attrmask);
666               struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
667               const struct gl_vertex_buffer_binding *binding2 =
668                  &vao->BufferBinding[attrib2->BufferBindingIndex];
669
670               /* Update the index into the common binding point and offset */
671               attrib2->_EffBufferBindingIndex = bindex;
672               attrib2->_EffRelativeOffset =
673                  binding2->Offset + attrib2->RelativeOffset - min_offset;
674               assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
675            }
676            /* Finally this is the set of effectively bound arrays */
677            binding->_EffOffset = min_offset;
678            /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
679            binding->_EffBoundArrays =
680               _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
681         }
682
683         /* Mark all the effective bound arrays as processed. */
684         mask &= ~eff_bound_arrays;
685
686      } else {
687         /* Scanning of common bindings for user space arrays.
688          */
689
690         const struct gl_array_attributes *attrib = &vao->VertexAttrib[i];
691         const GLbitfield bound = VERT_BIT(i);
692
693         /* Note that user space array pointers can only happen using a one
694          * to one binding point to array mapping.
695          * The OpenGL 4.x/ARB_vertex_attrib_binding api does not support
696          * user space arrays collected at multiple binding points.
697          * The only provider of user space interleaved arrays with a single
698          * binding point is the mesa internal vbo module. But that one
699          * provides a perfect interleaved set of arrays.
700          *
701          * If this would not be true we would potentially get attribute arrays
702          * with user space pointers that may not lie within the
703          * MaxRelativeOffset range but still attached to a single binding.
704          * Then we would need to store the effective attribute and binding
705          * grouping information in a seperate array beside
706          * gl_array_attributes/gl_vertex_buffer_binding.
707          */
708         assert(util_bitcount(binding->_BoundArrays & vao->Enabled) == 1
709                || (vao->Enabled & ~binding->_BoundArrays) == 0);
710
711         /* Start this current effective binding with the array */
712         GLbitfield eff_bound_arrays = bound;
713
714         const GLubyte *ptr = attrib->Ptr;
715         unsigned vertex_end = attrib->Format._ElementSize;
716
717         /* Walk other user space arrays and see which are interleaved
718          * using the same binding parameters.
719          */
720         GLbitfield scanmask = mask & ~vbos & ~bound;
721         while (scanmask) {
722            const int j = u_bit_scan(&scanmask);
723            const struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
724            const struct gl_vertex_buffer_binding *binding2 =
725               &vao->BufferBinding[attrib2->BufferBindingIndex];
726
727            /* See the comment at the same assert above. */
728            assert(util_bitcount(binding2->_BoundArrays & vao->Enabled) == 1
729                   || (vao->Enabled & ~binding->_BoundArrays) == 0);
730
731            /* Check if we have an identical binding */
732            if (binding->Stride != binding2->Stride)
733               continue;
734            if (binding->InstanceDivisor != binding2->InstanceDivisor)
735               continue;
736            if (ptr <= attrib2->Ptr) {
737               if (ptr + binding->Stride < attrib2->Ptr +
738                   attrib2->Format._ElementSize)
739                  continue;
740               unsigned end = attrib2->Ptr + attrib2->Format._ElementSize - ptr;
741               vertex_end = MAX2(vertex_end, end);
742            } else {
743               if (attrib2->Ptr + binding->Stride < ptr + vertex_end)
744                  continue;
745               vertex_end += (GLsizei)(ptr - attrib2->Ptr);
746               ptr = attrib2->Ptr;
747            }
748
749            /* User space buffer object */
750            assert(!binding2->BufferObj);
751
752            eff_bound_arrays |= VERT_BIT(j);
753         }
754
755         /* Update the back reference from the attrib to the binding */
756         GLbitfield attrmask = eff_bound_arrays;
757         while (attrmask) {
758            const int j = u_bit_scan(&attrmask);
759            struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
760
761            /* Update the index into the common binding point and the offset */
762            attrib2->_EffBufferBindingIndex = bindex;
763            attrib2->_EffRelativeOffset = attrib2->Ptr - ptr;
764            assert(attrib2->_EffRelativeOffset <= binding->Stride);
765         }
766         /* Finally this is the set of effectively bound arrays */
767         binding->_EffOffset = (GLintptr)ptr;
768         /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
769         binding->_EffBoundArrays =
770            _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
771
772         /* Mark all the effective bound arrays as processed. */
773         mask &= ~eff_bound_arrays;
774      }
775   }
776
777#ifndef NDEBUG
778   /* Make sure the above code works as expected. */
779   for (gl_vert_attrib attr = 0; attr < VERT_ATTRIB_MAX; ++attr) {
780      /* Query the original api defined attrib/binding information ... */
781      const unsigned char *const map =_mesa_vao_attribute_map[mode];
782      if (vao->Enabled & VERT_BIT(map[attr])) {
783         const struct gl_array_attributes *attrib =
784            &vao->VertexAttrib[map[attr]];
785         const struct gl_vertex_buffer_binding *binding =
786            &vao->BufferBinding[attrib->BufferBindingIndex];
787         /* ... and compare that with the computed attrib/binding */
788         const struct gl_vertex_buffer_binding *binding2 =
789            &vao->BufferBinding[attrib->_EffBufferBindingIndex];
790         assert(binding->Stride == binding2->Stride);
791         assert(binding->InstanceDivisor == binding2->InstanceDivisor);
792         assert(binding->BufferObj == binding2->BufferObj);
793         if (binding->BufferObj) {
794            assert(attrib->_EffRelativeOffset <= MaxRelativeOffset);
795            assert(binding->Offset + attrib->RelativeOffset ==
796                   binding2->_EffOffset + attrib->_EffRelativeOffset);
797         } else {
798            assert(attrib->_EffRelativeOffset < binding->Stride);
799            assert((GLintptr)attrib->Ptr ==
800                   binding2->_EffOffset + attrib->_EffRelativeOffset);
801         }
802      }
803   }
804#endif
805}
806
807
808void
809_mesa_set_vao_immutable(struct gl_context *ctx,
810                        struct gl_vertex_array_object *vao)
811{
812   _mesa_update_vao_derived_arrays(ctx, vao);
813   vao->NewArrays = 0;
814   vao->SharedAndImmutable = true;
815}
816
817
818bool
819_mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao)
820{
821   /* Walk those enabled arrays that have the default vbo attached */
822   GLbitfield mask = vao->Enabled & ~vao->VertexAttribBufferMask;
823
824   while (mask) {
825      /* Do not use u_bit_scan64 as we can walk multiple
826       * attrib arrays at once
827       */
828      const int i = ffs(mask) - 1;
829      const struct gl_array_attributes *attrib_array =
830         &vao->VertexAttrib[i];
831      const struct gl_vertex_buffer_binding *buffer_binding =
832         &vao->BufferBinding[attrib_array->BufferBindingIndex];
833
834      /* We have already masked out vao->VertexAttribBufferMask  */
835      assert(!buffer_binding->BufferObj);
836
837      /* Bail out once we find the first non vbo with a non zero stride */
838      if (buffer_binding->Stride != 0)
839         return false;
840
841      /* Note that we cannot use the xor variant since the _BoundArray mask
842       * may contain array attributes that are bound but not enabled.
843       */
844      mask &= ~buffer_binding->_BoundArrays;
845   }
846
847   return true;
848}
849
850bool
851_mesa_all_buffers_are_unmapped(const struct gl_vertex_array_object *vao)
852{
853   /* Walk the enabled arrays that have a vbo attached */
854   GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
855
856   while (mask) {
857      const int i = ffs(mask) - 1;
858      const struct gl_array_attributes *attrib_array =
859         &vao->VertexAttrib[i];
860      const struct gl_vertex_buffer_binding *buffer_binding =
861         &vao->BufferBinding[attrib_array->BufferBindingIndex];
862
863      /* We have already masked with vao->VertexAttribBufferMask  */
864      assert(buffer_binding->BufferObj);
865
866      /* Bail out once we find the first disallowed mapping */
867      if (_mesa_check_disallowed_mapping(buffer_binding->BufferObj))
868         return false;
869
870      /* We have handled everything that is bound to this buffer_binding. */
871      mask &= ~buffer_binding->_BoundArrays;
872   }
873
874   return true;
875}
876
877
878/**
879 * Map buffer objects used in attribute arrays.
880 */
881void
882_mesa_vao_map_arrays(struct gl_context *ctx, struct gl_vertex_array_object *vao,
883                     GLbitfield access)
884{
885   GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
886   while (mask) {
887      /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
888      const gl_vert_attrib attr = ffs(mask) - 1;
889      const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
890      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
891      mask &= ~binding->_BoundArrays;
892
893      struct gl_buffer_object *bo = binding->BufferObj;
894      assert(bo);
895      if (_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
896         continue;
897
898      ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
899   }
900}
901
902
903/**
904 * Map buffer objects used in the vao, attribute arrays and index buffer.
905 */
906void
907_mesa_vao_map(struct gl_context *ctx, struct gl_vertex_array_object *vao,
908              GLbitfield access)
909{
910   struct gl_buffer_object *bo = vao->IndexBufferObj;
911
912   /* map the index buffer, if there is one, and not already mapped */
913   if (bo && !_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
914      ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
915
916   _mesa_vao_map_arrays(ctx, vao, access);
917}
918
919
920/**
921 * Unmap buffer objects used in attribute arrays.
922 */
923void
924_mesa_vao_unmap_arrays(struct gl_context *ctx,
925                       struct gl_vertex_array_object *vao)
926{
927   GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
928   while (mask) {
929      /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
930      const gl_vert_attrib attr = ffs(mask) - 1;
931      const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
932      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
933      mask &= ~binding->_BoundArrays;
934
935      struct gl_buffer_object *bo = binding->BufferObj;
936      assert(bo);
937      if (!_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
938         continue;
939
940      ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
941   }
942}
943
944
945/**
946 * Unmap buffer objects used in the vao, attribute arrays and index buffer.
947 */
948void
949_mesa_vao_unmap(struct gl_context *ctx, struct gl_vertex_array_object *vao)
950{
951   struct gl_buffer_object *bo = vao->IndexBufferObj;
952
953   /* unmap the index buffer, if there is one, and still mapped */
954   if (bo && _mesa_bufferobj_mapped(bo, MAP_INTERNAL))
955      ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
956
957   _mesa_vao_unmap_arrays(ctx, vao);
958}
959
960
961/**********************************************************************/
962/* API Functions                                                      */
963/**********************************************************************/
964
965
966/**
967 * ARB version of glBindVertexArray()
968 */
969static ALWAYS_INLINE void
970bind_vertex_array(struct gl_context *ctx, GLuint id, bool no_error)
971{
972   struct gl_vertex_array_object *const oldObj = ctx->Array.VAO;
973   struct gl_vertex_array_object *newObj = NULL;
974
975   assert(oldObj != NULL);
976
977   if (oldObj->Name == id)
978      return;   /* rebinding the same array object- no change */
979
980   /*
981    * Get pointer to new array object (newObj)
982    */
983   if (id == 0) {
984      /* The spec says there is no array object named 0, but we use
985       * one internally because it simplifies things.
986       */
987      newObj = ctx->Array.DefaultVAO;
988   }
989   else {
990      /* non-default array object */
991      newObj = _mesa_lookup_vao(ctx, id);
992      if (!no_error && !newObj) {
993         _mesa_error(ctx, GL_INVALID_OPERATION,
994                     "glBindVertexArray(non-gen name)");
995         return;
996      }
997
998      newObj->EverBound = GL_TRUE;
999   }
1000
1001   /* The _DrawArrays pointer is pointing at the VAO being unbound and
1002    * that VAO may be in the process of being deleted. If it's not going
1003    * to be deleted, this will have no effect, because the pointer needs
1004    * to be updated by the VBO module anyway.
1005    *
1006    * Before the VBO module can update the pointer, we have to set it
1007    * to NULL for drivers not to set up arrays which are not bound,
1008    * or to prevent a crash if the VAO being unbound is going to be
1009    * deleted.
1010    */
1011   _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
1012
1013   _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj);
1014
1015   /* Update the valid-to-render state if binding on unbinding default VAO
1016    * if drawing with the default VAO is invalid.
1017    */
1018   if (ctx->API == API_OPENGL_CORE &&
1019       (oldObj == ctx->Array.DefaultVAO) != (newObj == ctx->Array.DefaultVAO))
1020      _mesa_update_valid_to_render_state(ctx);
1021}
1022
1023
1024void GLAPIENTRY
1025_mesa_BindVertexArray_no_error(GLuint id)
1026{
1027   GET_CURRENT_CONTEXT(ctx);
1028   bind_vertex_array(ctx, id, true);
1029}
1030
1031
1032void GLAPIENTRY
1033_mesa_BindVertexArray(GLuint id)
1034{
1035   GET_CURRENT_CONTEXT(ctx);
1036   bind_vertex_array(ctx, id, false);
1037}
1038
1039
1040/**
1041 * Delete a set of array objects.
1042 *
1043 * \param n      Number of array objects to delete.
1044 * \param ids    Array of \c n array object IDs.
1045 */
1046static void
1047delete_vertex_arrays(struct gl_context *ctx, GLsizei n, const GLuint *ids)
1048{
1049   GLsizei i;
1050
1051   for (i = 0; i < n; i++) {
1052      /* IDs equal to 0 should be silently ignored. */
1053      if (!ids[i])
1054         continue;
1055
1056      struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]);
1057
1058      if (obj) {
1059         assert(obj->Name == ids[i]);
1060
1061         /* If the array object is currently bound, the spec says "the binding
1062          * for that object reverts to zero and the default vertex array
1063          * becomes current."
1064          */
1065         if (obj == ctx->Array.VAO)
1066            _mesa_BindVertexArray_no_error(0);
1067
1068         /* The ID is immediately freed for re-use */
1069         _mesa_HashRemoveLocked(ctx->Array.Objects, obj->Name);
1070
1071         if (ctx->Array.LastLookedUpVAO == obj)
1072            _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL);
1073         if (ctx->Array._DrawVAO == obj)
1074            _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
1075
1076         /* Unreference the array object.
1077          * If refcount hits zero, the object will be deleted.
1078          */
1079         _mesa_reference_vao(ctx, &obj, NULL);
1080      }
1081   }
1082}
1083
1084
1085void GLAPIENTRY
1086_mesa_DeleteVertexArrays_no_error(GLsizei n, const GLuint *ids)
1087{
1088   GET_CURRENT_CONTEXT(ctx);
1089   delete_vertex_arrays(ctx, n, ids);
1090}
1091
1092
1093void GLAPIENTRY
1094_mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
1095{
1096   GET_CURRENT_CONTEXT(ctx);
1097
1098   if (n < 0) {
1099      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)");
1100      return;
1101   }
1102
1103   delete_vertex_arrays(ctx, n, ids);
1104}
1105
1106
1107/**
1108 * Generate a set of unique array object IDs and store them in \c arrays.
1109 * Helper for _mesa_GenVertexArrays() and _mesa_CreateVertexArrays()
1110 * below.
1111 *
1112 * \param n       Number of IDs to generate.
1113 * \param arrays  Array of \c n locations to store the IDs.
1114 * \param create  Indicates that the objects should also be created.
1115 * \param func    The name of the GL entry point.
1116 */
1117static void
1118gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
1119                  bool create, const char *func)
1120{
1121   GLint i;
1122
1123   if (!arrays)
1124      return;
1125
1126   _mesa_HashFindFreeKeys(ctx->Array.Objects, arrays, n);
1127
1128   /* For the sake of simplicity we create the array objects in both
1129    * the Gen* and Create* cases.  The only difference is the value of
1130    * EverBound, which is set to true in the Create* case.
1131    */
1132   for (i = 0; i < n; i++) {
1133      struct gl_vertex_array_object *obj;
1134
1135      obj = _mesa_new_vao(ctx, arrays[i]);
1136      if (!obj) {
1137         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1138         return;
1139      }
1140      obj->EverBound = create;
1141      _mesa_HashInsertLocked(ctx->Array.Objects, obj->Name, obj, true);
1142   }
1143}
1144
1145
1146static void
1147gen_vertex_arrays_err(struct gl_context *ctx, GLsizei n, GLuint *arrays,
1148                      bool create, const char *func)
1149{
1150   if (n < 0) {
1151      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
1152      return;
1153   }
1154
1155   gen_vertex_arrays(ctx, n, arrays, create, func);
1156}
1157
1158
1159/**
1160 * ARB version of glGenVertexArrays()
1161 * All arrays will be required to live in VBOs.
1162 */
1163void GLAPIENTRY
1164_mesa_GenVertexArrays_no_error(GLsizei n, GLuint *arrays)
1165{
1166   GET_CURRENT_CONTEXT(ctx);
1167   gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays");
1168}
1169
1170
1171void GLAPIENTRY
1172_mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
1173{
1174   GET_CURRENT_CONTEXT(ctx);
1175   gen_vertex_arrays_err(ctx, n, arrays, false, "glGenVertexArrays");
1176}
1177
1178
1179/**
1180 * ARB_direct_state_access
1181 * Generates ID's and creates the array objects.
1182 */
1183void GLAPIENTRY
1184_mesa_CreateVertexArrays_no_error(GLsizei n, GLuint *arrays)
1185{
1186   GET_CURRENT_CONTEXT(ctx);
1187   gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays");
1188}
1189
1190
1191void GLAPIENTRY
1192_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays)
1193{
1194   GET_CURRENT_CONTEXT(ctx);
1195   gen_vertex_arrays_err(ctx, n, arrays, true, "glCreateVertexArrays");
1196}
1197
1198
1199/**
1200 * Determine if ID is the name of an array object.
1201 *
1202 * \param id  ID of the potential array object.
1203 * \return  \c GL_TRUE if \c id is the name of a array object,
1204 *          \c GL_FALSE otherwise.
1205 */
1206GLboolean GLAPIENTRY
1207_mesa_IsVertexArray( GLuint id )
1208{
1209   struct gl_vertex_array_object * obj;
1210   GET_CURRENT_CONTEXT(ctx);
1211   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1212
1213   obj = _mesa_lookup_vao(ctx, id);
1214
1215   return obj != NULL && obj->EverBound;
1216}
1217
1218
1219/**
1220 * Sets the element array buffer binding of a vertex array object.
1221 *
1222 * This is the ARB_direct_state_access equivalent of
1223 * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer).
1224 */
1225static ALWAYS_INLINE void
1226vertex_array_element_buffer(struct gl_context *ctx, GLuint vaobj, GLuint buffer,
1227                            bool no_error)
1228{
1229   struct gl_vertex_array_object *vao;
1230   struct gl_buffer_object *bufObj;
1231
1232   ASSERT_OUTSIDE_BEGIN_END(ctx);
1233
1234   if (!no_error) {
1235      /* The GL_ARB_direct_state_access specification says:
1236       *
1237       *    "An INVALID_OPERATION error is generated by
1238       *     VertexArrayElementBuffer if <vaobj> is not [compatibility profile:
1239       *     zero or] the name of an existing vertex array object."
1240       */
1241      vao =_mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayElementBuffer");
1242      if (!vao)
1243         return;
1244   } else {
1245      vao = _mesa_lookup_vao(ctx, vaobj);
1246   }
1247
1248   if (buffer != 0) {
1249      if (!no_error) {
1250         /* The GL_ARB_direct_state_access specification says:
1251          *
1252          *    "An INVALID_OPERATION error is generated if <buffer> is not zero
1253          *     or the name of an existing buffer object."
1254          */
1255         bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
1256                                             "glVertexArrayElementBuffer");
1257      } else {
1258         bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1259      }
1260
1261      if (!bufObj)
1262         return;
1263
1264      bufObj->UsageHistory |= USAGE_ELEMENT_ARRAY_BUFFER;
1265   } else {
1266      bufObj = NULL;
1267   }
1268
1269   _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
1270}
1271
1272
1273void GLAPIENTRY
1274_mesa_VertexArrayElementBuffer_no_error(GLuint vaobj, GLuint buffer)
1275{
1276   GET_CURRENT_CONTEXT(ctx);
1277   vertex_array_element_buffer(ctx, vaobj, buffer, true);
1278}
1279
1280
1281void GLAPIENTRY
1282_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer)
1283{
1284   GET_CURRENT_CONTEXT(ctx);
1285   vertex_array_element_buffer(ctx, vaobj, buffer, false);
1286}
1287
1288
1289void GLAPIENTRY
1290_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param)
1291{
1292   GET_CURRENT_CONTEXT(ctx);
1293   struct gl_vertex_array_object *vao;
1294
1295   ASSERT_OUTSIDE_BEGIN_END(ctx);
1296
1297   /* The GL_ARB_direct_state_access specification says:
1298    *
1299    *   "An INVALID_OPERATION error is generated if <vaobj> is not
1300    *    [compatibility profile: zero or] the name of an existing
1301    *    vertex array object."
1302    */
1303   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayiv");
1304   if (!vao)
1305      return;
1306
1307   /* The GL_ARB_direct_state_access specification says:
1308    *
1309    *   "An INVALID_ENUM error is generated if <pname> is not
1310    *    ELEMENT_ARRAY_BUFFER_BINDING."
1311    */
1312   if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
1313      _mesa_error(ctx, GL_INVALID_ENUM,
1314                  "glGetVertexArrayiv(pname != "
1315                  "GL_ELEMENT_ARRAY_BUFFER_BINDING)");
1316      return;
1317   }
1318
1319   param[0] = vao->IndexBufferObj ? vao->IndexBufferObj->Name : 0;
1320}
1321