arrayobj.c revision 01e04c3f
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 array->Size = size; 389 array->Type = type; 390 array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */ 391 array->Stride = 0; 392 array->Ptr = NULL; 393 array->RelativeOffset = 0; 394 array->Enabled = GL_FALSE; 395 array->Normalized = GL_FALSE; 396 array->Integer = GL_FALSE; 397 array->Doubles = GL_FALSE; 398 array->_ElementSize = size * _mesa_sizeof_type(type); 399 ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex, 400 VERT_ATTRIB_MAX - 1); 401 array->BufferBindingIndex = index; 402 403 binding->Offset = 0; 404 binding->Stride = array->_ElementSize; 405 binding->BufferObj = NULL; 406 binding->_BoundArrays = BITFIELD_BIT(index); 407 408 /* Vertex array buffers */ 409 _mesa_reference_buffer_object(ctx, &binding->BufferObj, 410 ctx->Shared->NullBufferObj); 411} 412 413 414/** 415 * Initialize a gl_vertex_array_object's arrays. 416 */ 417void 418_mesa_initialize_vao(struct gl_context *ctx, 419 struct gl_vertex_array_object *vao, 420 GLuint name) 421{ 422 GLuint i; 423 424 vao->Name = name; 425 426 vao->RefCount = 1; 427 vao->SharedAndImmutable = false; 428 429 /* Init the individual arrays */ 430 for (i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) { 431 switch (i) { 432 case VERT_ATTRIB_NORMAL: 433 init_array(ctx, vao, VERT_ATTRIB_NORMAL, 3, GL_FLOAT); 434 break; 435 case VERT_ATTRIB_COLOR1: 436 init_array(ctx, vao, VERT_ATTRIB_COLOR1, 3, GL_FLOAT); 437 break; 438 case VERT_ATTRIB_FOG: 439 init_array(ctx, vao, VERT_ATTRIB_FOG, 1, GL_FLOAT); 440 break; 441 case VERT_ATTRIB_COLOR_INDEX: 442 init_array(ctx, vao, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT); 443 break; 444 case VERT_ATTRIB_EDGEFLAG: 445 init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL); 446 break; 447 case VERT_ATTRIB_POINT_SIZE: 448 init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT); 449 break; 450 default: 451 init_array(ctx, vao, i, 4, GL_FLOAT); 452 break; 453 } 454 } 455 456 vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY; 457 458 _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, 459 ctx->Shared->NullBufferObj); 460} 461 462 463/** 464 * Compute the offset range for the provided binding. 465 * 466 * This is a helper function for the below. 467 */ 468static void 469compute_vbo_offset_range(const struct gl_vertex_array_object *vao, 470 const struct gl_vertex_buffer_binding *binding, 471 GLsizeiptr* min, GLsizeiptr* max) 472{ 473 /* The function is meant to work on VBO bindings */ 474 assert(_mesa_is_bufferobj(binding->BufferObj)); 475 476 /* Start with an inverted range of relative offsets. */ 477 GLuint min_offset = ~(GLuint)0; 478 GLuint max_offset = 0; 479 480 /* We work on the unmapped originaly VAO array entries. */ 481 GLbitfield mask = vao->_Enabled & binding->_BoundArrays; 482 /* The binding should be active somehow, not to return inverted ranges */ 483 assert(mask); 484 while (mask) { 485 const int i = u_bit_scan(&mask); 486 const GLuint off = vao->VertexAttrib[i].RelativeOffset; 487 min_offset = MIN2(off, min_offset); 488 max_offset = MAX2(off, max_offset); 489 } 490 491 *min = binding->Offset + (GLsizeiptr)min_offset; 492 *max = binding->Offset + (GLsizeiptr)max_offset; 493} 494 495 496/** 497 * Update the unique binding and pos/generic0 map tracking in the vao. 498 * 499 * The idea is to build up information in the vao so that a consuming 500 * backend can execute the following to set up buffer and vertex element 501 * information: 502 * 503 * const GLbitfield inputs_read = VERT_BIT_ALL; // backend vp inputs 504 * 505 * // Attribute data is in a VBO. 506 * GLbitfield vbomask = inputs_read & _mesa_draw_vbo_array_bits(ctx); 507 * while (vbomask) { 508 * // The attribute index to start pulling a binding 509 * const gl_vert_attrib i = ffs(vbomask) - 1; 510 * const struct gl_vertex_buffer_binding *const binding 511 * = _mesa_draw_buffer_binding(vao, i); 512 * 513 * <insert code to handle the vertex buffer object at binding> 514 * 515 * const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding); 516 * GLbitfield attrmask = vbomask & boundmask; 517 * assert(attrmask); 518 * // Walk attributes belonging to the binding 519 * while (attrmask) { 520 * const gl_vert_attrib attr = u_bit_scan(&attrmask); 521 * const struct gl_array_attributes *const attrib 522 * = _mesa_draw_array_attrib(vao, attr); 523 * 524 * <insert code to handle the vertex element refering to the binding> 525 * } 526 * vbomask &= ~boundmask; 527 * } 528 * 529 * // Process user space buffers 530 * GLbitfield usermask = inputs_read & _mesa_draw_user_array_bits(ctx); 531 * while (usermask) { 532 * // The attribute index to start pulling a binding 533 * const gl_vert_attrib i = ffs(usermask) - 1; 534 * const struct gl_vertex_buffer_binding *const binding 535 * = _mesa_draw_buffer_binding(vao, i); 536 * 537 * <insert code to handle a set of interleaved user space arrays at binding> 538 * 539 * const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding); 540 * GLbitfield attrmask = usermask & boundmask; 541 * assert(attrmask); 542 * // Walk interleaved attributes with a common stride and instance divisor 543 * while (attrmask) { 544 * const gl_vert_attrib attr = u_bit_scan(&attrmask); 545 * const struct gl_array_attributes *const attrib 546 * = _mesa_draw_array_attrib(vao, attr); 547 * 548 * <insert code to handle non vbo vertex arrays> 549 * } 550 * usermask &= ~boundmask; 551 * } 552 * 553 * // Process values that should have better been uniforms in the application 554 * GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx); 555 * while (curmask) { 556 * const gl_vert_attrib attr = u_bit_scan(&curmask); 557 * const struct gl_array_attributes *const attrib 558 * = _mesa_draw_current_attrib(ctx, attr); 559 * 560 * <insert code to handle current values> 561 * } 562 * 563 * 564 * Note that the scan below must not incoporate any context state. 565 * The rationale is that once a VAO is finalized it should not 566 * be touched anymore. That means, do not incorporate the 567 * gl_context::Array._DrawVAOEnabledAttribs bitmask into this scan. 568 * A backend driver may further reduce the handled vertex processing 569 * inputs based on their vertex shader inputs. But scanning for 570 * collapsable binding points to reduce relocs is done based on the 571 * enabled arrays. 572 * Also VAOs may be shared between contexts due to their use in dlists 573 * thus no context state should bleed into the VAO. 574 */ 575void 576_mesa_update_vao_derived_arrays(struct gl_context *ctx, 577 struct gl_vertex_array_object *vao) 578{ 579 /* Make sure we do not run into problems with shared objects */ 580 assert(!vao->SharedAndImmutable || vao->NewArrays == 0); 581 582 /* Limit used for common binding scanning below. */ 583 const GLsizeiptr MaxRelativeOffset = 584 ctx->Const.MaxVertexAttribRelativeOffset; 585 586 /* The gl_vertex_array_object::_AttributeMapMode denotes the way 587 * VERT_ATTRIB_{POS,GENERIC0} mapping is done. 588 * 589 * This mapping is used to map between the OpenGL api visible 590 * VERT_ATTRIB_* arrays to mesa driver arrayinputs or shader inputs. 591 * The mapping only depends on the enabled bits of the 592 * VERT_ATTRIB_{POS,GENERIC0} arrays and is tracked in the VAO. 593 * 594 * This map needs to be applied when finally translating to the bitmasks 595 * as consumed by the driver backends. The duplicate scanning is here 596 * can as well be done in the OpenGL API numbering without this map. 597 */ 598 const gl_attribute_map_mode mode = vao->_AttributeMapMode; 599 /* Enabled array bits. */ 600 const GLbitfield enabled = vao->_Enabled; 601 /* VBO array bits. */ 602 const GLbitfield vbos = vao->VertexAttribBufferMask; 603 604 /* Compute and store effectively enabled and mapped vbo arrays */ 605 vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos); 606 /* Walk those enabled arrays that have a real vbo attached */ 607 GLbitfield mask = enabled; 608 while (mask) { 609 /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */ 610 const int i = ffs(mask) - 1; 611 /* The binding from the first to be processed attribute. */ 612 const GLuint bindex = vao->VertexAttrib[i].BufferBindingIndex; 613 struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex]; 614 615 /* The scan goes different for user space arrays than vbos */ 616 if (_mesa_is_bufferobj(binding->BufferObj)) { 617 /* The bound arrays. */ 618 const GLbitfield bound = enabled & binding->_BoundArrays; 619 620 /* Start this current effective binding with the actual bound arrays */ 621 GLbitfield eff_bound_arrays = bound; 622 623 /* 624 * If there is nothing left to scan just update the effective binding 625 * information. If the VAO is already only using a single binding point 626 * we end up here. So the overhead of this scan for an application 627 * carefully preparing the VAO for draw is low. 628 */ 629 630 GLbitfield scanmask = mask & vbos & ~bound; 631 /* Is there something left to scan? */ 632 if (scanmask == 0) { 633 /* Just update the back reference from the attrib to the binding and 634 * the effective offset. 635 */ 636 GLbitfield attrmask = eff_bound_arrays; 637 while (attrmask) { 638 const int j = u_bit_scan(&attrmask); 639 struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 640 641 /* Update the index into the common binding point and offset */ 642 attrib2->_EffBufferBindingIndex = bindex; 643 attrib2->_EffRelativeOffset = attrib2->RelativeOffset; 644 assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset); 645 646 /* Only enabled arrays shall appear in the unique bindings */ 647 assert(attrib2->Enabled); 648 } 649 /* Finally this is the set of effectively bound arrays with the 650 * original binding offset. 651 */ 652 binding->_EffOffset = binding->Offset; 653 /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 654 binding->_EffBoundArrays = 655 _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 656 657 } else { 658 /* In the VBO case, scan for attribute/binding 659 * combinations with relative bindings in the range of 660 * [0, ctx->Const.MaxVertexAttribRelativeOffset]. 661 * Note that this does also go beyond just interleaved arrays 662 * as long as they use the same VBO, binding parameters and the 663 * offsets stay within bounds that the backend still can handle. 664 */ 665 666 GLsizeiptr min_offset, max_offset; 667 compute_vbo_offset_range(vao, binding, &min_offset, &max_offset); 668 assert(max_offset <= min_offset + MaxRelativeOffset); 669 670 /* Now scan. */ 671 while (scanmask) { 672 /* Do not use u_bit_scan as we can walk multiple 673 * attrib arrays at once 674 */ 675 const int j = ffs(scanmask) - 1; 676 const struct gl_array_attributes *attrib2 = 677 &vao->VertexAttrib[j]; 678 const struct gl_vertex_buffer_binding *binding2 = 679 &vao->BufferBinding[attrib2->BufferBindingIndex]; 680 681 /* Remove those attrib bits from the mask that are bound to the 682 * same effective binding point. 683 */ 684 const GLbitfield bound2 = enabled & binding2->_BoundArrays; 685 scanmask &= ~bound2; 686 687 /* Check if we have an identical binding */ 688 if (binding->Stride != binding2->Stride) 689 continue; 690 if (binding->InstanceDivisor != binding2->InstanceDivisor) 691 continue; 692 if (binding->BufferObj != binding2->BufferObj) 693 continue; 694 /* Check if we can fold both bindings into a common binding */ 695 GLsizeiptr min_offset2, max_offset2; 696 compute_vbo_offset_range(vao, binding2, 697 &min_offset2, &max_offset2); 698 /* If the relative offset is within the limits ... */ 699 if (min_offset + MaxRelativeOffset < max_offset2) 700 continue; 701 if (min_offset2 + MaxRelativeOffset < max_offset) 702 continue; 703 /* ... add this array to the effective binding */ 704 eff_bound_arrays |= bound2; 705 min_offset = MIN2(min_offset, min_offset2); 706 max_offset = MAX2(max_offset, max_offset2); 707 assert(max_offset <= min_offset + MaxRelativeOffset); 708 } 709 710 /* Update the back reference from the attrib to the binding */ 711 GLbitfield attrmask = eff_bound_arrays; 712 while (attrmask) { 713 const int j = u_bit_scan(&attrmask); 714 struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 715 const struct gl_vertex_buffer_binding *binding2 = 716 &vao->BufferBinding[attrib2->BufferBindingIndex]; 717 718 /* Update the index into the common binding point and offset */ 719 attrib2->_EffBufferBindingIndex = bindex; 720 attrib2->_EffRelativeOffset = 721 binding2->Offset + attrib2->RelativeOffset - min_offset; 722 assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset); 723 724 /* Only enabled arrays shall appear in the unique bindings */ 725 assert(attrib2->Enabled); 726 } 727 /* Finally this is the set of effectively bound arrays */ 728 binding->_EffOffset = min_offset; 729 /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 730 binding->_EffBoundArrays = 731 _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 732 } 733 734 /* Mark all the effective bound arrays as processed. */ 735 mask &= ~eff_bound_arrays; 736 737 } else { 738 /* Scanning of common bindings for user space arrays. 739 */ 740 741 const struct gl_array_attributes *attrib = &vao->VertexAttrib[i]; 742 const GLbitfield bound = VERT_BIT(i); 743 744 /* Note that user space array pointers can only happen using a one 745 * to one binding point to array mapping. 746 * The OpenGL 4.x/ARB_vertex_attrib_binding api does not support 747 * user space arrays collected at multiple binding points. 748 * The only provider of user space interleaved arrays with a single 749 * binding point is the mesa internal vbo module. But that one 750 * provides a perfect interleaved set of arrays. 751 * 752 * If this would not be true we would potentially get attribute arrays 753 * with user space pointers that may not lie within the 754 * MaxRelativeOffset range but still attached to a single binding. 755 * Then we would need to store the effective attribute and binding 756 * grouping information in a seperate array beside 757 * gl_array_attributes/gl_vertex_buffer_binding. 758 */ 759 assert(util_bitcount(binding->_BoundArrays & vao->_Enabled) == 1 760 || (vao->_Enabled & ~binding->_BoundArrays) == 0); 761 762 /* Start this current effective binding with the array */ 763 GLbitfield eff_bound_arrays = bound; 764 765 const GLubyte *ptr = attrib->Ptr; 766 unsigned vertex_end = attrib->_ElementSize; 767 768 /* Walk other user space arrays and see which are interleaved 769 * using the same binding parameters. 770 */ 771 GLbitfield scanmask = mask & ~vbos & ~bound; 772 while (scanmask) { 773 const int j = u_bit_scan(&scanmask); 774 const struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 775 const struct gl_vertex_buffer_binding *binding2 = 776 &vao->BufferBinding[attrib2->BufferBindingIndex]; 777 778 /* See the comment at the same assert above. */ 779 assert(util_bitcount(binding2->_BoundArrays & vao->_Enabled) == 1 780 || (vao->_Enabled & ~binding->_BoundArrays) == 0); 781 782 /* Check if we have an identical binding */ 783 if (binding->Stride != binding2->Stride) 784 continue; 785 if (binding->InstanceDivisor != binding2->InstanceDivisor) 786 continue; 787 if (ptr <= attrib2->Ptr) { 788 if (ptr + binding->Stride < attrib2->Ptr + attrib2->_ElementSize) 789 continue; 790 unsigned end = attrib2->Ptr + attrib2->_ElementSize - ptr; 791 vertex_end = MAX2(vertex_end, end); 792 } else { 793 if (attrib2->Ptr + binding->Stride < ptr + vertex_end) 794 continue; 795 vertex_end += (GLsizei)(ptr - attrib2->Ptr); 796 ptr = attrib2->Ptr; 797 } 798 799 /* User space buffer object */ 800 assert(!_mesa_is_bufferobj(binding2->BufferObj)); 801 802 eff_bound_arrays |= VERT_BIT(j); 803 } 804 805 /* Update the back reference from the attrib to the binding */ 806 GLbitfield attrmask = eff_bound_arrays; 807 while (attrmask) { 808 const int j = u_bit_scan(&attrmask); 809 struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 810 811 /* Update the index into the common binding point and the offset */ 812 attrib2->_EffBufferBindingIndex = bindex; 813 attrib2->_EffRelativeOffset = attrib2->Ptr - ptr; 814 assert(attrib2->_EffRelativeOffset <= binding->Stride); 815 816 /* Only enabled arrays shall appear in the unique bindings */ 817 assert(attrib2->Enabled); 818 } 819 /* Finally this is the set of effectively bound arrays */ 820 binding->_EffOffset = (GLintptr)ptr; 821 /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 822 binding->_EffBoundArrays = 823 _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 824 825 /* Mark all the effective bound arrays as processed. */ 826 mask &= ~eff_bound_arrays; 827 } 828 } 829 830#ifndef NDEBUG 831 /* Make sure the above code works as expected. */ 832 for (gl_vert_attrib attr = 0; attr < VERT_ATTRIB_MAX; ++attr) { 833 /* Query the original api defined attrib/binding information ... */ 834 const unsigned char *const map =_mesa_vao_attribute_map[mode]; 835 const struct gl_array_attributes *attrib = &vao->VertexAttrib[map[attr]]; 836 if (attrib->Enabled) { 837 const struct gl_vertex_buffer_binding *binding = 838 &vao->BufferBinding[attrib->BufferBindingIndex]; 839 /* ... and compare that with the computed attrib/binding */ 840 const struct gl_vertex_buffer_binding *binding2 = 841 &vao->BufferBinding[attrib->_EffBufferBindingIndex]; 842 assert(binding->Stride == binding2->Stride); 843 assert(binding->InstanceDivisor == binding2->InstanceDivisor); 844 assert(binding->BufferObj == binding2->BufferObj); 845 if (_mesa_is_bufferobj(binding->BufferObj)) { 846 assert(attrib->_EffRelativeOffset <= MaxRelativeOffset); 847 assert(binding->Offset + attrib->RelativeOffset == 848 binding2->_EffOffset + attrib->_EffRelativeOffset); 849 } else { 850 assert(attrib->_EffRelativeOffset < binding->Stride); 851 assert((GLintptr)attrib->Ptr == 852 binding2->_EffOffset + attrib->_EffRelativeOffset); 853 } 854 } 855 } 856#endif 857} 858 859 860void 861_mesa_set_vao_immutable(struct gl_context *ctx, 862 struct gl_vertex_array_object *vao) 863{ 864 _mesa_update_vao_derived_arrays(ctx, vao); 865 vao->NewArrays = 0; 866 vao->SharedAndImmutable = true; 867} 868 869 870bool 871_mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao) 872{ 873 /* Walk those enabled arrays that have the default vbo attached */ 874 GLbitfield mask = vao->_Enabled & ~vao->VertexAttribBufferMask; 875 876 while (mask) { 877 /* Do not use u_bit_scan64 as we can walk multiple 878 * attrib arrays at once 879 */ 880 const int i = ffs(mask) - 1; 881 const struct gl_array_attributes *attrib_array = 882 &vao->VertexAttrib[i]; 883 const struct gl_vertex_buffer_binding *buffer_binding = 884 &vao->BufferBinding[attrib_array->BufferBindingIndex]; 885 886 /* Only enabled arrays shall appear in the _Enabled bitmask */ 887 assert(attrib_array->Enabled); 888 /* We have already masked out vao->VertexAttribBufferMask */ 889 assert(!_mesa_is_bufferobj(buffer_binding->BufferObj)); 890 891 /* Bail out once we find the first non vbo with a non zero stride */ 892 if (buffer_binding->Stride != 0) 893 return false; 894 895 /* Note that we cannot use the xor variant since the _BoundArray mask 896 * may contain array attributes that are bound but not enabled. 897 */ 898 mask &= ~buffer_binding->_BoundArrays; 899 } 900 901 return true; 902} 903 904bool 905_mesa_all_buffers_are_unmapped(const struct gl_vertex_array_object *vao) 906{ 907 /* Walk the enabled arrays that have a vbo attached */ 908 GLbitfield mask = vao->_Enabled & vao->VertexAttribBufferMask; 909 910 while (mask) { 911 const int i = ffs(mask) - 1; 912 const struct gl_array_attributes *attrib_array = 913 &vao->VertexAttrib[i]; 914 const struct gl_vertex_buffer_binding *buffer_binding = 915 &vao->BufferBinding[attrib_array->BufferBindingIndex]; 916 917 /* Only enabled arrays shall appear in the _Enabled bitmask */ 918 assert(attrib_array->Enabled); 919 /* We have already masked with vao->VertexAttribBufferMask */ 920 assert(_mesa_is_bufferobj(buffer_binding->BufferObj)); 921 922 /* Bail out once we find the first disallowed mapping */ 923 if (_mesa_check_disallowed_mapping(buffer_binding->BufferObj)) 924 return false; 925 926 /* We have handled everything that is bound to this buffer_binding. */ 927 mask &= ~buffer_binding->_BoundArrays; 928 } 929 930 return true; 931} 932 933/**********************************************************************/ 934/* API Functions */ 935/**********************************************************************/ 936 937 938/** 939 * ARB version of glBindVertexArray() 940 */ 941static ALWAYS_INLINE void 942bind_vertex_array(struct gl_context *ctx, GLuint id, bool no_error) 943{ 944 struct gl_vertex_array_object *const oldObj = ctx->Array.VAO; 945 struct gl_vertex_array_object *newObj = NULL; 946 947 assert(oldObj != NULL); 948 949 if (oldObj->Name == id) 950 return; /* rebinding the same array object- no change */ 951 952 /* 953 * Get pointer to new array object (newObj) 954 */ 955 if (id == 0) { 956 /* The spec says there is no array object named 0, but we use 957 * one internally because it simplifies things. 958 */ 959 newObj = ctx->Array.DefaultVAO; 960 } 961 else { 962 /* non-default array object */ 963 newObj = _mesa_lookup_vao(ctx, id); 964 if (!no_error && !newObj) { 965 _mesa_error(ctx, GL_INVALID_OPERATION, 966 "glBindVertexArray(non-gen name)"); 967 return; 968 } 969 970 newObj->EverBound = GL_TRUE; 971 } 972 973 /* The _DrawArrays pointer is pointing at the VAO being unbound and 974 * that VAO may be in the process of being deleted. If it's not going 975 * to be deleted, this will have no effect, because the pointer needs 976 * to be updated by the VBO module anyway. 977 * 978 * Before the VBO module can update the pointer, we have to set it 979 * to NULL for drivers not to set up arrays which are not bound, 980 * or to prevent a crash if the VAO being unbound is going to be 981 * deleted. 982 */ 983 _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0); 984 985 ctx->NewState |= _NEW_ARRAY; 986 _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj); 987} 988 989 990void GLAPIENTRY 991_mesa_BindVertexArray_no_error(GLuint id) 992{ 993 GET_CURRENT_CONTEXT(ctx); 994 bind_vertex_array(ctx, id, true); 995} 996 997 998void GLAPIENTRY 999_mesa_BindVertexArray(GLuint id) 1000{ 1001 GET_CURRENT_CONTEXT(ctx); 1002 bind_vertex_array(ctx, id, false); 1003} 1004 1005 1006/** 1007 * Delete a set of array objects. 1008 * 1009 * \param n Number of array objects to delete. 1010 * \param ids Array of \c n array object IDs. 1011 */ 1012static void 1013delete_vertex_arrays(struct gl_context *ctx, GLsizei n, const GLuint *ids) 1014{ 1015 GLsizei i; 1016 1017 for (i = 0; i < n; i++) { 1018 /* IDs equal to 0 should be silently ignored. */ 1019 if (!ids[i]) 1020 continue; 1021 1022 struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]); 1023 1024 if (obj) { 1025 assert(obj->Name == ids[i]); 1026 1027 /* If the array object is currently bound, the spec says "the binding 1028 * for that object reverts to zero and the default vertex array 1029 * becomes current." 1030 */ 1031 if (obj == ctx->Array.VAO) 1032 _mesa_BindVertexArray_no_error(0); 1033 1034 /* The ID is immediately freed for re-use */ 1035 _mesa_HashRemoveLocked(ctx->Array.Objects, obj->Name); 1036 1037 if (ctx->Array.LastLookedUpVAO == obj) 1038 _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL); 1039 if (ctx->Array._DrawVAO == obj) 1040 _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0); 1041 1042 /* Unreference the array object. 1043 * If refcount hits zero, the object will be deleted. 1044 */ 1045 _mesa_reference_vao(ctx, &obj, NULL); 1046 } 1047 } 1048} 1049 1050 1051void GLAPIENTRY 1052_mesa_DeleteVertexArrays_no_error(GLsizei n, const GLuint *ids) 1053{ 1054 GET_CURRENT_CONTEXT(ctx); 1055 delete_vertex_arrays(ctx, n, ids); 1056} 1057 1058 1059void GLAPIENTRY 1060_mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids) 1061{ 1062 GET_CURRENT_CONTEXT(ctx); 1063 1064 if (n < 0) { 1065 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)"); 1066 return; 1067 } 1068 1069 delete_vertex_arrays(ctx, n, ids); 1070} 1071 1072 1073/** 1074 * Generate a set of unique array object IDs and store them in \c arrays. 1075 * Helper for _mesa_GenVertexArrays() and _mesa_CreateVertexArrays() 1076 * below. 1077 * 1078 * \param n Number of IDs to generate. 1079 * \param arrays Array of \c n locations to store the IDs. 1080 * \param create Indicates that the objects should also be created. 1081 * \param func The name of the GL entry point. 1082 */ 1083static void 1084gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays, 1085 bool create, const char *func) 1086{ 1087 GLuint first; 1088 GLint i; 1089 1090 if (!arrays) 1091 return; 1092 1093 first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); 1094 1095 /* For the sake of simplicity we create the array objects in both 1096 * the Gen* and Create* cases. The only difference is the value of 1097 * EverBound, which is set to true in the Create* case. 1098 */ 1099 for (i = 0; i < n; i++) { 1100 struct gl_vertex_array_object *obj; 1101 GLuint name = first + i; 1102 1103 obj = _mesa_new_vao(ctx, name); 1104 if (!obj) { 1105 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 1106 return; 1107 } 1108 obj->EverBound = create; 1109 _mesa_HashInsertLocked(ctx->Array.Objects, obj->Name, obj); 1110 arrays[i] = first + i; 1111 } 1112} 1113 1114 1115static void 1116gen_vertex_arrays_err(struct gl_context *ctx, GLsizei n, GLuint *arrays, 1117 bool create, const char *func) 1118{ 1119 if (n < 0) { 1120 _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); 1121 return; 1122 } 1123 1124 gen_vertex_arrays(ctx, n, arrays, create, func); 1125} 1126 1127 1128/** 1129 * ARB version of glGenVertexArrays() 1130 * All arrays will be required to live in VBOs. 1131 */ 1132void GLAPIENTRY 1133_mesa_GenVertexArrays_no_error(GLsizei n, GLuint *arrays) 1134{ 1135 GET_CURRENT_CONTEXT(ctx); 1136 gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays"); 1137} 1138 1139 1140void GLAPIENTRY 1141_mesa_GenVertexArrays(GLsizei n, GLuint *arrays) 1142{ 1143 GET_CURRENT_CONTEXT(ctx); 1144 gen_vertex_arrays_err(ctx, n, arrays, false, "glGenVertexArrays"); 1145} 1146 1147 1148/** 1149 * ARB_direct_state_access 1150 * Generates ID's and creates the array objects. 1151 */ 1152void GLAPIENTRY 1153_mesa_CreateVertexArrays_no_error(GLsizei n, GLuint *arrays) 1154{ 1155 GET_CURRENT_CONTEXT(ctx); 1156 gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays"); 1157} 1158 1159 1160void GLAPIENTRY 1161_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays) 1162{ 1163 GET_CURRENT_CONTEXT(ctx); 1164 gen_vertex_arrays_err(ctx, n, arrays, true, "glCreateVertexArrays"); 1165} 1166 1167 1168/** 1169 * Determine if ID is the name of an array object. 1170 * 1171 * \param id ID of the potential array object. 1172 * \return \c GL_TRUE if \c id is the name of a array object, 1173 * \c GL_FALSE otherwise. 1174 */ 1175GLboolean GLAPIENTRY 1176_mesa_IsVertexArray( GLuint id ) 1177{ 1178 struct gl_vertex_array_object * obj; 1179 GET_CURRENT_CONTEXT(ctx); 1180 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1181 1182 obj = _mesa_lookup_vao(ctx, id); 1183 1184 return obj != NULL && obj->EverBound; 1185} 1186 1187 1188/** 1189 * Sets the element array buffer binding of a vertex array object. 1190 * 1191 * This is the ARB_direct_state_access equivalent of 1192 * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer). 1193 */ 1194static ALWAYS_INLINE void 1195vertex_array_element_buffer(struct gl_context *ctx, GLuint vaobj, GLuint buffer, 1196 bool no_error) 1197{ 1198 struct gl_vertex_array_object *vao; 1199 struct gl_buffer_object *bufObj; 1200 1201 ASSERT_OUTSIDE_BEGIN_END(ctx); 1202 1203 if (!no_error) { 1204 /* The GL_ARB_direct_state_access specification says: 1205 * 1206 * "An INVALID_OPERATION error is generated by 1207 * VertexArrayElementBuffer if <vaobj> is not [compatibility profile: 1208 * zero or] the name of an existing vertex array object." 1209 */ 1210 vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer"); 1211 if (!vao) 1212 return; 1213 } else { 1214 vao = _mesa_lookup_vao(ctx, vaobj); 1215 } 1216 1217 if (buffer != 0) { 1218 if (!no_error) { 1219 /* The GL_ARB_direct_state_access specification says: 1220 * 1221 * "An INVALID_OPERATION error is generated if <buffer> is not zero 1222 * or the name of an existing buffer object." 1223 */ 1224 bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 1225 "glVertexArrayElementBuffer"); 1226 } else { 1227 bufObj = _mesa_lookup_bufferobj(ctx, buffer); 1228 } 1229 } else { 1230 bufObj = ctx->Shared->NullBufferObj; 1231 } 1232 1233 if (bufObj) 1234 _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj); 1235} 1236 1237 1238void GLAPIENTRY 1239_mesa_VertexArrayElementBuffer_no_error(GLuint vaobj, GLuint buffer) 1240{ 1241 GET_CURRENT_CONTEXT(ctx); 1242 vertex_array_element_buffer(ctx, vaobj, buffer, true); 1243} 1244 1245 1246void GLAPIENTRY 1247_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer) 1248{ 1249 GET_CURRENT_CONTEXT(ctx); 1250 vertex_array_element_buffer(ctx, vaobj, buffer, false); 1251} 1252 1253 1254void GLAPIENTRY 1255_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param) 1256{ 1257 GET_CURRENT_CONTEXT(ctx); 1258 struct gl_vertex_array_object *vao; 1259 1260 ASSERT_OUTSIDE_BEGIN_END(ctx); 1261 1262 /* The GL_ARB_direct_state_access specification says: 1263 * 1264 * "An INVALID_OPERATION error is generated if <vaobj> is not 1265 * [compatibility profile: zero or] the name of an existing 1266 * vertex array object." 1267 */ 1268 vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv"); 1269 if (!vao) 1270 return; 1271 1272 /* The GL_ARB_direct_state_access specification says: 1273 * 1274 * "An INVALID_ENUM error is generated if <pname> is not 1275 * ELEMENT_ARRAY_BUFFER_BINDING." 1276 */ 1277 if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) { 1278 _mesa_error(ctx, GL_INVALID_ENUM, 1279 "glGetVertexArrayiv(pname != " 1280 "GL_ELEMENT_ARRAY_BUFFER_BINDING)"); 1281 return; 1282 } 1283 1284 param[0] = vao->IndexBufferObj->Name; 1285} 1286