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