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