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