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