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