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