• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5  * (C) Copyright IBM Corporation 2006
6  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  */
26 
27 
28 /**
29  * \file arrayobj.c
30  *
31  * Implementation of Vertex Array Objects (VAOs), from OpenGL 3.1+ /
32  * the GL_ARB_vertex_array_object extension.
33  *
34  * \todo
35  * The code in this file borrows a lot from bufferobj.c.  There's a certain
36  * amount of cruft left over from that origin that may be unnecessary.
37  *
38  * \author Ian Romanick <idr@us.ibm.com>
39  * \author Brian Paul
40  */
41 
42 
43 #include "glheader.h"
44 #include "hash.h"
45 #include "image.h"
46 
47 #include "context.h"
48 #include "bufferobj.h"
49 #include "arrayobj.h"
50 #include "draw_validate.h"
51 #include "macros.h"
52 #include "mtypes.h"
53 #include "state.h"
54 #include "varray.h"
55 #include "util/bitscan.h"
56 #include "util/u_atomic.h"
57 #include "util/u_math.h"
58 #include "util/u_memory.h"
59 
60 
61 const 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 
199 struct gl_vertex_array_object *
_mesa_lookup_vao(struct gl_context * ctx,GLuint id)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  */
242 struct gl_vertex_array_object *
_mesa_lookup_vao_err(struct gl_context * ctx,GLuint id,bool is_ext_dsa,const char * caller)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  */
308 void
_mesa_unbind_array_object_vbos(struct gl_context * ctx,struct gl_vertex_array_object * obj)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  */
322 struct gl_vertex_array_object *
_mesa_new_vao(struct gl_context * ctx,GLuint name)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  */
335 void
_mesa_delete_vao(struct gl_context * ctx,struct gl_vertex_array_object * obj)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  */
350 void
_mesa_reference_vao_(struct gl_context * ctx,struct gl_vertex_array_object ** ptr,struct gl_vertex_array_object * vao)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  */
394 void
_mesa_initialize_vao(struct gl_context * ctx,struct gl_vertex_array_object * vao,GLuint name)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  */
409 static void
compute_vbo_offset_range(const struct gl_vertex_array_object * vao,const struct gl_vertex_buffer_binding * binding,GLsizeiptr * min,GLsizeiptr * max)410 compute_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  */
516 void
_mesa_update_vao_derived_arrays(struct gl_context * ctx,struct gl_vertex_array_object * vao)517 _mesa_update_vao_derived_arrays(struct gl_context *ctx,
518                                 struct gl_vertex_array_object *vao)
519 {
520    /* Make sure we do not run into problems with shared objects */
521    assert(!vao->SharedAndImmutable || vao->NewArrays == 0);
522 
523    /* Limit used for common binding scanning below. */
524    const GLsizeiptr MaxRelativeOffset =
525       ctx->Const.MaxVertexAttribRelativeOffset;
526 
527    /* The gl_vertex_array_object::_AttributeMapMode denotes the way
528     * VERT_ATTRIB_{POS,GENERIC0} mapping is done.
529     *
530     * This mapping is used to map between the OpenGL api visible
531     * VERT_ATTRIB_* arrays to mesa driver arrayinputs or shader inputs.
532     * The mapping only depends on the enabled bits of the
533     * VERT_ATTRIB_{POS,GENERIC0} arrays and is tracked in the VAO.
534     *
535     * This map needs to be applied when finally translating to the bitmasks
536     * as consumed by the driver backends. The duplicate scanning is here
537     * can as well be done in the OpenGL API numbering without this map.
538     */
539    const gl_attribute_map_mode mode = vao->_AttributeMapMode;
540    /* Enabled array bits. */
541    const GLbitfield enabled = vao->Enabled;
542    /* VBO array bits. */
543    const GLbitfield vbos = vao->VertexAttribBufferMask;
544    const GLbitfield divisor_is_nonzero = vao->NonZeroDivisorMask;
545 
546    /* Compute and store effectively enabled and mapped vbo arrays */
547    vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos);
548    vao->_EffEnabledNonZeroDivisor =
549       _mesa_vao_enable_to_vp_inputs(mode, enabled & divisor_is_nonzero);
550 
551    /* Fast path when the VAO is updated too often. */
552    if (vao->IsDynamic)
553       return;
554 
555    /* More than 4 updates turn the VAO to dynamic. */
556    if (ctx->Const.AllowDynamicVAOFastPath && ++vao->NumUpdates > 4) {
557       vao->IsDynamic = true;
558       return;
559    }
560 
561    /* Walk those enabled arrays that have a real vbo attached */
562    GLbitfield mask = enabled;
563    while (mask) {
564       /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
565       const int i = ffs(mask) - 1;
566       /* The binding from the first to be processed attribute. */
567       const GLuint bindex = vao->VertexAttrib[i].BufferBindingIndex;
568       struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
569 
570       /* The scan goes different for user space arrays than vbos */
571       if (binding->BufferObj) {
572          /* The bound arrays. */
573          const GLbitfield bound = enabled & binding->_BoundArrays;
574 
575          /* Start this current effective binding with the actual bound arrays */
576          GLbitfield eff_bound_arrays = bound;
577 
578          /*
579           * If there is nothing left to scan just update the effective binding
580           * information. If the VAO is already only using a single binding point
581           * we end up here. So the overhead of this scan for an application
582           * carefully preparing the VAO for draw is low.
583           */
584 
585          GLbitfield scanmask = mask & vbos & ~bound;
586          /* Is there something left to scan? */
587          if (scanmask == 0) {
588             /* Just update the back reference from the attrib to the binding and
589              * the effective offset.
590              */
591             GLbitfield attrmask = eff_bound_arrays;
592             while (attrmask) {
593                const int j = u_bit_scan(&attrmask);
594                struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
595 
596                /* Update the index into the common binding point and offset */
597                attrib2->_EffBufferBindingIndex = bindex;
598                attrib2->_EffRelativeOffset = attrib2->RelativeOffset;
599                assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
600             }
601             /* Finally this is the set of effectively bound arrays with the
602              * original binding offset.
603              */
604             binding->_EffOffset = binding->Offset;
605             /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
606             binding->_EffBoundArrays =
607                _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
608 
609          } else {
610             /* In the VBO case, scan for attribute/binding
611              * combinations with relative bindings in the range of
612              * [0, ctx->Const.MaxVertexAttribRelativeOffset].
613              * Note that this does also go beyond just interleaved arrays
614              * as long as they use the same VBO, binding parameters and the
615              * offsets stay within bounds that the backend still can handle.
616              */
617 
618             GLsizeiptr min_offset, max_offset;
619             compute_vbo_offset_range(vao, binding, &min_offset, &max_offset);
620             assert(max_offset <= min_offset + MaxRelativeOffset);
621 
622             /* Now scan. */
623             while (scanmask) {
624                /* Do not use u_bit_scan as we can walk multiple
625                 * attrib arrays at once
626                 */
627                const int j = ffs(scanmask) - 1;
628                const struct gl_array_attributes *attrib2 =
629                   &vao->VertexAttrib[j];
630                const struct gl_vertex_buffer_binding *binding2 =
631                   &vao->BufferBinding[attrib2->BufferBindingIndex];
632 
633                /* Remove those attrib bits from the mask that are bound to the
634                 * same effective binding point.
635                 */
636                const GLbitfield bound2 = enabled & binding2->_BoundArrays;
637                scanmask &= ~bound2;
638 
639                /* Check if we have an identical binding */
640                if (binding->Stride != binding2->Stride)
641                   continue;
642                if (binding->InstanceDivisor != binding2->InstanceDivisor)
643                   continue;
644                if (binding->BufferObj != binding2->BufferObj)
645                   continue;
646                /* Check if we can fold both bindings into a common binding */
647                GLsizeiptr min_offset2, max_offset2;
648                compute_vbo_offset_range(vao, binding2,
649                                         &min_offset2, &max_offset2);
650                /* If the relative offset is within the limits ... */
651                if (min_offset + MaxRelativeOffset < max_offset2)
652                   continue;
653                if (min_offset2 + MaxRelativeOffset < max_offset)
654                   continue;
655                /* ... add this array to the effective binding */
656                eff_bound_arrays |= bound2;
657                min_offset = MIN2(min_offset, min_offset2);
658                max_offset = MAX2(max_offset, max_offset2);
659                assert(max_offset <= min_offset + MaxRelativeOffset);
660             }
661 
662             /* Update the back reference from the attrib to the binding */
663             GLbitfield attrmask = eff_bound_arrays;
664             while (attrmask) {
665                const int j = u_bit_scan(&attrmask);
666                struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
667                const struct gl_vertex_buffer_binding *binding2 =
668                   &vao->BufferBinding[attrib2->BufferBindingIndex];
669 
670                /* Update the index into the common binding point and offset */
671                attrib2->_EffBufferBindingIndex = bindex;
672                attrib2->_EffRelativeOffset =
673                   binding2->Offset + attrib2->RelativeOffset - min_offset;
674                assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
675             }
676             /* Finally this is the set of effectively bound arrays */
677             binding->_EffOffset = min_offset;
678             /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
679             binding->_EffBoundArrays =
680                _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
681          }
682 
683          /* Mark all the effective bound arrays as processed. */
684          mask &= ~eff_bound_arrays;
685 
686       } else {
687          /* Scanning of common bindings for user space arrays.
688           */
689 
690          const struct gl_array_attributes *attrib = &vao->VertexAttrib[i];
691          const GLbitfield bound = VERT_BIT(i);
692 
693          /* Note that user space array pointers can only happen using a one
694           * to one binding point to array mapping.
695           * The OpenGL 4.x/ARB_vertex_attrib_binding api does not support
696           * user space arrays collected at multiple binding points.
697           * The only provider of user space interleaved arrays with a single
698           * binding point is the mesa internal vbo module. But that one
699           * provides a perfect interleaved set of arrays.
700           *
701           * If this would not be true we would potentially get attribute arrays
702           * with user space pointers that may not lie within the
703           * MaxRelativeOffset range but still attached to a single binding.
704           * Then we would need to store the effective attribute and binding
705           * grouping information in a seperate array beside
706           * gl_array_attributes/gl_vertex_buffer_binding.
707           */
708          assert(util_bitcount(binding->_BoundArrays & vao->Enabled) == 1
709                 || (vao->Enabled & ~binding->_BoundArrays) == 0);
710 
711          /* Start this current effective binding with the array */
712          GLbitfield eff_bound_arrays = bound;
713 
714          const GLubyte *ptr = attrib->Ptr;
715          unsigned vertex_end = attrib->Format._ElementSize;
716 
717          /* Walk other user space arrays and see which are interleaved
718           * using the same binding parameters.
719           */
720          GLbitfield scanmask = mask & ~vbos & ~bound;
721          while (scanmask) {
722             const int j = u_bit_scan(&scanmask);
723             const struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
724             const struct gl_vertex_buffer_binding *binding2 =
725                &vao->BufferBinding[attrib2->BufferBindingIndex];
726 
727             /* See the comment at the same assert above. */
728             assert(util_bitcount(binding2->_BoundArrays & vao->Enabled) == 1
729                    || (vao->Enabled & ~binding->_BoundArrays) == 0);
730 
731             /* Check if we have an identical binding */
732             if (binding->Stride != binding2->Stride)
733                continue;
734             if (binding->InstanceDivisor != binding2->InstanceDivisor)
735                continue;
736             if (ptr <= attrib2->Ptr) {
737                if (ptr + binding->Stride < attrib2->Ptr +
738                    attrib2->Format._ElementSize)
739                   continue;
740                unsigned end = attrib2->Ptr + attrib2->Format._ElementSize - ptr;
741                vertex_end = MAX2(vertex_end, end);
742             } else {
743                if (attrib2->Ptr + binding->Stride < ptr + vertex_end)
744                   continue;
745                vertex_end += (GLsizei)(ptr - attrib2->Ptr);
746                ptr = attrib2->Ptr;
747             }
748 
749             /* User space buffer object */
750             assert(!binding2->BufferObj);
751 
752             eff_bound_arrays |= VERT_BIT(j);
753          }
754 
755          /* Update the back reference from the attrib to the binding */
756          GLbitfield attrmask = eff_bound_arrays;
757          while (attrmask) {
758             const int j = u_bit_scan(&attrmask);
759             struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
760 
761             /* Update the index into the common binding point and the offset */
762             attrib2->_EffBufferBindingIndex = bindex;
763             attrib2->_EffRelativeOffset = attrib2->Ptr - ptr;
764             assert(attrib2->_EffRelativeOffset <= binding->Stride);
765          }
766          /* Finally this is the set of effectively bound arrays */
767          binding->_EffOffset = (GLintptr)ptr;
768          /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
769          binding->_EffBoundArrays =
770             _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
771 
772          /* Mark all the effective bound arrays as processed. */
773          mask &= ~eff_bound_arrays;
774       }
775    }
776 
777 #ifndef NDEBUG
778    /* Make sure the above code works as expected. */
779    for (gl_vert_attrib attr = 0; attr < VERT_ATTRIB_MAX; ++attr) {
780       /* Query the original api defined attrib/binding information ... */
781       const unsigned char *const map =_mesa_vao_attribute_map[mode];
782       if (vao->Enabled & VERT_BIT(map[attr])) {
783          const struct gl_array_attributes *attrib =
784             &vao->VertexAttrib[map[attr]];
785          const struct gl_vertex_buffer_binding *binding =
786             &vao->BufferBinding[attrib->BufferBindingIndex];
787          /* ... and compare that with the computed attrib/binding */
788          const struct gl_vertex_buffer_binding *binding2 =
789             &vao->BufferBinding[attrib->_EffBufferBindingIndex];
790          assert(binding->Stride == binding2->Stride);
791          assert(binding->InstanceDivisor == binding2->InstanceDivisor);
792          assert(binding->BufferObj == binding2->BufferObj);
793          if (binding->BufferObj) {
794             assert(attrib->_EffRelativeOffset <= MaxRelativeOffset);
795             assert(binding->Offset + attrib->RelativeOffset ==
796                    binding2->_EffOffset + attrib->_EffRelativeOffset);
797          } else {
798             assert(attrib->_EffRelativeOffset < binding->Stride);
799             assert((GLintptr)attrib->Ptr ==
800                    binding2->_EffOffset + attrib->_EffRelativeOffset);
801          }
802       }
803    }
804 #endif
805 }
806 
807 
808 void
_mesa_set_vao_immutable(struct gl_context * ctx,struct gl_vertex_array_object * vao)809 _mesa_set_vao_immutable(struct gl_context *ctx,
810                         struct gl_vertex_array_object *vao)
811 {
812    _mesa_update_vao_derived_arrays(ctx, vao);
813    vao->NewArrays = 0;
814    vao->SharedAndImmutable = true;
815 }
816 
817 
818 bool
_mesa_all_varyings_in_vbos(const struct gl_vertex_array_object * vao)819 _mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao)
820 {
821    /* Walk those enabled arrays that have the default vbo attached */
822    GLbitfield mask = vao->Enabled & ~vao->VertexAttribBufferMask;
823 
824    while (mask) {
825       /* Do not use u_bit_scan64 as we can walk multiple
826        * attrib arrays at once
827        */
828       const int i = ffs(mask) - 1;
829       const struct gl_array_attributes *attrib_array =
830          &vao->VertexAttrib[i];
831       const struct gl_vertex_buffer_binding *buffer_binding =
832          &vao->BufferBinding[attrib_array->BufferBindingIndex];
833 
834       /* We have already masked out vao->VertexAttribBufferMask  */
835       assert(!buffer_binding->BufferObj);
836 
837       /* Bail out once we find the first non vbo with a non zero stride */
838       if (buffer_binding->Stride != 0)
839          return false;
840 
841       /* Note that we cannot use the xor variant since the _BoundArray mask
842        * may contain array attributes that are bound but not enabled.
843        */
844       mask &= ~buffer_binding->_BoundArrays;
845    }
846 
847    return true;
848 }
849 
850 bool
_mesa_all_buffers_are_unmapped(const struct gl_vertex_array_object * vao)851 _mesa_all_buffers_are_unmapped(const struct gl_vertex_array_object *vao)
852 {
853    /* Walk the enabled arrays that have a vbo attached */
854    GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
855 
856    while (mask) {
857       const int i = ffs(mask) - 1;
858       const struct gl_array_attributes *attrib_array =
859          &vao->VertexAttrib[i];
860       const struct gl_vertex_buffer_binding *buffer_binding =
861          &vao->BufferBinding[attrib_array->BufferBindingIndex];
862 
863       /* We have already masked with vao->VertexAttribBufferMask  */
864       assert(buffer_binding->BufferObj);
865 
866       /* Bail out once we find the first disallowed mapping */
867       if (_mesa_check_disallowed_mapping(buffer_binding->BufferObj))
868          return false;
869 
870       /* We have handled everything that is bound to this buffer_binding. */
871       mask &= ~buffer_binding->_BoundArrays;
872    }
873 
874    return true;
875 }
876 
877 
878 /**
879  * Map buffer objects used in attribute arrays.
880  */
881 void
_mesa_vao_map_arrays(struct gl_context * ctx,struct gl_vertex_array_object * vao,GLbitfield access)882 _mesa_vao_map_arrays(struct gl_context *ctx, struct gl_vertex_array_object *vao,
883                      GLbitfield access)
884 {
885    GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
886    while (mask) {
887       /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
888       const gl_vert_attrib attr = ffs(mask) - 1;
889       const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
890       struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
891       mask &= ~binding->_BoundArrays;
892 
893       struct gl_buffer_object *bo = binding->BufferObj;
894       assert(bo);
895       if (_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
896          continue;
897 
898       ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
899    }
900 }
901 
902 
903 /**
904  * Map buffer objects used in the vao, attribute arrays and index buffer.
905  */
906 void
_mesa_vao_map(struct gl_context * ctx,struct gl_vertex_array_object * vao,GLbitfield access)907 _mesa_vao_map(struct gl_context *ctx, struct gl_vertex_array_object *vao,
908               GLbitfield access)
909 {
910    struct gl_buffer_object *bo = vao->IndexBufferObj;
911 
912    /* map the index buffer, if there is one, and not already mapped */
913    if (bo && !_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
914       ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
915 
916    _mesa_vao_map_arrays(ctx, vao, access);
917 }
918 
919 
920 /**
921  * Unmap buffer objects used in attribute arrays.
922  */
923 void
_mesa_vao_unmap_arrays(struct gl_context * ctx,struct gl_vertex_array_object * vao)924 _mesa_vao_unmap_arrays(struct gl_context *ctx,
925                        struct gl_vertex_array_object *vao)
926 {
927    GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
928    while (mask) {
929       /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
930       const gl_vert_attrib attr = ffs(mask) - 1;
931       const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
932       struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
933       mask &= ~binding->_BoundArrays;
934 
935       struct gl_buffer_object *bo = binding->BufferObj;
936       assert(bo);
937       if (!_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
938          continue;
939 
940       ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
941    }
942 }
943 
944 
945 /**
946  * Unmap buffer objects used in the vao, attribute arrays and index buffer.
947  */
948 void
_mesa_vao_unmap(struct gl_context * ctx,struct gl_vertex_array_object * vao)949 _mesa_vao_unmap(struct gl_context *ctx, struct gl_vertex_array_object *vao)
950 {
951    struct gl_buffer_object *bo = vao->IndexBufferObj;
952 
953    /* unmap the index buffer, if there is one, and still mapped */
954    if (bo && _mesa_bufferobj_mapped(bo, MAP_INTERNAL))
955       ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
956 
957    _mesa_vao_unmap_arrays(ctx, vao);
958 }
959 
960 
961 /**********************************************************************/
962 /* API Functions                                                      */
963 /**********************************************************************/
964 
965 
966 /**
967  * ARB version of glBindVertexArray()
968  */
969 static ALWAYS_INLINE void
bind_vertex_array(struct gl_context * ctx,GLuint id,bool no_error)970 bind_vertex_array(struct gl_context *ctx, GLuint id, bool no_error)
971 {
972    struct gl_vertex_array_object *const oldObj = ctx->Array.VAO;
973    struct gl_vertex_array_object *newObj = NULL;
974 
975    assert(oldObj != NULL);
976 
977    if (oldObj->Name == id)
978       return;   /* rebinding the same array object- no change */
979 
980    /*
981     * Get pointer to new array object (newObj)
982     */
983    if (id == 0) {
984       /* The spec says there is no array object named 0, but we use
985        * one internally because it simplifies things.
986        */
987       newObj = ctx->Array.DefaultVAO;
988    }
989    else {
990       /* non-default array object */
991       newObj = _mesa_lookup_vao(ctx, id);
992       if (!no_error && !newObj) {
993          _mesa_error(ctx, GL_INVALID_OPERATION,
994                      "glBindVertexArray(non-gen name)");
995          return;
996       }
997 
998       newObj->EverBound = GL_TRUE;
999    }
1000 
1001    /* The _DrawArrays pointer is pointing at the VAO being unbound and
1002     * that VAO may be in the process of being deleted. If it's not going
1003     * to be deleted, this will have no effect, because the pointer needs
1004     * to be updated by the VBO module anyway.
1005     *
1006     * Before the VBO module can update the pointer, we have to set it
1007     * to NULL for drivers not to set up arrays which are not bound,
1008     * or to prevent a crash if the VAO being unbound is going to be
1009     * deleted.
1010     */
1011    _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
1012 
1013    _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj);
1014 
1015    /* Update the valid-to-render state if binding on unbinding default VAO
1016     * if drawing with the default VAO is invalid.
1017     */
1018    if (ctx->API == API_OPENGL_CORE &&
1019        (oldObj == ctx->Array.DefaultVAO) != (newObj == ctx->Array.DefaultVAO))
1020       _mesa_update_valid_to_render_state(ctx);
1021 }
1022 
1023 
1024 void GLAPIENTRY
_mesa_BindVertexArray_no_error(GLuint id)1025 _mesa_BindVertexArray_no_error(GLuint id)
1026 {
1027    GET_CURRENT_CONTEXT(ctx);
1028    bind_vertex_array(ctx, id, true);
1029 }
1030 
1031 
1032 void GLAPIENTRY
_mesa_BindVertexArray(GLuint id)1033 _mesa_BindVertexArray(GLuint id)
1034 {
1035    GET_CURRENT_CONTEXT(ctx);
1036    bind_vertex_array(ctx, id, false);
1037 }
1038 
1039 
1040 /**
1041  * Delete a set of array objects.
1042  *
1043  * \param n      Number of array objects to delete.
1044  * \param ids    Array of \c n array object IDs.
1045  */
1046 static void
delete_vertex_arrays(struct gl_context * ctx,GLsizei n,const GLuint * ids)1047 delete_vertex_arrays(struct gl_context *ctx, GLsizei n, const GLuint *ids)
1048 {
1049    GLsizei i;
1050 
1051    for (i = 0; i < n; i++) {
1052       /* IDs equal to 0 should be silently ignored. */
1053       if (!ids[i])
1054          continue;
1055 
1056       struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]);
1057 
1058       if (obj) {
1059          assert(obj->Name == ids[i]);
1060 
1061          /* If the array object is currently bound, the spec says "the binding
1062           * for that object reverts to zero and the default vertex array
1063           * becomes current."
1064           */
1065          if (obj == ctx->Array.VAO)
1066             _mesa_BindVertexArray_no_error(0);
1067 
1068          /* The ID is immediately freed for re-use */
1069          _mesa_HashRemoveLocked(ctx->Array.Objects, obj->Name);
1070 
1071          if (ctx->Array.LastLookedUpVAO == obj)
1072             _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL);
1073          if (ctx->Array._DrawVAO == obj)
1074             _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
1075 
1076          /* Unreference the array object.
1077           * If refcount hits zero, the object will be deleted.
1078           */
1079          _mesa_reference_vao(ctx, &obj, NULL);
1080       }
1081    }
1082 }
1083 
1084 
1085 void GLAPIENTRY
_mesa_DeleteVertexArrays_no_error(GLsizei n,const GLuint * ids)1086 _mesa_DeleteVertexArrays_no_error(GLsizei n, const GLuint *ids)
1087 {
1088    GET_CURRENT_CONTEXT(ctx);
1089    delete_vertex_arrays(ctx, n, ids);
1090 }
1091 
1092 
1093 void GLAPIENTRY
_mesa_DeleteVertexArrays(GLsizei n,const GLuint * ids)1094 _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
1095 {
1096    GET_CURRENT_CONTEXT(ctx);
1097 
1098    if (n < 0) {
1099       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)");
1100       return;
1101    }
1102 
1103    delete_vertex_arrays(ctx, n, ids);
1104 }
1105 
1106 
1107 /**
1108  * Generate a set of unique array object IDs and store them in \c arrays.
1109  * Helper for _mesa_GenVertexArrays() and _mesa_CreateVertexArrays()
1110  * below.
1111  *
1112  * \param n       Number of IDs to generate.
1113  * \param arrays  Array of \c n locations to store the IDs.
1114  * \param create  Indicates that the objects should also be created.
1115  * \param func    The name of the GL entry point.
1116  */
1117 static void
gen_vertex_arrays(struct gl_context * ctx,GLsizei n,GLuint * arrays,bool create,const char * func)1118 gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
1119                   bool create, const char *func)
1120 {
1121    GLint i;
1122 
1123    if (!arrays)
1124       return;
1125 
1126    _mesa_HashFindFreeKeys(ctx->Array.Objects, arrays, n);
1127 
1128    /* For the sake of simplicity we create the array objects in both
1129     * the Gen* and Create* cases.  The only difference is the value of
1130     * EverBound, which is set to true in the Create* case.
1131     */
1132    for (i = 0; i < n; i++) {
1133       struct gl_vertex_array_object *obj;
1134 
1135       obj = _mesa_new_vao(ctx, arrays[i]);
1136       if (!obj) {
1137          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
1138          return;
1139       }
1140       obj->EverBound = create;
1141       _mesa_HashInsertLocked(ctx->Array.Objects, obj->Name, obj, true);
1142    }
1143 }
1144 
1145 
1146 static void
gen_vertex_arrays_err(struct gl_context * ctx,GLsizei n,GLuint * arrays,bool create,const char * func)1147 gen_vertex_arrays_err(struct gl_context *ctx, GLsizei n, GLuint *arrays,
1148                       bool create, const char *func)
1149 {
1150    if (n < 0) {
1151       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
1152       return;
1153    }
1154 
1155    gen_vertex_arrays(ctx, n, arrays, create, func);
1156 }
1157 
1158 
1159 /**
1160  * ARB version of glGenVertexArrays()
1161  * All arrays will be required to live in VBOs.
1162  */
1163 void GLAPIENTRY
_mesa_GenVertexArrays_no_error(GLsizei n,GLuint * arrays)1164 _mesa_GenVertexArrays_no_error(GLsizei n, GLuint *arrays)
1165 {
1166    GET_CURRENT_CONTEXT(ctx);
1167    gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays");
1168 }
1169 
1170 
1171 void GLAPIENTRY
_mesa_GenVertexArrays(GLsizei n,GLuint * arrays)1172 _mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
1173 {
1174    GET_CURRENT_CONTEXT(ctx);
1175    gen_vertex_arrays_err(ctx, n, arrays, false, "glGenVertexArrays");
1176 }
1177 
1178 
1179 /**
1180  * ARB_direct_state_access
1181  * Generates ID's and creates the array objects.
1182  */
1183 void GLAPIENTRY
_mesa_CreateVertexArrays_no_error(GLsizei n,GLuint * arrays)1184 _mesa_CreateVertexArrays_no_error(GLsizei n, GLuint *arrays)
1185 {
1186    GET_CURRENT_CONTEXT(ctx);
1187    gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays");
1188 }
1189 
1190 
1191 void GLAPIENTRY
_mesa_CreateVertexArrays(GLsizei n,GLuint * arrays)1192 _mesa_CreateVertexArrays(GLsizei n, GLuint *arrays)
1193 {
1194    GET_CURRENT_CONTEXT(ctx);
1195    gen_vertex_arrays_err(ctx, n, arrays, true, "glCreateVertexArrays");
1196 }
1197 
1198 
1199 /**
1200  * Determine if ID is the name of an array object.
1201  *
1202  * \param id  ID of the potential array object.
1203  * \return  \c GL_TRUE if \c id is the name of a array object,
1204  *          \c GL_FALSE otherwise.
1205  */
1206 GLboolean GLAPIENTRY
_mesa_IsVertexArray(GLuint id)1207 _mesa_IsVertexArray( GLuint id )
1208 {
1209    struct gl_vertex_array_object * obj;
1210    GET_CURRENT_CONTEXT(ctx);
1211    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1212 
1213    obj = _mesa_lookup_vao(ctx, id);
1214 
1215    return obj != NULL && obj->EverBound;
1216 }
1217 
1218 
1219 /**
1220  * Sets the element array buffer binding of a vertex array object.
1221  *
1222  * This is the ARB_direct_state_access equivalent of
1223  * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer).
1224  */
1225 static ALWAYS_INLINE void
vertex_array_element_buffer(struct gl_context * ctx,GLuint vaobj,GLuint buffer,bool no_error)1226 vertex_array_element_buffer(struct gl_context *ctx, GLuint vaobj, GLuint buffer,
1227                             bool no_error)
1228 {
1229    struct gl_vertex_array_object *vao;
1230    struct gl_buffer_object *bufObj;
1231 
1232    ASSERT_OUTSIDE_BEGIN_END(ctx);
1233 
1234    if (!no_error) {
1235       /* The GL_ARB_direct_state_access specification says:
1236        *
1237        *    "An INVALID_OPERATION error is generated by
1238        *     VertexArrayElementBuffer if <vaobj> is not [compatibility profile:
1239        *     zero or] the name of an existing vertex array object."
1240        */
1241       vao =_mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayElementBuffer");
1242       if (!vao)
1243          return;
1244    } else {
1245       vao = _mesa_lookup_vao(ctx, vaobj);
1246    }
1247 
1248    if (buffer != 0) {
1249       if (!no_error) {
1250          /* The GL_ARB_direct_state_access specification says:
1251           *
1252           *    "An INVALID_OPERATION error is generated if <buffer> is not zero
1253           *     or the name of an existing buffer object."
1254           */
1255          bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
1256                                              "glVertexArrayElementBuffer");
1257       } else {
1258          bufObj = _mesa_lookup_bufferobj(ctx, buffer);
1259       }
1260 
1261       if (!bufObj)
1262          return;
1263 
1264       bufObj->UsageHistory |= USAGE_ELEMENT_ARRAY_BUFFER;
1265    } else {
1266       bufObj = NULL;
1267    }
1268 
1269    _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
1270 }
1271 
1272 
1273 void GLAPIENTRY
_mesa_VertexArrayElementBuffer_no_error(GLuint vaobj,GLuint buffer)1274 _mesa_VertexArrayElementBuffer_no_error(GLuint vaobj, GLuint buffer)
1275 {
1276    GET_CURRENT_CONTEXT(ctx);
1277    vertex_array_element_buffer(ctx, vaobj, buffer, true);
1278 }
1279 
1280 
1281 void GLAPIENTRY
_mesa_VertexArrayElementBuffer(GLuint vaobj,GLuint buffer)1282 _mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer)
1283 {
1284    GET_CURRENT_CONTEXT(ctx);
1285    vertex_array_element_buffer(ctx, vaobj, buffer, false);
1286 }
1287 
1288 
1289 void GLAPIENTRY
_mesa_GetVertexArrayiv(GLuint vaobj,GLenum pname,GLint * param)1290 _mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param)
1291 {
1292    GET_CURRENT_CONTEXT(ctx);
1293    struct gl_vertex_array_object *vao;
1294 
1295    ASSERT_OUTSIDE_BEGIN_END(ctx);
1296 
1297    /* The GL_ARB_direct_state_access specification says:
1298     *
1299     *   "An INVALID_OPERATION error is generated if <vaobj> is not
1300     *    [compatibility profile: zero or] the name of an existing
1301     *    vertex array object."
1302     */
1303    vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayiv");
1304    if (!vao)
1305       return;
1306 
1307    /* The GL_ARB_direct_state_access specification says:
1308     *
1309     *   "An INVALID_ENUM error is generated if <pname> is not
1310     *    ELEMENT_ARRAY_BUFFER_BINDING."
1311     */
1312    if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
1313       _mesa_error(ctx, GL_INVALID_ENUM,
1314                   "glGetVertexArrayiv(pname != "
1315                   "GL_ELEMENT_ARRAY_BUFFER_BINDING)");
1316       return;
1317    }
1318 
1319    param[0] = vao->IndexBufferObj ? vao->IndexBufferObj->Name : 0;
1320 }
1321