xref: /third_party/mesa3d/src/mesa/main/arrayobj.c (revision bf215546)
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#include "api_exec_decl.h"
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->NewVertexBuffers && !vao->NewVertexElements));
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      /* IsDynamic changes how vertex elements map to vertex buffers. */
559      vao->NewVertexElements = true;
560      return;
561   }
562
563   /* Walk those enabled arrays that have a real vbo attached */
564   GLbitfield mask = enabled;
565   while (mask) {
566      /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
567      const int i = ffs(mask) - 1;
568      /* The binding from the first to be processed attribute. */
569      const GLuint bindex = vao->VertexAttrib[i].BufferBindingIndex;
570      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
571
572      /* The scan goes different for user space arrays than vbos */
573      if (binding->BufferObj) {
574         /* The bound arrays. */
575         const GLbitfield bound = enabled & binding->_BoundArrays;
576
577         /* Start this current effective binding with the actual bound arrays */
578         GLbitfield eff_bound_arrays = bound;
579
580         /*
581          * If there is nothing left to scan just update the effective binding
582          * information. If the VAO is already only using a single binding point
583          * we end up here. So the overhead of this scan for an application
584          * carefully preparing the VAO for draw is low.
585          */
586
587         GLbitfield scanmask = mask & vbos & ~bound;
588         /* Is there something left to scan? */
589         if (scanmask == 0) {
590            /* Just update the back reference from the attrib to the binding and
591             * the effective offset.
592             */
593            GLbitfield attrmask = eff_bound_arrays;
594            while (attrmask) {
595               const int j = u_bit_scan(&attrmask);
596               struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
597
598               /* Update the index into the common binding point and offset */
599               attrib2->_EffBufferBindingIndex = bindex;
600               attrib2->_EffRelativeOffset = attrib2->RelativeOffset;
601               assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
602            }
603            /* Finally this is the set of effectively bound arrays with the
604             * original binding offset.
605             */
606            binding->_EffOffset = binding->Offset;
607            /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
608            binding->_EffBoundArrays =
609               _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
610
611         } else {
612            /* In the VBO case, scan for attribute/binding
613             * combinations with relative bindings in the range of
614             * [0, ctx->Const.MaxVertexAttribRelativeOffset].
615             * Note that this does also go beyond just interleaved arrays
616             * as long as they use the same VBO, binding parameters and the
617             * offsets stay within bounds that the backend still can handle.
618             */
619
620            GLsizeiptr min_offset, max_offset;
621            compute_vbo_offset_range(vao, binding, &min_offset, &max_offset);
622            assert(max_offset <= min_offset + MaxRelativeOffset);
623
624            /* Now scan. */
625            while (scanmask) {
626               /* Do not use u_bit_scan as we can walk multiple
627                * attrib arrays at once
628                */
629               const int j = ffs(scanmask) - 1;
630               const struct gl_array_attributes *attrib2 =
631                  &vao->VertexAttrib[j];
632               const struct gl_vertex_buffer_binding *binding2 =
633                  &vao->BufferBinding[attrib2->BufferBindingIndex];
634
635               /* Remove those attrib bits from the mask that are bound to the
636                * same effective binding point.
637                */
638               const GLbitfield bound2 = enabled & binding2->_BoundArrays;
639               scanmask &= ~bound2;
640
641               /* Check if we have an identical binding */
642               if (binding->Stride != binding2->Stride)
643                  continue;
644               if (binding->InstanceDivisor != binding2->InstanceDivisor)
645                  continue;
646               if (binding->BufferObj != binding2->BufferObj)
647                  continue;
648               /* Check if we can fold both bindings into a common binding */
649               GLsizeiptr min_offset2, max_offset2;
650               compute_vbo_offset_range(vao, binding2,
651                                        &min_offset2, &max_offset2);
652               /* If the relative offset is within the limits ... */
653               if (min_offset + MaxRelativeOffset < max_offset2)
654                  continue;
655               if (min_offset2 + MaxRelativeOffset < max_offset)
656                  continue;
657               /* ... add this array to the effective binding */
658               eff_bound_arrays |= bound2;
659               min_offset = MIN2(min_offset, min_offset2);
660               max_offset = MAX2(max_offset, max_offset2);
661               assert(max_offset <= min_offset + MaxRelativeOffset);
662            }
663
664            /* Update the back reference from the attrib to the binding */
665            GLbitfield attrmask = eff_bound_arrays;
666            while (attrmask) {
667               const int j = u_bit_scan(&attrmask);
668               struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
669               const struct gl_vertex_buffer_binding *binding2 =
670                  &vao->BufferBinding[attrib2->BufferBindingIndex];
671
672               /* Update the index into the common binding point and offset */
673               attrib2->_EffBufferBindingIndex = bindex;
674               attrib2->_EffRelativeOffset =
675                  binding2->Offset + attrib2->RelativeOffset - min_offset;
676               assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
677            }
678            /* Finally this is the set of effectively bound arrays */
679            binding->_EffOffset = min_offset;
680            /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
681            binding->_EffBoundArrays =
682               _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
683         }
684
685         /* Mark all the effective bound arrays as processed. */
686         mask &= ~eff_bound_arrays;
687
688      } else {
689         /* Scanning of common bindings for user space arrays.
690          */
691
692         const struct gl_array_attributes *attrib = &vao->VertexAttrib[i];
693         const GLbitfield bound = VERT_BIT(i);
694
695         /* Note that user space array pointers can only happen using a one
696          * to one binding point to array mapping.
697          * The OpenGL 4.x/ARB_vertex_attrib_binding api does not support
698          * user space arrays collected at multiple binding points.
699          * The only provider of user space interleaved arrays with a single
700          * binding point is the mesa internal vbo module. But that one
701          * provides a perfect interleaved set of arrays.
702          *
703          * If this would not be true we would potentially get attribute arrays
704          * with user space pointers that may not lie within the
705          * MaxRelativeOffset range but still attached to a single binding.
706          * Then we would need to store the effective attribute and binding
707          * grouping information in a seperate array beside
708          * gl_array_attributes/gl_vertex_buffer_binding.
709          */
710         assert(util_bitcount(binding->_BoundArrays & vao->Enabled) == 1
711                || (vao->Enabled & ~binding->_BoundArrays) == 0);
712
713         /* Start this current effective binding with the array */
714         GLbitfield eff_bound_arrays = bound;
715
716         const GLubyte *ptr = attrib->Ptr;
717         unsigned vertex_end = attrib->Format._ElementSize;
718
719         /* Walk other user space arrays and see which are interleaved
720          * using the same binding parameters.
721          */
722         GLbitfield scanmask = mask & ~vbos & ~bound;
723         while (scanmask) {
724            const int j = u_bit_scan(&scanmask);
725            const struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
726            const struct gl_vertex_buffer_binding *binding2 =
727               &vao->BufferBinding[attrib2->BufferBindingIndex];
728
729            /* See the comment at the same assert above. */
730            assert(util_bitcount(binding2->_BoundArrays & vao->Enabled) == 1
731                   || (vao->Enabled & ~binding->_BoundArrays) == 0);
732
733            /* Check if we have an identical binding */
734            if (binding->Stride != binding2->Stride)
735               continue;
736            if (binding->InstanceDivisor != binding2->InstanceDivisor)
737               continue;
738            if (ptr <= attrib2->Ptr) {
739               if (ptr + binding->Stride < attrib2->Ptr +
740                   attrib2->Format._ElementSize)
741                  continue;
742               unsigned end = attrib2->Ptr + attrib2->Format._ElementSize - ptr;
743               vertex_end = MAX2(vertex_end, end);
744            } else {
745               if (attrib2->Ptr + binding->Stride < ptr + vertex_end)
746                  continue;
747               vertex_end += (GLsizei)(ptr - attrib2->Ptr);
748               ptr = attrib2->Ptr;
749            }
750
751            /* User space buffer object */
752            assert(!binding2->BufferObj);
753
754            eff_bound_arrays |= VERT_BIT(j);
755         }
756
757         /* Update the back reference from the attrib to the binding */
758         GLbitfield attrmask = eff_bound_arrays;
759         while (attrmask) {
760            const int j = u_bit_scan(&attrmask);
761            struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
762
763            /* Update the index into the common binding point and the offset */
764            attrib2->_EffBufferBindingIndex = bindex;
765            attrib2->_EffRelativeOffset = attrib2->Ptr - ptr;
766            assert(attrib2->_EffRelativeOffset <= binding->Stride);
767         }
768         /* Finally this is the set of effectively bound arrays */
769         binding->_EffOffset = (GLintptr)ptr;
770         /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
771         binding->_EffBoundArrays =
772            _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
773
774         /* Mark all the effective bound arrays as processed. */
775         mask &= ~eff_bound_arrays;
776      }
777   }
778
779#ifndef NDEBUG
780   /* Make sure the above code works as expected. */
781   for (gl_vert_attrib attr = 0; attr < VERT_ATTRIB_MAX; ++attr) {
782      /* Query the original api defined attrib/binding information ... */
783      const unsigned char *const map =_mesa_vao_attribute_map[mode];
784      if (vao->Enabled & VERT_BIT(map[attr])) {
785         const struct gl_array_attributes *attrib =
786            &vao->VertexAttrib[map[attr]];
787         const struct gl_vertex_buffer_binding *binding =
788            &vao->BufferBinding[attrib->BufferBindingIndex];
789         /* ... and compare that with the computed attrib/binding */
790         const struct gl_vertex_buffer_binding *binding2 =
791            &vao->BufferBinding[attrib->_EffBufferBindingIndex];
792         assert(binding->Stride == binding2->Stride);
793         assert(binding->InstanceDivisor == binding2->InstanceDivisor);
794         assert(binding->BufferObj == binding2->BufferObj);
795         if (binding->BufferObj) {
796            assert(attrib->_EffRelativeOffset <= MaxRelativeOffset);
797            assert(binding->Offset + attrib->RelativeOffset ==
798                   binding2->_EffOffset + attrib->_EffRelativeOffset);
799         } else {
800            assert(attrib->_EffRelativeOffset < binding->Stride);
801            assert((GLintptr)attrib->Ptr ==
802                   binding2->_EffOffset + attrib->_EffRelativeOffset);
803         }
804      }
805   }
806#endif
807}
808
809
810void
811_mesa_set_vao_immutable(struct gl_context *ctx,
812                        struct gl_vertex_array_object *vao)
813{
814   _mesa_update_vao_derived_arrays(ctx, vao);
815   vao->NewVertexBuffers = false;
816   vao->NewVertexElements = false;
817   vao->SharedAndImmutable = true;
818}
819
820
821/**
822 * Map buffer objects used in attribute arrays.
823 */
824void
825_mesa_vao_map_arrays(struct gl_context *ctx, struct gl_vertex_array_object *vao,
826                     GLbitfield access)
827{
828   GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
829   while (mask) {
830      /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
831      const gl_vert_attrib attr = ffs(mask) - 1;
832      const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
833      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
834      mask &= ~binding->_BoundArrays;
835
836      struct gl_buffer_object *bo = binding->BufferObj;
837      assert(bo);
838      if (_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
839         continue;
840
841      _mesa_bufferobj_map_range(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
842   }
843}
844
845
846/**
847 * Map buffer objects used in the vao, attribute arrays and index buffer.
848 */
849void
850_mesa_vao_map(struct gl_context *ctx, struct gl_vertex_array_object *vao,
851              GLbitfield access)
852{
853   struct gl_buffer_object *bo = vao->IndexBufferObj;
854
855   /* map the index buffer, if there is one, and not already mapped */
856   if (bo && !_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
857      _mesa_bufferobj_map_range(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
858
859   _mesa_vao_map_arrays(ctx, vao, access);
860}
861
862
863/**
864 * Unmap buffer objects used in attribute arrays.
865 */
866void
867_mesa_vao_unmap_arrays(struct gl_context *ctx,
868                       struct gl_vertex_array_object *vao)
869{
870   GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
871   while (mask) {
872      /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
873      const gl_vert_attrib attr = ffs(mask) - 1;
874      const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
875      struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
876      mask &= ~binding->_BoundArrays;
877
878      struct gl_buffer_object *bo = binding->BufferObj;
879      assert(bo);
880      if (!_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
881         continue;
882
883      _mesa_bufferobj_unmap(ctx, bo, MAP_INTERNAL);
884   }
885}
886
887
888/**
889 * Unmap buffer objects used in the vao, attribute arrays and index buffer.
890 */
891void
892_mesa_vao_unmap(struct gl_context *ctx, struct gl_vertex_array_object *vao)
893{
894   struct gl_buffer_object *bo = vao->IndexBufferObj;
895
896   /* unmap the index buffer, if there is one, and still mapped */
897   if (bo && _mesa_bufferobj_mapped(bo, MAP_INTERNAL))
898      _mesa_bufferobj_unmap(ctx, bo, MAP_INTERNAL);
899
900   _mesa_vao_unmap_arrays(ctx, vao);
901}
902
903
904/**********************************************************************/
905/* API Functions                                                      */
906/**********************************************************************/
907
908
909/**
910 * ARB version of glBindVertexArray()
911 */
912static ALWAYS_INLINE void
913bind_vertex_array(struct gl_context *ctx, GLuint id, bool no_error)
914{
915   struct gl_vertex_array_object *const oldObj = ctx->Array.VAO;
916   struct gl_vertex_array_object *newObj = NULL;
917
918   assert(oldObj != NULL);
919
920   if (oldObj->Name == id)
921      return;   /* rebinding the same array object- no change */
922
923   /*
924    * Get pointer to new array object (newObj)
925    */
926   if (id == 0) {
927      /* The spec says there is no array object named 0, but we use
928       * one internally because it simplifies things.
929       */
930      newObj = ctx->Array.DefaultVAO;
931   }
932   else {
933      /* non-default array object */
934      newObj = _mesa_lookup_vao(ctx, id);
935      if (!no_error && !newObj) {
936         _mesa_error(ctx, GL_INVALID_OPERATION,
937                     "glBindVertexArray(non-gen name)");
938         return;
939      }
940
941      newObj->EverBound = GL_TRUE;
942   }
943
944   /* The _DrawArrays pointer is pointing at the VAO being unbound and
945    * that VAO may be in the process of being deleted. If it's not going
946    * to be deleted, this will have no effect, because the pointer needs
947    * to be updated by the VBO module anyway.
948    *
949    * Before the VBO module can update the pointer, we have to set it
950    * to NULL for drivers not to set up arrays which are not bound,
951    * or to prevent a crash if the VAO being unbound is going to be
952    * deleted.
953    */
954   _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
955
956   _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj);
957
958   /* Update the valid-to-render state if binding on unbinding default VAO
959    * if drawing with the default VAO is invalid.
960    */
961   if (ctx->API == API_OPENGL_CORE &&
962       (oldObj == ctx->Array.DefaultVAO) != (newObj == ctx->Array.DefaultVAO))
963      _mesa_update_valid_to_render_state(ctx);
964}
965
966
967void GLAPIENTRY
968_mesa_BindVertexArray_no_error(GLuint id)
969{
970   GET_CURRENT_CONTEXT(ctx);
971   bind_vertex_array(ctx, id, true);
972}
973
974
975void GLAPIENTRY
976_mesa_BindVertexArray(GLuint id)
977{
978   GET_CURRENT_CONTEXT(ctx);
979   bind_vertex_array(ctx, id, false);
980}
981
982
983/**
984 * Delete a set of array objects.
985 *
986 * \param n      Number of array objects to delete.
987 * \param ids    Array of \c n array object IDs.
988 */
989static void
990delete_vertex_arrays(struct gl_context *ctx, GLsizei n, const GLuint *ids)
991{
992   GLsizei i;
993
994   for (i = 0; i < n; i++) {
995      /* IDs equal to 0 should be silently ignored. */
996      if (!ids[i])
997         continue;
998
999      struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]);
1000
1001      if (obj) {
1002         assert(obj->Name == ids[i]);
1003
1004         /* If the array object is currently bound, the spec says "the binding
1005          * for that object reverts to zero and the default vertex array
1006          * becomes current."
1007          */
1008         if (obj == ctx->Array.VAO)
1009            _mesa_BindVertexArray_no_error(0);
1010
1011         /* The ID is immediately freed for re-use */
1012         _mesa_HashRemoveLocked(ctx->Array.Objects, obj->Name);
1013
1014         if (ctx->Array.LastLookedUpVAO == obj)
1015            _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL);
1016         if (ctx->Array._DrawVAO == obj)
1017            _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
1018
1019         /* Unreference the array object.
1020          * If refcount hits zero, the object will be deleted.
1021          */
1022         _mesa_reference_vao(ctx, &obj, NULL);
1023      }
1024   }
1025}
1026
1027
1028void GLAPIENTRY
1029_mesa_DeleteVertexArrays_no_error(GLsizei n, const GLuint *ids)
1030{
1031   GET_CURRENT_CONTEXT(ctx);
1032   delete_vertex_arrays(ctx, n, ids);
1033}
1034
1035
1036void GLAPIENTRY
1037_mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
1038{
1039   GET_CURRENT_CONTEXT(ctx);
1040
1041   if (n < 0) {
1042      _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)");
1043      return;
1044   }
1045
1046   delete_vertex_arrays(ctx, n, ids);
1047}
1048
1049
1050/**
1051 * Generate a set of unique array object IDs and store them in \c arrays.
1052 * Helper for _mesa_GenVertexArrays() and _mesa_CreateVertexArrays()
1053 * below.
1054 *
1055 * \param n       Number of IDs to generate.
1056 * \param arrays  Array of \c n locations to store the IDs.
1057 * \param create  Indicates that the objects should also be created.
1058 * \param func    The name of the GL entry point.
1059 */
1060static void
1061gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
1062                  bool create, const char *func)
1063{
1064   GLint i;
1065
1066   if (!arrays)
1067      return;
1068
1069   _mesa_HashFindFreeKeys(ctx->Array.Objects, arrays, n);
1070
1071   /* For the sake of simplicity we create the array objects in both
1072    * the Gen* and Create* cases.  The only difference is the value of
1073    * EverBound, which is set to true in the Create* case.
1074    */
1075   for (i = 0; i < n; i++) {
1076      struct gl_vertex_array_object *obj;
1077
1078      obj = _mesa_new_vao(ctx, arrays[i]);
1079      if (!obj) {
1080         _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1081         return;
1082      }
1083      obj->EverBound = create;
1084      _mesa_HashInsertLocked(ctx->Array.Objects, obj->Name, obj, true);
1085   }
1086}
1087
1088
1089static void
1090gen_vertex_arrays_err(struct gl_context *ctx, GLsizei n, GLuint *arrays,
1091                      bool create, const char *func)
1092{
1093   if (n < 0) {
1094      _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
1095      return;
1096   }
1097
1098   gen_vertex_arrays(ctx, n, arrays, create, func);
1099}
1100
1101
1102/**
1103 * ARB version of glGenVertexArrays()
1104 * All arrays will be required to live in VBOs.
1105 */
1106void GLAPIENTRY
1107_mesa_GenVertexArrays_no_error(GLsizei n, GLuint *arrays)
1108{
1109   GET_CURRENT_CONTEXT(ctx);
1110   gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays");
1111}
1112
1113
1114void GLAPIENTRY
1115_mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
1116{
1117   GET_CURRENT_CONTEXT(ctx);
1118   gen_vertex_arrays_err(ctx, n, arrays, false, "glGenVertexArrays");
1119}
1120
1121
1122/**
1123 * ARB_direct_state_access
1124 * Generates ID's and creates the array objects.
1125 */
1126void GLAPIENTRY
1127_mesa_CreateVertexArrays_no_error(GLsizei n, GLuint *arrays)
1128{
1129   GET_CURRENT_CONTEXT(ctx);
1130   gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays");
1131}
1132
1133
1134void GLAPIENTRY
1135_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays)
1136{
1137   GET_CURRENT_CONTEXT(ctx);
1138   gen_vertex_arrays_err(ctx, n, arrays, true, "glCreateVertexArrays");
1139}
1140
1141
1142/**
1143 * Determine if ID is the name of an array object.
1144 *
1145 * \param id  ID of the potential array object.
1146 * \return  \c GL_TRUE if \c id is the name of a array object,
1147 *          \c GL_FALSE otherwise.
1148 */
1149GLboolean GLAPIENTRY
1150_mesa_IsVertexArray( GLuint id )
1151{
1152   struct gl_vertex_array_object * obj;
1153   GET_CURRENT_CONTEXT(ctx);
1154   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1155
1156   obj = _mesa_lookup_vao(ctx, id);
1157
1158   return obj != NULL && obj->EverBound;
1159}
1160
1161
1162/**
1163 * Sets the element array buffer binding of a vertex array object.
1164 *
1165 * This is the ARB_direct_state_access equivalent of
1166 * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer).
1167 */
1168static ALWAYS_INLINE void
1169vertex_array_element_buffer(struct gl_context *ctx, GLuint vaobj, GLuint buffer,
1170                            bool no_error)
1171{
1172   struct gl_vertex_array_object *vao;
1173   struct gl_buffer_object *bufObj;
1174
1175   ASSERT_OUTSIDE_BEGIN_END(ctx);
1176
1177   if (!no_error) {
1178      /* The GL_ARB_direct_state_access specification says:
1179       *
1180       *    "An INVALID_OPERATION error is generated by
1181       *     VertexArrayElementBuffer if <vaobj> is not [compatibility profile:
1182       *     zero or] the name of an existing vertex array object."
1183       */
1184      vao =_mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayElementBuffer");
1185      if (!vao)
1186         return;
1187   } else {
1188      vao = _mesa_lookup_vao(ctx, vaobj);
1189   }
1190
1191   if (buffer != 0) {
1192      if (!no_error) {
1193         /* The GL_ARB_direct_state_access specification says:
1194          *
1195          *    "An INVALID_OPERATION error is generated if <buffer> is not zero
1196          *     or the name of an existing buffer object."
1197          */
1198         bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
1199                                             "glVertexArrayElementBuffer");
1200      } else {
1201         bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1202      }
1203
1204      if (!bufObj)
1205         return;
1206   } else {
1207      bufObj = NULL;
1208   }
1209
1210   _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
1211}
1212
1213
1214void GLAPIENTRY
1215_mesa_VertexArrayElementBuffer_no_error(GLuint vaobj, GLuint buffer)
1216{
1217   GET_CURRENT_CONTEXT(ctx);
1218   vertex_array_element_buffer(ctx, vaobj, buffer, true);
1219}
1220
1221
1222void GLAPIENTRY
1223_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer)
1224{
1225   GET_CURRENT_CONTEXT(ctx);
1226   vertex_array_element_buffer(ctx, vaobj, buffer, false);
1227}
1228
1229
1230void GLAPIENTRY
1231_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param)
1232{
1233   GET_CURRENT_CONTEXT(ctx);
1234   struct gl_vertex_array_object *vao;
1235
1236   ASSERT_OUTSIDE_BEGIN_END(ctx);
1237
1238   /* The GL_ARB_direct_state_access specification says:
1239    *
1240    *   "An INVALID_OPERATION error is generated if <vaobj> is not
1241    *    [compatibility profile: zero or] the name of an existing
1242    *    vertex array object."
1243    */
1244   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayiv");
1245   if (!vao)
1246      return;
1247
1248   /* The GL_ARB_direct_state_access specification says:
1249    *
1250    *   "An INVALID_ENUM error is generated if <pname> is not
1251    *    ELEMENT_ARRAY_BUFFER_BINDING."
1252    */
1253   if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
1254      _mesa_error(ctx, GL_INVALID_ENUM,
1255                  "glGetVertexArrayiv(pname != "
1256                  "GL_ELEMENT_ARRAY_BUFFER_BINDING)");
1257      return;
1258   }
1259
1260   param[0] = vao->IndexBufferObj ? vao->IndexBufferObj->Name : 0;
1261}
1262