1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * (C) Copyright IBM Corporation 2006 6848b8605Smrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 7848b8605Smrg * 8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9848b8605Smrg * copy of this software and associated documentation files (the "Software"), 10848b8605Smrg * to deal in the Software without restriction, including without limitation 11848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 13848b8605Smrg * Software is furnished to do so, subject to the following conditions: 14848b8605Smrg * 15848b8605Smrg * The above copyright notice and this permission notice shall be included 16848b8605Smrg * in all copies or substantial portions of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg */ 26848b8605Smrg 27848b8605Smrg 28848b8605Smrg/** 29848b8605Smrg * \file arrayobj.c 30848b8605Smrg * 31b8e80941Smrg * Implementation of Vertex Array Objects (VAOs), from OpenGL 3.1+ / 32b8e80941Smrg * the GL_ARB_vertex_array_object extension. 33848b8605Smrg * 34848b8605Smrg * \todo 35848b8605Smrg * The code in this file borrows a lot from bufferobj.c. There's a certain 36848b8605Smrg * amount of cruft left over from that origin that may be unnecessary. 37848b8605Smrg * 38848b8605Smrg * \author Ian Romanick <idr@us.ibm.com> 39848b8605Smrg * \author Brian Paul 40848b8605Smrg */ 41848b8605Smrg 42848b8605Smrg 43848b8605Smrg#include "glheader.h" 44848b8605Smrg#include "hash.h" 45848b8605Smrg#include "image.h" 46848b8605Smrg#include "imports.h" 47848b8605Smrg#include "context.h" 48848b8605Smrg#include "bufferobj.h" 49848b8605Smrg#include "arrayobj.h" 50848b8605Smrg#include "macros.h" 51848b8605Smrg#include "mtypes.h" 52b8e80941Smrg#include "state.h" 53848b8605Smrg#include "varray.h" 54b8e80941Smrg#include "util/bitscan.h" 55b8e80941Smrg#include "util/u_atomic.h" 56b8e80941Smrg#include "util/u_math.h" 57b8e80941Smrg 58b8e80941Smrg 59b8e80941Smrgconst GLubyte 60b8e80941Smrg_mesa_vao_attribute_map[ATTRIBUTE_MAP_MODE_MAX][VERT_ATTRIB_MAX] = 61b8e80941Smrg{ 62b8e80941Smrg /* ATTRIBUTE_MAP_MODE_IDENTITY 63b8e80941Smrg * 64b8e80941Smrg * Grab vertex processing attribute VERT_ATTRIB_POS from 65b8e80941Smrg * the VAO attribute VERT_ATTRIB_POS, and grab vertex processing 66b8e80941Smrg * attribute VERT_ATTRIB_GENERIC0 from the VAO attribute 67b8e80941Smrg * VERT_ATTRIB_GENERIC0. 68b8e80941Smrg */ 69b8e80941Smrg { 70b8e80941Smrg VERT_ATTRIB_POS, /* VERT_ATTRIB_POS */ 71b8e80941Smrg VERT_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 72b8e80941Smrg VERT_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 73b8e80941Smrg VERT_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 74b8e80941Smrg VERT_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 75b8e80941Smrg VERT_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 76b8e80941Smrg VERT_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 77b8e80941Smrg VERT_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 78b8e80941Smrg VERT_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 79b8e80941Smrg VERT_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 80b8e80941Smrg VERT_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 81b8e80941Smrg VERT_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 82b8e80941Smrg VERT_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 83b8e80941Smrg VERT_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 84b8e80941Smrg VERT_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 85b8e80941Smrg VERT_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 86b8e80941Smrg VERT_ATTRIB_GENERIC0, /* VERT_ATTRIB_GENERIC0 */ 87b8e80941Smrg VERT_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 88b8e80941Smrg VERT_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 89b8e80941Smrg VERT_ATTRIB_GENERIC3, /* VERT_ATTRIB_GENERIC3 */ 90b8e80941Smrg VERT_ATTRIB_GENERIC4, /* VERT_ATTRIB_GENERIC4 */ 91b8e80941Smrg VERT_ATTRIB_GENERIC5, /* VERT_ATTRIB_GENERIC5 */ 92b8e80941Smrg VERT_ATTRIB_GENERIC6, /* VERT_ATTRIB_GENERIC6 */ 93b8e80941Smrg VERT_ATTRIB_GENERIC7, /* VERT_ATTRIB_GENERIC7 */ 94b8e80941Smrg VERT_ATTRIB_GENERIC8, /* VERT_ATTRIB_GENERIC8 */ 95b8e80941Smrg VERT_ATTRIB_GENERIC9, /* VERT_ATTRIB_GENERIC9 */ 96b8e80941Smrg VERT_ATTRIB_GENERIC10, /* VERT_ATTRIB_GENERIC10 */ 97b8e80941Smrg VERT_ATTRIB_GENERIC11, /* VERT_ATTRIB_GENERIC11 */ 98b8e80941Smrg VERT_ATTRIB_GENERIC12, /* VERT_ATTRIB_GENERIC12 */ 99b8e80941Smrg VERT_ATTRIB_GENERIC13, /* VERT_ATTRIB_GENERIC13 */ 100b8e80941Smrg VERT_ATTRIB_GENERIC14, /* VERT_ATTRIB_GENERIC14 */ 101b8e80941Smrg VERT_ATTRIB_GENERIC15 /* VERT_ATTRIB_GENERIC15 */ 102b8e80941Smrg }, 103b8e80941Smrg 104b8e80941Smrg /* ATTRIBUTE_MAP_MODE_POSITION 105b8e80941Smrg * 106b8e80941Smrg * Grab vertex processing attribute VERT_ATTRIB_POS as well as 107b8e80941Smrg * vertex processing attribute VERT_ATTRIB_GENERIC0 from the 108b8e80941Smrg * VAO attribute VERT_ATTRIB_POS. 109b8e80941Smrg */ 110b8e80941Smrg { 111b8e80941Smrg VERT_ATTRIB_POS, /* VERT_ATTRIB_POS */ 112b8e80941Smrg VERT_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 113b8e80941Smrg VERT_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 114b8e80941Smrg VERT_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 115b8e80941Smrg VERT_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 116b8e80941Smrg VERT_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 117b8e80941Smrg VERT_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 118b8e80941Smrg VERT_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 119b8e80941Smrg VERT_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 120b8e80941Smrg VERT_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 121b8e80941Smrg VERT_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 122b8e80941Smrg VERT_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 123b8e80941Smrg VERT_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 124b8e80941Smrg VERT_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 125b8e80941Smrg VERT_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 126b8e80941Smrg VERT_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 127b8e80941Smrg VERT_ATTRIB_POS, /* VERT_ATTRIB_GENERIC0 */ 128b8e80941Smrg VERT_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 129b8e80941Smrg VERT_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 130b8e80941Smrg VERT_ATTRIB_GENERIC3, /* VERT_ATTRIB_GENERIC3 */ 131b8e80941Smrg VERT_ATTRIB_GENERIC4, /* VERT_ATTRIB_GENERIC4 */ 132b8e80941Smrg VERT_ATTRIB_GENERIC5, /* VERT_ATTRIB_GENERIC5 */ 133b8e80941Smrg VERT_ATTRIB_GENERIC6, /* VERT_ATTRIB_GENERIC6 */ 134b8e80941Smrg VERT_ATTRIB_GENERIC7, /* VERT_ATTRIB_GENERIC7 */ 135b8e80941Smrg VERT_ATTRIB_GENERIC8, /* VERT_ATTRIB_GENERIC8 */ 136b8e80941Smrg VERT_ATTRIB_GENERIC9, /* VERT_ATTRIB_GENERIC9 */ 137b8e80941Smrg VERT_ATTRIB_GENERIC10, /* VERT_ATTRIB_GENERIC10 */ 138b8e80941Smrg VERT_ATTRIB_GENERIC11, /* VERT_ATTRIB_GENERIC11 */ 139b8e80941Smrg VERT_ATTRIB_GENERIC12, /* VERT_ATTRIB_GENERIC12 */ 140b8e80941Smrg VERT_ATTRIB_GENERIC13, /* VERT_ATTRIB_GENERIC13 */ 141b8e80941Smrg VERT_ATTRIB_GENERIC14, /* VERT_ATTRIB_GENERIC14 */ 142b8e80941Smrg VERT_ATTRIB_GENERIC15 /* VERT_ATTRIB_GENERIC15 */ 143b8e80941Smrg }, 144b8e80941Smrg 145b8e80941Smrg /* ATTRIBUTE_MAP_MODE_GENERIC0 146b8e80941Smrg * 147b8e80941Smrg * Grab vertex processing attribute VERT_ATTRIB_POS as well as 148b8e80941Smrg * vertex processing attribute VERT_ATTRIB_GENERIC0 from the 149b8e80941Smrg * VAO attribute VERT_ATTRIB_GENERIC0. 150b8e80941Smrg */ 151b8e80941Smrg { 152b8e80941Smrg VERT_ATTRIB_GENERIC0, /* VERT_ATTRIB_POS */ 153b8e80941Smrg VERT_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 154b8e80941Smrg VERT_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 155b8e80941Smrg VERT_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 156b8e80941Smrg VERT_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 157b8e80941Smrg VERT_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 158b8e80941Smrg VERT_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 159b8e80941Smrg VERT_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 160b8e80941Smrg VERT_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 161b8e80941Smrg VERT_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 162b8e80941Smrg VERT_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 163b8e80941Smrg VERT_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 164b8e80941Smrg VERT_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 165b8e80941Smrg VERT_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 166b8e80941Smrg VERT_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 167b8e80941Smrg VERT_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 168b8e80941Smrg VERT_ATTRIB_GENERIC0, /* VERT_ATTRIB_GENERIC0 */ 169b8e80941Smrg VERT_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 170b8e80941Smrg VERT_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 171b8e80941Smrg VERT_ATTRIB_GENERIC3, /* VERT_ATTRIB_GENERIC3 */ 172b8e80941Smrg VERT_ATTRIB_GENERIC4, /* VERT_ATTRIB_GENERIC4 */ 173b8e80941Smrg VERT_ATTRIB_GENERIC5, /* VERT_ATTRIB_GENERIC5 */ 174b8e80941Smrg VERT_ATTRIB_GENERIC6, /* VERT_ATTRIB_GENERIC6 */ 175b8e80941Smrg VERT_ATTRIB_GENERIC7, /* VERT_ATTRIB_GENERIC7 */ 176b8e80941Smrg VERT_ATTRIB_GENERIC8, /* VERT_ATTRIB_GENERIC8 */ 177b8e80941Smrg VERT_ATTRIB_GENERIC9, /* VERT_ATTRIB_GENERIC9 */ 178b8e80941Smrg VERT_ATTRIB_GENERIC10, /* VERT_ATTRIB_GENERIC10 */ 179b8e80941Smrg VERT_ATTRIB_GENERIC11, /* VERT_ATTRIB_GENERIC11 */ 180b8e80941Smrg VERT_ATTRIB_GENERIC12, /* VERT_ATTRIB_GENERIC12 */ 181b8e80941Smrg VERT_ATTRIB_GENERIC13, /* VERT_ATTRIB_GENERIC13 */ 182b8e80941Smrg VERT_ATTRIB_GENERIC14, /* VERT_ATTRIB_GENERIC14 */ 183b8e80941Smrg VERT_ATTRIB_GENERIC15 /* VERT_ATTRIB_GENERIC15 */ 184b8e80941Smrg } 185b8e80941Smrg}; 186848b8605Smrg 187848b8605Smrg 188848b8605Smrg/** 189848b8605Smrg * Look up the array object for the given ID. 190848b8605Smrg * 191848b8605Smrg * \returns 192848b8605Smrg * Either a pointer to the array object with the specified ID or \c NULL for 193848b8605Smrg * a non-existent ID. The spec defines ID 0 as being technically 194848b8605Smrg * non-existent. 195848b8605Smrg */ 196848b8605Smrg 197848b8605Smrgstruct gl_vertex_array_object * 198848b8605Smrg_mesa_lookup_vao(struct gl_context *ctx, GLuint id) 199848b8605Smrg{ 200b8e80941Smrg /* The ARB_direct_state_access specification says: 201b8e80941Smrg * 202b8e80941Smrg * "<vaobj> is [compatibility profile: 203b8e80941Smrg * zero, indicating the default vertex array object, or] 204b8e80941Smrg * the name of the vertex array object." 205b8e80941Smrg */ 206b8e80941Smrg if (id == 0) { 207b8e80941Smrg if (ctx->API == API_OPENGL_COMPAT) 208b8e80941Smrg return ctx->Array.DefaultVAO; 209b8e80941Smrg 210848b8605Smrg return NULL; 211b8e80941Smrg } else { 212b8e80941Smrg struct gl_vertex_array_object *vao; 213b8e80941Smrg 214b8e80941Smrg if (ctx->Array.LastLookedUpVAO && 215b8e80941Smrg ctx->Array.LastLookedUpVAO->Name == id) { 216b8e80941Smrg vao = ctx->Array.LastLookedUpVAO; 217b8e80941Smrg } else { 218b8e80941Smrg vao = (struct gl_vertex_array_object *) 219b8e80941Smrg _mesa_HashLookupLocked(ctx->Array.Objects, id); 220b8e80941Smrg 221b8e80941Smrg _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao); 222b8e80941Smrg } 223b8e80941Smrg 224b8e80941Smrg return vao; 225b8e80941Smrg } 226b8e80941Smrg} 227b8e80941Smrg 228b8e80941Smrg 229b8e80941Smrg/** 230b8e80941Smrg * Looks up the array object for the given ID. 231b8e80941Smrg * 232b8e80941Smrg * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION 233b8e80941Smrg * error if the array object does not exist. It also returns the default 234b8e80941Smrg * array object when ctx is a compatibility profile context and id is zero. 235b8e80941Smrg */ 236b8e80941Smrgstruct gl_vertex_array_object * 237b8e80941Smrg_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller) 238b8e80941Smrg{ 239b8e80941Smrg /* The ARB_direct_state_access specification says: 240b8e80941Smrg * 241b8e80941Smrg * "<vaobj> is [compatibility profile: 242b8e80941Smrg * zero, indicating the default vertex array object, or] 243b8e80941Smrg * the name of the vertex array object." 244b8e80941Smrg */ 245b8e80941Smrg if (id == 0) { 246b8e80941Smrg if (ctx->API == API_OPENGL_CORE) { 247b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 248b8e80941Smrg "%s(zero is not valid vaobj name in a core profile " 249b8e80941Smrg "context)", caller); 250b8e80941Smrg return NULL; 251b8e80941Smrg } 252b8e80941Smrg 253b8e80941Smrg return ctx->Array.DefaultVAO; 254b8e80941Smrg } else { 255b8e80941Smrg struct gl_vertex_array_object *vao; 256b8e80941Smrg 257b8e80941Smrg if (ctx->Array.LastLookedUpVAO && 258b8e80941Smrg ctx->Array.LastLookedUpVAO->Name == id) { 259b8e80941Smrg vao = ctx->Array.LastLookedUpVAO; 260b8e80941Smrg } else { 261b8e80941Smrg vao = (struct gl_vertex_array_object *) 262b8e80941Smrg _mesa_HashLookupLocked(ctx->Array.Objects, id); 263b8e80941Smrg 264b8e80941Smrg /* The ARB_direct_state_access specification says: 265b8e80941Smrg * 266b8e80941Smrg * "An INVALID_OPERATION error is generated if <vaobj> is not 267b8e80941Smrg * [compatibility profile: zero or] the name of an existing 268b8e80941Smrg * vertex array object." 269b8e80941Smrg */ 270b8e80941Smrg if (!vao || !vao->EverBound) { 271b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 272b8e80941Smrg "%s(non-existent vaobj=%u)", caller, id); 273b8e80941Smrg return NULL; 274b8e80941Smrg } 275b8e80941Smrg 276b8e80941Smrg _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao); 277b8e80941Smrg } 278b8e80941Smrg 279b8e80941Smrg return vao; 280b8e80941Smrg } 281848b8605Smrg} 282848b8605Smrg 283848b8605Smrg 284848b8605Smrg/** 285848b8605Smrg * For all the vertex binding points in the array object, unbind any pointers 286848b8605Smrg * to any buffer objects (VBOs). 287848b8605Smrg * This is done just prior to array object destruction. 288848b8605Smrg */ 289848b8605Smrgstatic void 290848b8605Smrgunbind_array_object_vbos(struct gl_context *ctx, struct gl_vertex_array_object *obj) 291848b8605Smrg{ 292848b8605Smrg GLuint i; 293848b8605Smrg 294b8e80941Smrg for (i = 0; i < ARRAY_SIZE(obj->BufferBinding); i++) 295b8e80941Smrg _mesa_reference_buffer_object(ctx, &obj->BufferBinding[i].BufferObj, NULL); 296848b8605Smrg} 297848b8605Smrg 298848b8605Smrg 299848b8605Smrg/** 300848b8605Smrg * Allocate and initialize a new vertex array object. 301848b8605Smrg */ 302848b8605Smrgstruct gl_vertex_array_object * 303848b8605Smrg_mesa_new_vao(struct gl_context *ctx, GLuint name) 304848b8605Smrg{ 305848b8605Smrg struct gl_vertex_array_object *obj = CALLOC_STRUCT(gl_vertex_array_object); 306848b8605Smrg if (obj) 307848b8605Smrg _mesa_initialize_vao(ctx, obj, name); 308848b8605Smrg return obj; 309848b8605Smrg} 310848b8605Smrg 311848b8605Smrg 312848b8605Smrg/** 313848b8605Smrg * Delete an array object. 314848b8605Smrg */ 315848b8605Smrgvoid 316848b8605Smrg_mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj) 317848b8605Smrg{ 318848b8605Smrg unbind_array_object_vbos(ctx, obj); 319848b8605Smrg _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL); 320848b8605Smrg free(obj->Label); 321848b8605Smrg free(obj); 322848b8605Smrg} 323848b8605Smrg 324848b8605Smrg 325848b8605Smrg/** 326848b8605Smrg * Set ptr to vao w/ reference counting. 327848b8605Smrg * Note: this should only be called from the _mesa_reference_vao() 328848b8605Smrg * inline function. 329848b8605Smrg */ 330848b8605Smrgvoid 331848b8605Smrg_mesa_reference_vao_(struct gl_context *ctx, 332848b8605Smrg struct gl_vertex_array_object **ptr, 333848b8605Smrg struct gl_vertex_array_object *vao) 334848b8605Smrg{ 335848b8605Smrg assert(*ptr != vao); 336848b8605Smrg 337848b8605Smrg if (*ptr) { 338848b8605Smrg /* Unreference the old array object */ 339848b8605Smrg struct gl_vertex_array_object *oldObj = *ptr; 340848b8605Smrg 341b8e80941Smrg bool deleteFlag; 342b8e80941Smrg if (oldObj->SharedAndImmutable) { 343b8e80941Smrg deleteFlag = p_atomic_dec_zero(&oldObj->RefCount); 344b8e80941Smrg } else { 345b8e80941Smrg assert(oldObj->RefCount > 0); 346b8e80941Smrg oldObj->RefCount--; 347b8e80941Smrg deleteFlag = (oldObj->RefCount == 0); 348848b8605Smrg } 349848b8605Smrg 350b8e80941Smrg if (deleteFlag) 351b8e80941Smrg _mesa_delete_vao(ctx, oldObj); 352b8e80941Smrg 353848b8605Smrg *ptr = NULL; 354848b8605Smrg } 355b8e80941Smrg assert(!*ptr); 356848b8605Smrg 357848b8605Smrg if (vao) { 358848b8605Smrg /* reference new array object */ 359b8e80941Smrg if (vao->SharedAndImmutable) { 360b8e80941Smrg p_atomic_inc(&vao->RefCount); 361b8e80941Smrg } else { 362b8e80941Smrg assert(vao->RefCount > 0); 363848b8605Smrg vao->RefCount++; 364848b8605Smrg } 365b8e80941Smrg 366b8e80941Smrg *ptr = vao; 367848b8605Smrg } 368848b8605Smrg} 369848b8605Smrg 370848b8605Smrg 371b8e80941Smrg/** 372b8e80941Smrg * Initialize attributes of a vertex array within a vertex array object. 373b8e80941Smrg * \param vao the container vertex array object 374b8e80941Smrg * \param index which array in the VAO to initialize 375b8e80941Smrg * \param size number of components (1, 2, 3 or 4) per attribute 376b8e80941Smrg * \param type datatype of the attribute (GL_FLOAT, GL_INT, etc). 377b8e80941Smrg */ 378848b8605Smrgstatic void 379848b8605Smrginit_array(struct gl_context *ctx, 380b8e80941Smrg struct gl_vertex_array_object *vao, 381b8e80941Smrg gl_vert_attrib index, GLint size, GLint type) 382848b8605Smrg{ 383b8e80941Smrg assert(index < ARRAY_SIZE(vao->VertexAttrib)); 384b8e80941Smrg struct gl_array_attributes *array = &vao->VertexAttrib[index]; 385b8e80941Smrg assert(index < ARRAY_SIZE(vao->BufferBinding)); 386b8e80941Smrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index]; 387848b8605Smrg 388b8e80941Smrg _mesa_set_vertex_format(&array->Format, size, type, GL_RGBA, 389b8e80941Smrg GL_FALSE, GL_FALSE, GL_FALSE); 390848b8605Smrg array->Stride = 0; 391848b8605Smrg array->Ptr = NULL; 392848b8605Smrg array->RelativeOffset = 0; 393b8e80941Smrg ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex, 394b8e80941Smrg VERT_ATTRIB_MAX - 1); 395b8e80941Smrg array->BufferBindingIndex = index; 396848b8605Smrg 397848b8605Smrg binding->Offset = 0; 398b8e80941Smrg binding->Stride = array->Format._ElementSize; 399848b8605Smrg binding->BufferObj = NULL; 400b8e80941Smrg binding->_BoundArrays = BITFIELD_BIT(index); 401848b8605Smrg 402848b8605Smrg /* Vertex array buffers */ 403848b8605Smrg _mesa_reference_buffer_object(ctx, &binding->BufferObj, 404848b8605Smrg ctx->Shared->NullBufferObj); 405848b8605Smrg} 406848b8605Smrg 407848b8605Smrg 408848b8605Smrg/** 409848b8605Smrg * Initialize a gl_vertex_array_object's arrays. 410848b8605Smrg */ 411848b8605Smrgvoid 412848b8605Smrg_mesa_initialize_vao(struct gl_context *ctx, 413b8e80941Smrg struct gl_vertex_array_object *vao, 414848b8605Smrg GLuint name) 415848b8605Smrg{ 416848b8605Smrg GLuint i; 417848b8605Smrg 418b8e80941Smrg vao->Name = name; 419848b8605Smrg 420b8e80941Smrg vao->RefCount = 1; 421b8e80941Smrg vao->SharedAndImmutable = false; 422848b8605Smrg 423848b8605Smrg /* Init the individual arrays */ 424b8e80941Smrg for (i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) { 425848b8605Smrg switch (i) { 426848b8605Smrg case VERT_ATTRIB_NORMAL: 427b8e80941Smrg init_array(ctx, vao, VERT_ATTRIB_NORMAL, 3, GL_FLOAT); 428848b8605Smrg break; 429848b8605Smrg case VERT_ATTRIB_COLOR1: 430b8e80941Smrg init_array(ctx, vao, VERT_ATTRIB_COLOR1, 3, GL_FLOAT); 431848b8605Smrg break; 432848b8605Smrg case VERT_ATTRIB_FOG: 433b8e80941Smrg init_array(ctx, vao, VERT_ATTRIB_FOG, 1, GL_FLOAT); 434848b8605Smrg break; 435848b8605Smrg case VERT_ATTRIB_COLOR_INDEX: 436b8e80941Smrg init_array(ctx, vao, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT); 437848b8605Smrg break; 438848b8605Smrg case VERT_ATTRIB_EDGEFLAG: 439b8e80941Smrg init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_UNSIGNED_BYTE); 440848b8605Smrg break; 441848b8605Smrg case VERT_ATTRIB_POINT_SIZE: 442b8e80941Smrg init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT); 443848b8605Smrg break; 444848b8605Smrg default: 445b8e80941Smrg init_array(ctx, vao, i, 4, GL_FLOAT); 446848b8605Smrg break; 447848b8605Smrg } 448848b8605Smrg } 449848b8605Smrg 450b8e80941Smrg vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY; 451b8e80941Smrg 452b8e80941Smrg _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, 453848b8605Smrg ctx->Shared->NullBufferObj); 454848b8605Smrg} 455848b8605Smrg 456848b8605Smrg 457848b8605Smrg/** 458b8e80941Smrg * Compute the offset range for the provided binding. 459b8e80941Smrg * 460b8e80941Smrg * This is a helper function for the below. 461848b8605Smrg */ 462848b8605Smrgstatic void 463b8e80941Smrgcompute_vbo_offset_range(const struct gl_vertex_array_object *vao, 464b8e80941Smrg const struct gl_vertex_buffer_binding *binding, 465b8e80941Smrg GLsizeiptr* min, GLsizeiptr* max) 466848b8605Smrg{ 467b8e80941Smrg /* The function is meant to work on VBO bindings */ 468b8e80941Smrg assert(_mesa_is_bufferobj(binding->BufferObj)); 469b8e80941Smrg 470b8e80941Smrg /* Start with an inverted range of relative offsets. */ 471b8e80941Smrg GLuint min_offset = ~(GLuint)0; 472b8e80941Smrg GLuint max_offset = 0; 473b8e80941Smrg 474b8e80941Smrg /* We work on the unmapped originaly VAO array entries. */ 475b8e80941Smrg GLbitfield mask = vao->Enabled & binding->_BoundArrays; 476b8e80941Smrg /* The binding should be active somehow, not to return inverted ranges */ 477b8e80941Smrg assert(mask); 478b8e80941Smrg while (mask) { 479b8e80941Smrg const int i = u_bit_scan(&mask); 480b8e80941Smrg const GLuint off = vao->VertexAttrib[i].RelativeOffset; 481b8e80941Smrg min_offset = MIN2(off, min_offset); 482b8e80941Smrg max_offset = MAX2(off, max_offset); 483848b8605Smrg } 484b8e80941Smrg 485b8e80941Smrg *min = binding->Offset + (GLsizeiptr)min_offset; 486b8e80941Smrg *max = binding->Offset + (GLsizeiptr)max_offset; 487848b8605Smrg} 488848b8605Smrg 489848b8605Smrg 490848b8605Smrg/** 491b8e80941Smrg * Update the unique binding and pos/generic0 map tracking in the vao. 492b8e80941Smrg * 493b8e80941Smrg * The idea is to build up information in the vao so that a consuming 494b8e80941Smrg * backend can execute the following to set up buffer and vertex element 495b8e80941Smrg * information: 496b8e80941Smrg * 497b8e80941Smrg * const GLbitfield inputs_read = VERT_BIT_ALL; // backend vp inputs 498b8e80941Smrg * 499b8e80941Smrg * // Attribute data is in a VBO. 500b8e80941Smrg * GLbitfield vbomask = inputs_read & _mesa_draw_vbo_array_bits(ctx); 501b8e80941Smrg * while (vbomask) { 502b8e80941Smrg * // The attribute index to start pulling a binding 503b8e80941Smrg * const gl_vert_attrib i = ffs(vbomask) - 1; 504b8e80941Smrg * const struct gl_vertex_buffer_binding *const binding 505b8e80941Smrg * = _mesa_draw_buffer_binding(vao, i); 506b8e80941Smrg * 507b8e80941Smrg * <insert code to handle the vertex buffer object at binding> 508b8e80941Smrg * 509b8e80941Smrg * const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding); 510b8e80941Smrg * GLbitfield attrmask = vbomask & boundmask; 511b8e80941Smrg * assert(attrmask); 512b8e80941Smrg * // Walk attributes belonging to the binding 513b8e80941Smrg * while (attrmask) { 514b8e80941Smrg * const gl_vert_attrib attr = u_bit_scan(&attrmask); 515b8e80941Smrg * const struct gl_array_attributes *const attrib 516b8e80941Smrg * = _mesa_draw_array_attrib(vao, attr); 517b8e80941Smrg * 518b8e80941Smrg * <insert code to handle the vertex element refering to the binding> 519b8e80941Smrg * } 520b8e80941Smrg * vbomask &= ~boundmask; 521b8e80941Smrg * } 522b8e80941Smrg * 523b8e80941Smrg * // Process user space buffers 524b8e80941Smrg * GLbitfield usermask = inputs_read & _mesa_draw_user_array_bits(ctx); 525b8e80941Smrg * while (usermask) { 526b8e80941Smrg * // The attribute index to start pulling a binding 527b8e80941Smrg * const gl_vert_attrib i = ffs(usermask) - 1; 528b8e80941Smrg * const struct gl_vertex_buffer_binding *const binding 529b8e80941Smrg * = _mesa_draw_buffer_binding(vao, i); 530b8e80941Smrg * 531b8e80941Smrg * <insert code to handle a set of interleaved user space arrays at binding> 532b8e80941Smrg * 533b8e80941Smrg * const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding); 534b8e80941Smrg * GLbitfield attrmask = usermask & boundmask; 535b8e80941Smrg * assert(attrmask); 536b8e80941Smrg * // Walk interleaved attributes with a common stride and instance divisor 537b8e80941Smrg * while (attrmask) { 538b8e80941Smrg * const gl_vert_attrib attr = u_bit_scan(&attrmask); 539b8e80941Smrg * const struct gl_array_attributes *const attrib 540b8e80941Smrg * = _mesa_draw_array_attrib(vao, attr); 541b8e80941Smrg * 542b8e80941Smrg * <insert code to handle non vbo vertex arrays> 543b8e80941Smrg * } 544b8e80941Smrg * usermask &= ~boundmask; 545b8e80941Smrg * } 546b8e80941Smrg * 547b8e80941Smrg * // Process values that should have better been uniforms in the application 548b8e80941Smrg * GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx); 549b8e80941Smrg * while (curmask) { 550b8e80941Smrg * const gl_vert_attrib attr = u_bit_scan(&curmask); 551b8e80941Smrg * const struct gl_array_attributes *const attrib 552b8e80941Smrg * = _mesa_draw_current_attrib(ctx, attr); 553b8e80941Smrg * 554b8e80941Smrg * <insert code to handle current values> 555b8e80941Smrg * } 556b8e80941Smrg * 557b8e80941Smrg * 558b8e80941Smrg * Note that the scan below must not incoporate any context state. 559b8e80941Smrg * The rationale is that once a VAO is finalized it should not 560b8e80941Smrg * be touched anymore. That means, do not incorporate the 561b8e80941Smrg * gl_context::Array._DrawVAOEnabledAttribs bitmask into this scan. 562b8e80941Smrg * A backend driver may further reduce the handled vertex processing 563b8e80941Smrg * inputs based on their vertex shader inputs. But scanning for 564b8e80941Smrg * collapsable binding points to reduce relocs is done based on the 565b8e80941Smrg * enabled arrays. 566b8e80941Smrg * Also VAOs may be shared between contexts due to their use in dlists 567b8e80941Smrg * thus no context state should bleed into the VAO. 568848b8605Smrg */ 569b8e80941Smrgvoid 570b8e80941Smrg_mesa_update_vao_derived_arrays(struct gl_context *ctx, 571b8e80941Smrg struct gl_vertex_array_object *vao) 572848b8605Smrg{ 573b8e80941Smrg /* Make sure we do not run into problems with shared objects */ 574b8e80941Smrg assert(!vao->SharedAndImmutable || vao->NewArrays == 0); 575b8e80941Smrg 576b8e80941Smrg /* Limit used for common binding scanning below. */ 577b8e80941Smrg const GLsizeiptr MaxRelativeOffset = 578b8e80941Smrg ctx->Const.MaxVertexAttribRelativeOffset; 579b8e80941Smrg 580b8e80941Smrg /* The gl_vertex_array_object::_AttributeMapMode denotes the way 581b8e80941Smrg * VERT_ATTRIB_{POS,GENERIC0} mapping is done. 582b8e80941Smrg * 583b8e80941Smrg * This mapping is used to map between the OpenGL api visible 584b8e80941Smrg * VERT_ATTRIB_* arrays to mesa driver arrayinputs or shader inputs. 585b8e80941Smrg * The mapping only depends on the enabled bits of the 586b8e80941Smrg * VERT_ATTRIB_{POS,GENERIC0} arrays and is tracked in the VAO. 587b8e80941Smrg * 588b8e80941Smrg * This map needs to be applied when finally translating to the bitmasks 589b8e80941Smrg * as consumed by the driver backends. The duplicate scanning is here 590b8e80941Smrg * can as well be done in the OpenGL API numbering without this map. 591b8e80941Smrg */ 592b8e80941Smrg const gl_attribute_map_mode mode = vao->_AttributeMapMode; 593b8e80941Smrg /* Enabled array bits. */ 594b8e80941Smrg const GLbitfield enabled = vao->Enabled; 595b8e80941Smrg /* VBO array bits. */ 596b8e80941Smrg const GLbitfield vbos = vao->VertexAttribBufferMask; 597b8e80941Smrg 598b8e80941Smrg /* Compute and store effectively enabled and mapped vbo arrays */ 599b8e80941Smrg vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos); 600b8e80941Smrg /* Walk those enabled arrays that have a real vbo attached */ 601b8e80941Smrg GLbitfield mask = enabled; 602b8e80941Smrg while (mask) { 603b8e80941Smrg /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */ 604b8e80941Smrg const int i = ffs(mask) - 1; 605b8e80941Smrg /* The binding from the first to be processed attribute. */ 606b8e80941Smrg const GLuint bindex = vao->VertexAttrib[i].BufferBindingIndex; 607b8e80941Smrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex]; 608b8e80941Smrg 609b8e80941Smrg /* The scan goes different for user space arrays than vbos */ 610b8e80941Smrg if (_mesa_is_bufferobj(binding->BufferObj)) { 611b8e80941Smrg /* The bound arrays. */ 612b8e80941Smrg const GLbitfield bound = enabled & binding->_BoundArrays; 613b8e80941Smrg 614b8e80941Smrg /* Start this current effective binding with the actual bound arrays */ 615b8e80941Smrg GLbitfield eff_bound_arrays = bound; 616b8e80941Smrg 617b8e80941Smrg /* 618b8e80941Smrg * If there is nothing left to scan just update the effective binding 619b8e80941Smrg * information. If the VAO is already only using a single binding point 620b8e80941Smrg * we end up here. So the overhead of this scan for an application 621b8e80941Smrg * carefully preparing the VAO for draw is low. 622b8e80941Smrg */ 623b8e80941Smrg 624b8e80941Smrg GLbitfield scanmask = mask & vbos & ~bound; 625b8e80941Smrg /* Is there something left to scan? */ 626b8e80941Smrg if (scanmask == 0) { 627b8e80941Smrg /* Just update the back reference from the attrib to the binding and 628b8e80941Smrg * the effective offset. 629b8e80941Smrg */ 630b8e80941Smrg GLbitfield attrmask = eff_bound_arrays; 631b8e80941Smrg while (attrmask) { 632b8e80941Smrg const int j = u_bit_scan(&attrmask); 633b8e80941Smrg struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 634b8e80941Smrg 635b8e80941Smrg /* Update the index into the common binding point and offset */ 636b8e80941Smrg attrib2->_EffBufferBindingIndex = bindex; 637b8e80941Smrg attrib2->_EffRelativeOffset = attrib2->RelativeOffset; 638b8e80941Smrg assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset); 639b8e80941Smrg } 640b8e80941Smrg /* Finally this is the set of effectively bound arrays with the 641b8e80941Smrg * original binding offset. 642b8e80941Smrg */ 643b8e80941Smrg binding->_EffOffset = binding->Offset; 644b8e80941Smrg /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 645b8e80941Smrg binding->_EffBoundArrays = 646b8e80941Smrg _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 647b8e80941Smrg 648b8e80941Smrg } else { 649b8e80941Smrg /* In the VBO case, scan for attribute/binding 650b8e80941Smrg * combinations with relative bindings in the range of 651b8e80941Smrg * [0, ctx->Const.MaxVertexAttribRelativeOffset]. 652b8e80941Smrg * Note that this does also go beyond just interleaved arrays 653b8e80941Smrg * as long as they use the same VBO, binding parameters and the 654b8e80941Smrg * offsets stay within bounds that the backend still can handle. 655b8e80941Smrg */ 656b8e80941Smrg 657b8e80941Smrg GLsizeiptr min_offset, max_offset; 658b8e80941Smrg compute_vbo_offset_range(vao, binding, &min_offset, &max_offset); 659b8e80941Smrg assert(max_offset <= min_offset + MaxRelativeOffset); 660b8e80941Smrg 661b8e80941Smrg /* Now scan. */ 662b8e80941Smrg while (scanmask) { 663b8e80941Smrg /* Do not use u_bit_scan as we can walk multiple 664b8e80941Smrg * attrib arrays at once 665b8e80941Smrg */ 666b8e80941Smrg const int j = ffs(scanmask) - 1; 667b8e80941Smrg const struct gl_array_attributes *attrib2 = 668b8e80941Smrg &vao->VertexAttrib[j]; 669b8e80941Smrg const struct gl_vertex_buffer_binding *binding2 = 670b8e80941Smrg &vao->BufferBinding[attrib2->BufferBindingIndex]; 671b8e80941Smrg 672b8e80941Smrg /* Remove those attrib bits from the mask that are bound to the 673b8e80941Smrg * same effective binding point. 674b8e80941Smrg */ 675b8e80941Smrg const GLbitfield bound2 = enabled & binding2->_BoundArrays; 676b8e80941Smrg scanmask &= ~bound2; 677b8e80941Smrg 678b8e80941Smrg /* Check if we have an identical binding */ 679b8e80941Smrg if (binding->Stride != binding2->Stride) 680b8e80941Smrg continue; 681b8e80941Smrg if (binding->InstanceDivisor != binding2->InstanceDivisor) 682b8e80941Smrg continue; 683b8e80941Smrg if (binding->BufferObj != binding2->BufferObj) 684b8e80941Smrg continue; 685b8e80941Smrg /* Check if we can fold both bindings into a common binding */ 686b8e80941Smrg GLsizeiptr min_offset2, max_offset2; 687b8e80941Smrg compute_vbo_offset_range(vao, binding2, 688b8e80941Smrg &min_offset2, &max_offset2); 689b8e80941Smrg /* If the relative offset is within the limits ... */ 690b8e80941Smrg if (min_offset + MaxRelativeOffset < max_offset2) 691b8e80941Smrg continue; 692b8e80941Smrg if (min_offset2 + MaxRelativeOffset < max_offset) 693b8e80941Smrg continue; 694b8e80941Smrg /* ... add this array to the effective binding */ 695b8e80941Smrg eff_bound_arrays |= bound2; 696b8e80941Smrg min_offset = MIN2(min_offset, min_offset2); 697b8e80941Smrg max_offset = MAX2(max_offset, max_offset2); 698b8e80941Smrg assert(max_offset <= min_offset + MaxRelativeOffset); 699b8e80941Smrg } 700b8e80941Smrg 701b8e80941Smrg /* Update the back reference from the attrib to the binding */ 702b8e80941Smrg GLbitfield attrmask = eff_bound_arrays; 703b8e80941Smrg while (attrmask) { 704b8e80941Smrg const int j = u_bit_scan(&attrmask); 705b8e80941Smrg struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 706b8e80941Smrg const struct gl_vertex_buffer_binding *binding2 = 707b8e80941Smrg &vao->BufferBinding[attrib2->BufferBindingIndex]; 708b8e80941Smrg 709b8e80941Smrg /* Update the index into the common binding point and offset */ 710b8e80941Smrg attrib2->_EffBufferBindingIndex = bindex; 711b8e80941Smrg attrib2->_EffRelativeOffset = 712b8e80941Smrg binding2->Offset + attrib2->RelativeOffset - min_offset; 713b8e80941Smrg assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset); 714b8e80941Smrg } 715b8e80941Smrg /* Finally this is the set of effectively bound arrays */ 716b8e80941Smrg binding->_EffOffset = min_offset; 717b8e80941Smrg /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 718b8e80941Smrg binding->_EffBoundArrays = 719b8e80941Smrg _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 720b8e80941Smrg } 721b8e80941Smrg 722b8e80941Smrg /* Mark all the effective bound arrays as processed. */ 723b8e80941Smrg mask &= ~eff_bound_arrays; 724b8e80941Smrg 725b8e80941Smrg } else { 726b8e80941Smrg /* Scanning of common bindings for user space arrays. 727b8e80941Smrg */ 728b8e80941Smrg 729b8e80941Smrg const struct gl_array_attributes *attrib = &vao->VertexAttrib[i]; 730b8e80941Smrg const GLbitfield bound = VERT_BIT(i); 731b8e80941Smrg 732b8e80941Smrg /* Note that user space array pointers can only happen using a one 733b8e80941Smrg * to one binding point to array mapping. 734b8e80941Smrg * The OpenGL 4.x/ARB_vertex_attrib_binding api does not support 735b8e80941Smrg * user space arrays collected at multiple binding points. 736b8e80941Smrg * The only provider of user space interleaved arrays with a single 737b8e80941Smrg * binding point is the mesa internal vbo module. But that one 738b8e80941Smrg * provides a perfect interleaved set of arrays. 739b8e80941Smrg * 740b8e80941Smrg * If this would not be true we would potentially get attribute arrays 741b8e80941Smrg * with user space pointers that may not lie within the 742b8e80941Smrg * MaxRelativeOffset range but still attached to a single binding. 743b8e80941Smrg * Then we would need to store the effective attribute and binding 744b8e80941Smrg * grouping information in a seperate array beside 745b8e80941Smrg * gl_array_attributes/gl_vertex_buffer_binding. 746b8e80941Smrg */ 747b8e80941Smrg assert(util_bitcount(binding->_BoundArrays & vao->Enabled) == 1 748b8e80941Smrg || (vao->Enabled & ~binding->_BoundArrays) == 0); 749b8e80941Smrg 750b8e80941Smrg /* Start this current effective binding with the array */ 751b8e80941Smrg GLbitfield eff_bound_arrays = bound; 752b8e80941Smrg 753b8e80941Smrg const GLubyte *ptr = attrib->Ptr; 754b8e80941Smrg unsigned vertex_end = attrib->Format._ElementSize; 755b8e80941Smrg 756b8e80941Smrg /* Walk other user space arrays and see which are interleaved 757b8e80941Smrg * using the same binding parameters. 758b8e80941Smrg */ 759b8e80941Smrg GLbitfield scanmask = mask & ~vbos & ~bound; 760b8e80941Smrg while (scanmask) { 761b8e80941Smrg const int j = u_bit_scan(&scanmask); 762b8e80941Smrg const struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 763b8e80941Smrg const struct gl_vertex_buffer_binding *binding2 = 764b8e80941Smrg &vao->BufferBinding[attrib2->BufferBindingIndex]; 765b8e80941Smrg 766b8e80941Smrg /* See the comment at the same assert above. */ 767b8e80941Smrg assert(util_bitcount(binding2->_BoundArrays & vao->Enabled) == 1 768b8e80941Smrg || (vao->Enabled & ~binding->_BoundArrays) == 0); 769b8e80941Smrg 770b8e80941Smrg /* Check if we have an identical binding */ 771b8e80941Smrg if (binding->Stride != binding2->Stride) 772b8e80941Smrg continue; 773b8e80941Smrg if (binding->InstanceDivisor != binding2->InstanceDivisor) 774b8e80941Smrg continue; 775b8e80941Smrg if (ptr <= attrib2->Ptr) { 776b8e80941Smrg if (ptr + binding->Stride < attrib2->Ptr + 777b8e80941Smrg attrib2->Format._ElementSize) 778b8e80941Smrg continue; 779b8e80941Smrg unsigned end = attrib2->Ptr + attrib2->Format._ElementSize - ptr; 780b8e80941Smrg vertex_end = MAX2(vertex_end, end); 781b8e80941Smrg } else { 782b8e80941Smrg if (attrib2->Ptr + binding->Stride < ptr + vertex_end) 783b8e80941Smrg continue; 784b8e80941Smrg vertex_end += (GLsizei)(ptr - attrib2->Ptr); 785b8e80941Smrg ptr = attrib2->Ptr; 786b8e80941Smrg } 787b8e80941Smrg 788b8e80941Smrg /* User space buffer object */ 789b8e80941Smrg assert(!_mesa_is_bufferobj(binding2->BufferObj)); 790b8e80941Smrg 791b8e80941Smrg eff_bound_arrays |= VERT_BIT(j); 792b8e80941Smrg } 793b8e80941Smrg 794b8e80941Smrg /* Update the back reference from the attrib to the binding */ 795b8e80941Smrg GLbitfield attrmask = eff_bound_arrays; 796b8e80941Smrg while (attrmask) { 797b8e80941Smrg const int j = u_bit_scan(&attrmask); 798b8e80941Smrg struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 799b8e80941Smrg 800b8e80941Smrg /* Update the index into the common binding point and the offset */ 801b8e80941Smrg attrib2->_EffBufferBindingIndex = bindex; 802b8e80941Smrg attrib2->_EffRelativeOffset = attrib2->Ptr - ptr; 803b8e80941Smrg assert(attrib2->_EffRelativeOffset <= binding->Stride); 804b8e80941Smrg } 805b8e80941Smrg /* Finally this is the set of effectively bound arrays */ 806b8e80941Smrg binding->_EffOffset = (GLintptr)ptr; 807b8e80941Smrg /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 808b8e80941Smrg binding->_EffBoundArrays = 809b8e80941Smrg _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 810b8e80941Smrg 811b8e80941Smrg /* Mark all the effective bound arrays as processed. */ 812b8e80941Smrg mask &= ~eff_bound_arrays; 813b8e80941Smrg } 814848b8605Smrg } 815b8e80941Smrg 816b8e80941Smrg#ifndef NDEBUG 817b8e80941Smrg /* Make sure the above code works as expected. */ 818b8e80941Smrg for (gl_vert_attrib attr = 0; attr < VERT_ATTRIB_MAX; ++attr) { 819b8e80941Smrg /* Query the original api defined attrib/binding information ... */ 820b8e80941Smrg const unsigned char *const map =_mesa_vao_attribute_map[mode]; 821b8e80941Smrg if (vao->Enabled & VERT_BIT(map[attr])) { 822b8e80941Smrg const struct gl_array_attributes *attrib = 823b8e80941Smrg &vao->VertexAttrib[map[attr]]; 824b8e80941Smrg const struct gl_vertex_buffer_binding *binding = 825b8e80941Smrg &vao->BufferBinding[attrib->BufferBindingIndex]; 826b8e80941Smrg /* ... and compare that with the computed attrib/binding */ 827b8e80941Smrg const struct gl_vertex_buffer_binding *binding2 = 828b8e80941Smrg &vao->BufferBinding[attrib->_EffBufferBindingIndex]; 829b8e80941Smrg assert(binding->Stride == binding2->Stride); 830b8e80941Smrg assert(binding->InstanceDivisor == binding2->InstanceDivisor); 831b8e80941Smrg assert(binding->BufferObj == binding2->BufferObj); 832b8e80941Smrg if (_mesa_is_bufferobj(binding->BufferObj)) { 833b8e80941Smrg assert(attrib->_EffRelativeOffset <= MaxRelativeOffset); 834b8e80941Smrg assert(binding->Offset + attrib->RelativeOffset == 835b8e80941Smrg binding2->_EffOffset + attrib->_EffRelativeOffset); 836b8e80941Smrg } else { 837b8e80941Smrg assert(attrib->_EffRelativeOffset < binding->Stride); 838b8e80941Smrg assert((GLintptr)attrib->Ptr == 839b8e80941Smrg binding2->_EffOffset + attrib->_EffRelativeOffset); 840b8e80941Smrg } 841b8e80941Smrg } 842b8e80941Smrg } 843b8e80941Smrg#endif 844b8e80941Smrg} 845b8e80941Smrg 846b8e80941Smrg 847b8e80941Smrgvoid 848b8e80941Smrg_mesa_set_vao_immutable(struct gl_context *ctx, 849b8e80941Smrg struct gl_vertex_array_object *vao) 850b8e80941Smrg{ 851b8e80941Smrg _mesa_update_vao_derived_arrays(ctx, vao); 852b8e80941Smrg vao->NewArrays = 0; 853b8e80941Smrg vao->SharedAndImmutable = true; 854848b8605Smrg} 855848b8605Smrg 856848b8605Smrg 857b8e80941Smrgbool 858b8e80941Smrg_mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao) 859b8e80941Smrg{ 860b8e80941Smrg /* Walk those enabled arrays that have the default vbo attached */ 861b8e80941Smrg GLbitfield mask = vao->Enabled & ~vao->VertexAttribBufferMask; 862848b8605Smrg 863b8e80941Smrg while (mask) { 864b8e80941Smrg /* Do not use u_bit_scan64 as we can walk multiple 865b8e80941Smrg * attrib arrays at once 866b8e80941Smrg */ 867b8e80941Smrg const int i = ffs(mask) - 1; 868b8e80941Smrg const struct gl_array_attributes *attrib_array = 869b8e80941Smrg &vao->VertexAttrib[i]; 870b8e80941Smrg const struct gl_vertex_buffer_binding *buffer_binding = 871b8e80941Smrg &vao->BufferBinding[attrib_array->BufferBindingIndex]; 872b8e80941Smrg 873b8e80941Smrg /* We have already masked out vao->VertexAttribBufferMask */ 874b8e80941Smrg assert(!_mesa_is_bufferobj(buffer_binding->BufferObj)); 875b8e80941Smrg 876b8e80941Smrg /* Bail out once we find the first non vbo with a non zero stride */ 877b8e80941Smrg if (buffer_binding->Stride != 0) 878b8e80941Smrg return false; 879b8e80941Smrg 880b8e80941Smrg /* Note that we cannot use the xor variant since the _BoundArray mask 881b8e80941Smrg * may contain array attributes that are bound but not enabled. 882b8e80941Smrg */ 883b8e80941Smrg mask &= ~buffer_binding->_BoundArrays; 884b8e80941Smrg } 885b8e80941Smrg 886b8e80941Smrg return true; 887b8e80941Smrg} 888b8e80941Smrg 889b8e80941Smrgbool 890b8e80941Smrg_mesa_all_buffers_are_unmapped(const struct gl_vertex_array_object *vao) 891848b8605Smrg{ 892b8e80941Smrg /* Walk the enabled arrays that have a vbo attached */ 893b8e80941Smrg GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask; 894b8e80941Smrg 895b8e80941Smrg while (mask) { 896b8e80941Smrg const int i = ffs(mask) - 1; 897b8e80941Smrg const struct gl_array_attributes *attrib_array = 898b8e80941Smrg &vao->VertexAttrib[i]; 899b8e80941Smrg const struct gl_vertex_buffer_binding *buffer_binding = 900b8e80941Smrg &vao->BufferBinding[attrib_array->BufferBindingIndex]; 901848b8605Smrg 902b8e80941Smrg /* We have already masked with vao->VertexAttribBufferMask */ 903b8e80941Smrg assert(_mesa_is_bufferobj(buffer_binding->BufferObj)); 904848b8605Smrg 905b8e80941Smrg /* Bail out once we find the first disallowed mapping */ 906b8e80941Smrg if (_mesa_check_disallowed_mapping(buffer_binding->BufferObj)) 907b8e80941Smrg return false; 908b8e80941Smrg 909b8e80941Smrg /* We have handled everything that is bound to this buffer_binding. */ 910b8e80941Smrg mask &= ~buffer_binding->_BoundArrays; 911848b8605Smrg } 912848b8605Smrg 913b8e80941Smrg return true; 914848b8605Smrg} 915848b8605Smrg 916848b8605Smrg 917848b8605Smrg/** 918b8e80941Smrg * Map buffer objects used in attribute arrays. 919848b8605Smrg */ 920848b8605Smrgvoid 921b8e80941Smrg_mesa_vao_map_arrays(struct gl_context *ctx, struct gl_vertex_array_object *vao, 922b8e80941Smrg GLbitfield access) 923848b8605Smrg{ 924b8e80941Smrg GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask; 925b8e80941Smrg while (mask) { 926b8e80941Smrg /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */ 927b8e80941Smrg const gl_vert_attrib attr = ffs(mask) - 1; 928b8e80941Smrg const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex; 929b8e80941Smrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex]; 930b8e80941Smrg mask &= ~binding->_BoundArrays; 931b8e80941Smrg 932b8e80941Smrg struct gl_buffer_object *bo = binding->BufferObj; 933b8e80941Smrg assert(_mesa_is_bufferobj(bo)); 934b8e80941Smrg if (_mesa_bufferobj_mapped(bo, MAP_INTERNAL)) 935b8e80941Smrg continue; 936b8e80941Smrg 937b8e80941Smrg ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL); 938848b8605Smrg } 939848b8605Smrg} 940848b8605Smrg 941848b8605Smrg 942848b8605Smrg/** 943b8e80941Smrg * Map buffer objects used in the vao, attribute arrays and index buffer. 944848b8605Smrg */ 945848b8605Smrgvoid 946b8e80941Smrg_mesa_vao_map(struct gl_context *ctx, struct gl_vertex_array_object *vao, 947b8e80941Smrg GLbitfield access) 948848b8605Smrg{ 949b8e80941Smrg struct gl_buffer_object *bo = vao->IndexBufferObj; 950848b8605Smrg 951b8e80941Smrg /* map the index buffer, if there is one, and not already mapped */ 952b8e80941Smrg if (_mesa_is_bufferobj(bo) && !_mesa_bufferobj_mapped(bo, MAP_INTERNAL)) 953b8e80941Smrg ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL); 954848b8605Smrg 955b8e80941Smrg _mesa_vao_map_arrays(ctx, vao, access); 956b8e80941Smrg} 957848b8605Smrg 958848b8605Smrg 959b8e80941Smrg/** 960b8e80941Smrg * Unmap buffer objects used in attribute arrays. 961b8e80941Smrg */ 962b8e80941Smrgvoid 963b8e80941Smrg_mesa_vao_unmap_arrays(struct gl_context *ctx, 964b8e80941Smrg struct gl_vertex_array_object *vao) 965b8e80941Smrg{ 966b8e80941Smrg GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask; 967b8e80941Smrg while (mask) { 968b8e80941Smrg /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */ 969b8e80941Smrg const gl_vert_attrib attr = ffs(mask) - 1; 970b8e80941Smrg const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex; 971b8e80941Smrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex]; 972b8e80941Smrg mask &= ~binding->_BoundArrays; 973b8e80941Smrg 974b8e80941Smrg struct gl_buffer_object *bo = binding->BufferObj; 975b8e80941Smrg assert(_mesa_is_bufferobj(bo)); 976b8e80941Smrg if (!_mesa_bufferobj_mapped(bo, MAP_INTERNAL)) 977b8e80941Smrg continue; 978b8e80941Smrg 979b8e80941Smrg ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL); 980848b8605Smrg } 981848b8605Smrg} 982848b8605Smrg 983848b8605Smrg 984b8e80941Smrg/** 985b8e80941Smrg * Unmap buffer objects used in the vao, attribute arrays and index buffer. 986b8e80941Smrg */ 987b8e80941Smrgvoid 988b8e80941Smrg_mesa_vao_unmap(struct gl_context *ctx, struct gl_vertex_array_object *vao) 989b8e80941Smrg{ 990b8e80941Smrg struct gl_buffer_object *bo = vao->IndexBufferObj; 991b8e80941Smrg 992b8e80941Smrg /* unmap the index buffer, if there is one, and still mapped */ 993b8e80941Smrg if (_mesa_is_bufferobj(bo) && _mesa_bufferobj_mapped(bo, MAP_INTERNAL)) 994b8e80941Smrg ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL); 995b8e80941Smrg 996b8e80941Smrg _mesa_vao_unmap_arrays(ctx, vao); 997b8e80941Smrg} 998b8e80941Smrg 999b8e80941Smrg 1000848b8605Smrg/**********************************************************************/ 1001848b8605Smrg/* API Functions */ 1002848b8605Smrg/**********************************************************************/ 1003848b8605Smrg 1004848b8605Smrg 1005848b8605Smrg/** 1006b8e80941Smrg * ARB version of glBindVertexArray() 1007848b8605Smrg */ 1008b8e80941Smrgstatic ALWAYS_INLINE void 1009b8e80941Smrgbind_vertex_array(struct gl_context *ctx, GLuint id, bool no_error) 1010848b8605Smrg{ 1011b8e80941Smrg struct gl_vertex_array_object *const oldObj = ctx->Array.VAO; 1012848b8605Smrg struct gl_vertex_array_object *newObj = NULL; 1013848b8605Smrg 1014b8e80941Smrg assert(oldObj != NULL); 1015848b8605Smrg 1016b8e80941Smrg if (oldObj->Name == id) 1017848b8605Smrg return; /* rebinding the same array object- no change */ 1018848b8605Smrg 1019848b8605Smrg /* 1020848b8605Smrg * Get pointer to new array object (newObj) 1021848b8605Smrg */ 1022848b8605Smrg if (id == 0) { 1023848b8605Smrg /* The spec says there is no array object named 0, but we use 1024848b8605Smrg * one internally because it simplifies things. 1025848b8605Smrg */ 1026848b8605Smrg newObj = ctx->Array.DefaultVAO; 1027848b8605Smrg } 1028848b8605Smrg else { 1029848b8605Smrg /* non-default array object */ 1030848b8605Smrg newObj = _mesa_lookup_vao(ctx, id); 1031b8e80941Smrg if (!no_error && !newObj) { 1032b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1033b8e80941Smrg "glBindVertexArray(non-gen name)"); 1034b8e80941Smrg return; 1035848b8605Smrg } 1036848b8605Smrg 1037b8e80941Smrg newObj->EverBound = GL_TRUE; 1038848b8605Smrg } 1039848b8605Smrg 1040b8e80941Smrg /* The _DrawArrays pointer is pointing at the VAO being unbound and 1041b8e80941Smrg * that VAO may be in the process of being deleted. If it's not going 1042b8e80941Smrg * to be deleted, this will have no effect, because the pointer needs 1043b8e80941Smrg * to be updated by the VBO module anyway. 1044b8e80941Smrg * 1045b8e80941Smrg * Before the VBO module can update the pointer, we have to set it 1046b8e80941Smrg * to NULL for drivers not to set up arrays which are not bound, 1047b8e80941Smrg * or to prevent a crash if the VAO being unbound is going to be 1048b8e80941Smrg * deleted. 1049b8e80941Smrg */ 1050b8e80941Smrg _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0); 1051848b8605Smrg 1052848b8605Smrg _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj); 1053848b8605Smrg} 1054848b8605Smrg 1055848b8605Smrg 1056848b8605Smrgvoid GLAPIENTRY 1057b8e80941Smrg_mesa_BindVertexArray_no_error(GLuint id) 1058848b8605Smrg{ 1059848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1060b8e80941Smrg bind_vertex_array(ctx, id, true); 1061848b8605Smrg} 1062848b8605Smrg 1063848b8605Smrg 1064848b8605Smrgvoid GLAPIENTRY 1065b8e80941Smrg_mesa_BindVertexArray(GLuint id) 1066848b8605Smrg{ 1067848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1068b8e80941Smrg bind_vertex_array(ctx, id, false); 1069848b8605Smrg} 1070848b8605Smrg 1071848b8605Smrg 1072848b8605Smrg/** 1073848b8605Smrg * Delete a set of array objects. 1074848b8605Smrg * 1075848b8605Smrg * \param n Number of array objects to delete. 1076848b8605Smrg * \param ids Array of \c n array object IDs. 1077848b8605Smrg */ 1078b8e80941Smrgstatic void 1079b8e80941Smrgdelete_vertex_arrays(struct gl_context *ctx, GLsizei n, const GLuint *ids) 1080848b8605Smrg{ 1081848b8605Smrg GLsizei i; 1082848b8605Smrg 1083848b8605Smrg for (i = 0; i < n; i++) { 1084b8e80941Smrg /* IDs equal to 0 should be silently ignored. */ 1085b8e80941Smrg if (!ids[i]) 1086b8e80941Smrg continue; 1087b8e80941Smrg 1088848b8605Smrg struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]); 1089848b8605Smrg 1090b8e80941Smrg if (obj) { 1091b8e80941Smrg assert(obj->Name == ids[i]); 1092848b8605Smrg 1093b8e80941Smrg /* If the array object is currently bound, the spec says "the binding 1094b8e80941Smrg * for that object reverts to zero and the default vertex array 1095b8e80941Smrg * becomes current." 1096b8e80941Smrg */ 1097b8e80941Smrg if (obj == ctx->Array.VAO) 1098b8e80941Smrg _mesa_BindVertexArray_no_error(0); 1099b8e80941Smrg 1100b8e80941Smrg /* The ID is immediately freed for re-use */ 1101b8e80941Smrg _mesa_HashRemoveLocked(ctx->Array.Objects, obj->Name); 1102848b8605Smrg 1103b8e80941Smrg if (ctx->Array.LastLookedUpVAO == obj) 1104b8e80941Smrg _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL); 1105b8e80941Smrg if (ctx->Array._DrawVAO == obj) 1106b8e80941Smrg _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0); 1107848b8605Smrg 1108848b8605Smrg /* Unreference the array object. 1109848b8605Smrg * If refcount hits zero, the object will be deleted. 1110848b8605Smrg */ 1111848b8605Smrg _mesa_reference_vao(ctx, &obj, NULL); 1112848b8605Smrg } 1113848b8605Smrg } 1114848b8605Smrg} 1115848b8605Smrg 1116848b8605Smrg 1117b8e80941Smrgvoid GLAPIENTRY 1118b8e80941Smrg_mesa_DeleteVertexArrays_no_error(GLsizei n, const GLuint *ids) 1119b8e80941Smrg{ 1120b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1121b8e80941Smrg delete_vertex_arrays(ctx, n, ids); 1122b8e80941Smrg} 1123b8e80941Smrg 1124b8e80941Smrg 1125b8e80941Smrgvoid GLAPIENTRY 1126b8e80941Smrg_mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids) 1127b8e80941Smrg{ 1128b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1129b8e80941Smrg 1130b8e80941Smrg if (n < 0) { 1131b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)"); 1132b8e80941Smrg return; 1133b8e80941Smrg } 1134b8e80941Smrg 1135b8e80941Smrg delete_vertex_arrays(ctx, n, ids); 1136b8e80941Smrg} 1137b8e80941Smrg 1138b8e80941Smrg 1139848b8605Smrg/** 1140848b8605Smrg * Generate a set of unique array object IDs and store them in \c arrays. 1141b8e80941Smrg * Helper for _mesa_GenVertexArrays() and _mesa_CreateVertexArrays() 1142b8e80941Smrg * below. 1143b8e80941Smrg * 1144848b8605Smrg * \param n Number of IDs to generate. 1145848b8605Smrg * \param arrays Array of \c n locations to store the IDs. 1146b8e80941Smrg * \param create Indicates that the objects should also be created. 1147b8e80941Smrg * \param func The name of the GL entry point. 1148848b8605Smrg */ 1149848b8605Smrgstatic void 1150b8e80941Smrggen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays, 1151b8e80941Smrg bool create, const char *func) 1152848b8605Smrg{ 1153848b8605Smrg GLuint first; 1154848b8605Smrg GLint i; 1155848b8605Smrg 1156b8e80941Smrg if (!arrays) 1157848b8605Smrg return; 1158848b8605Smrg 1159848b8605Smrg first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); 1160848b8605Smrg 1161b8e80941Smrg /* For the sake of simplicity we create the array objects in both 1162b8e80941Smrg * the Gen* and Create* cases. The only difference is the value of 1163b8e80941Smrg * EverBound, which is set to true in the Create* case. 1164b8e80941Smrg */ 1165848b8605Smrg for (i = 0; i < n; i++) { 1166848b8605Smrg struct gl_vertex_array_object *obj; 1167848b8605Smrg GLuint name = first + i; 1168848b8605Smrg 1169b8e80941Smrg obj = _mesa_new_vao(ctx, name); 1170848b8605Smrg if (!obj) { 1171b8e80941Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 1172848b8605Smrg return; 1173848b8605Smrg } 1174b8e80941Smrg obj->EverBound = create; 1175b8e80941Smrg _mesa_HashInsertLocked(ctx->Array.Objects, obj->Name, obj); 1176848b8605Smrg arrays[i] = first + i; 1177848b8605Smrg } 1178848b8605Smrg} 1179848b8605Smrg 1180848b8605Smrg 1181b8e80941Smrgstatic void 1182b8e80941Smrggen_vertex_arrays_err(struct gl_context *ctx, GLsizei n, GLuint *arrays, 1183b8e80941Smrg bool create, const char *func) 1184b8e80941Smrg{ 1185b8e80941Smrg if (n < 0) { 1186b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); 1187b8e80941Smrg return; 1188b8e80941Smrg } 1189b8e80941Smrg 1190b8e80941Smrg gen_vertex_arrays(ctx, n, arrays, create, func); 1191b8e80941Smrg} 1192b8e80941Smrg 1193b8e80941Smrg 1194848b8605Smrg/** 1195848b8605Smrg * ARB version of glGenVertexArrays() 1196848b8605Smrg * All arrays will be required to live in VBOs. 1197848b8605Smrg */ 1198b8e80941Smrgvoid GLAPIENTRY 1199b8e80941Smrg_mesa_GenVertexArrays_no_error(GLsizei n, GLuint *arrays) 1200b8e80941Smrg{ 1201b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1202b8e80941Smrg gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays"); 1203b8e80941Smrg} 1204b8e80941Smrg 1205b8e80941Smrg 1206848b8605Smrgvoid GLAPIENTRY 1207848b8605Smrg_mesa_GenVertexArrays(GLsizei n, GLuint *arrays) 1208848b8605Smrg{ 1209848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1210b8e80941Smrg gen_vertex_arrays_err(ctx, n, arrays, false, "glGenVertexArrays"); 1211848b8605Smrg} 1212848b8605Smrg 1213848b8605Smrg 1214848b8605Smrg/** 1215b8e80941Smrg * ARB_direct_state_access 1216b8e80941Smrg * Generates ID's and creates the array objects. 1217848b8605Smrg */ 1218848b8605Smrgvoid GLAPIENTRY 1219b8e80941Smrg_mesa_CreateVertexArrays_no_error(GLsizei n, GLuint *arrays) 1220b8e80941Smrg{ 1221b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1222b8e80941Smrg gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays"); 1223b8e80941Smrg} 1224b8e80941Smrg 1225b8e80941Smrg 1226b8e80941Smrgvoid GLAPIENTRY 1227b8e80941Smrg_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays) 1228848b8605Smrg{ 1229848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1230b8e80941Smrg gen_vertex_arrays_err(ctx, n, arrays, true, "glCreateVertexArrays"); 1231848b8605Smrg} 1232848b8605Smrg 1233848b8605Smrg 1234848b8605Smrg/** 1235848b8605Smrg * Determine if ID is the name of an array object. 1236848b8605Smrg * 1237848b8605Smrg * \param id ID of the potential array object. 1238848b8605Smrg * \return \c GL_TRUE if \c id is the name of a array object, 1239848b8605Smrg * \c GL_FALSE otherwise. 1240848b8605Smrg */ 1241848b8605SmrgGLboolean GLAPIENTRY 1242848b8605Smrg_mesa_IsVertexArray( GLuint id ) 1243848b8605Smrg{ 1244848b8605Smrg struct gl_vertex_array_object * obj; 1245848b8605Smrg GET_CURRENT_CONTEXT(ctx); 1246848b8605Smrg ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 1247848b8605Smrg 1248848b8605Smrg obj = _mesa_lookup_vao(ctx, id); 1249848b8605Smrg 1250b8e80941Smrg return obj != NULL && obj->EverBound; 1251b8e80941Smrg} 1252b8e80941Smrg 1253b8e80941Smrg 1254b8e80941Smrg/** 1255b8e80941Smrg * Sets the element array buffer binding of a vertex array object. 1256b8e80941Smrg * 1257b8e80941Smrg * This is the ARB_direct_state_access equivalent of 1258b8e80941Smrg * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer). 1259b8e80941Smrg */ 1260b8e80941Smrgstatic ALWAYS_INLINE void 1261b8e80941Smrgvertex_array_element_buffer(struct gl_context *ctx, GLuint vaobj, GLuint buffer, 1262b8e80941Smrg bool no_error) 1263b8e80941Smrg{ 1264b8e80941Smrg struct gl_vertex_array_object *vao; 1265b8e80941Smrg struct gl_buffer_object *bufObj; 1266b8e80941Smrg 1267b8e80941Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1268b8e80941Smrg 1269b8e80941Smrg if (!no_error) { 1270b8e80941Smrg /* The GL_ARB_direct_state_access specification says: 1271b8e80941Smrg * 1272b8e80941Smrg * "An INVALID_OPERATION error is generated by 1273b8e80941Smrg * VertexArrayElementBuffer if <vaobj> is not [compatibility profile: 1274b8e80941Smrg * zero or] the name of an existing vertex array object." 1275b8e80941Smrg */ 1276b8e80941Smrg vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer"); 1277b8e80941Smrg if (!vao) 1278b8e80941Smrg return; 1279b8e80941Smrg } else { 1280b8e80941Smrg vao = _mesa_lookup_vao(ctx, vaobj); 1281b8e80941Smrg } 1282b8e80941Smrg 1283b8e80941Smrg if (buffer != 0) { 1284b8e80941Smrg if (!no_error) { 1285b8e80941Smrg /* The GL_ARB_direct_state_access specification says: 1286b8e80941Smrg * 1287b8e80941Smrg * "An INVALID_OPERATION error is generated if <buffer> is not zero 1288b8e80941Smrg * or the name of an existing buffer object." 1289b8e80941Smrg */ 1290b8e80941Smrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 1291b8e80941Smrg "glVertexArrayElementBuffer"); 1292b8e80941Smrg } else { 1293b8e80941Smrg bufObj = _mesa_lookup_bufferobj(ctx, buffer); 1294b8e80941Smrg } 1295b8e80941Smrg } else { 1296b8e80941Smrg bufObj = ctx->Shared->NullBufferObj; 1297b8e80941Smrg } 1298b8e80941Smrg 1299b8e80941Smrg if (bufObj) { 1300b8e80941Smrg bufObj->UsageHistory |= USAGE_ELEMENT_ARRAY_BUFFER; 1301b8e80941Smrg _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj); 1302b8e80941Smrg } 1303b8e80941Smrg} 1304b8e80941Smrg 1305b8e80941Smrg 1306b8e80941Smrgvoid GLAPIENTRY 1307b8e80941Smrg_mesa_VertexArrayElementBuffer_no_error(GLuint vaobj, GLuint buffer) 1308b8e80941Smrg{ 1309b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1310b8e80941Smrg vertex_array_element_buffer(ctx, vaobj, buffer, true); 1311b8e80941Smrg} 1312b8e80941Smrg 1313b8e80941Smrg 1314b8e80941Smrgvoid GLAPIENTRY 1315b8e80941Smrg_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer) 1316b8e80941Smrg{ 1317b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1318b8e80941Smrg vertex_array_element_buffer(ctx, vaobj, buffer, false); 1319b8e80941Smrg} 1320b8e80941Smrg 1321b8e80941Smrg 1322b8e80941Smrgvoid GLAPIENTRY 1323b8e80941Smrg_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param) 1324b8e80941Smrg{ 1325b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1326b8e80941Smrg struct gl_vertex_array_object *vao; 1327b8e80941Smrg 1328b8e80941Smrg ASSERT_OUTSIDE_BEGIN_END(ctx); 1329b8e80941Smrg 1330b8e80941Smrg /* The GL_ARB_direct_state_access specification says: 1331b8e80941Smrg * 1332b8e80941Smrg * "An INVALID_OPERATION error is generated if <vaobj> is not 1333b8e80941Smrg * [compatibility profile: zero or] the name of an existing 1334b8e80941Smrg * vertex array object." 1335b8e80941Smrg */ 1336b8e80941Smrg vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv"); 1337b8e80941Smrg if (!vao) 1338b8e80941Smrg return; 1339b8e80941Smrg 1340b8e80941Smrg /* The GL_ARB_direct_state_access specification says: 1341b8e80941Smrg * 1342b8e80941Smrg * "An INVALID_ENUM error is generated if <pname> is not 1343b8e80941Smrg * ELEMENT_ARRAY_BUFFER_BINDING." 1344b8e80941Smrg */ 1345b8e80941Smrg if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) { 1346b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, 1347b8e80941Smrg "glGetVertexArrayiv(pname != " 1348b8e80941Smrg "GL_ELEMENT_ARRAY_BUFFER_BINDING)"); 1349b8e80941Smrg return; 1350b8e80941Smrg } 1351b8e80941Smrg 1352b8e80941Smrg param[0] = vao->IndexBufferObj->Name; 1353848b8605Smrg} 1354