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