arrayobj.c revision 01e04c3f
17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 4c1f859d4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 57117f1b4Smrg * (C) Copyright IBM Corporation 2006 64a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 77117f1b4Smrg * 87117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 97117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 107117f1b4Smrg * to deal in the Software without restriction, including without limitation 117117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 127117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 137117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 147117f1b4Smrg * 157117f1b4Smrg * The above copyright notice and this permission notice shall be included 167117f1b4Smrg * in all copies or substantial portions of the Software. 177117f1b4Smrg * 187117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 197117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 207117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 257117f1b4Smrg */ 267117f1b4Smrg 277117f1b4Smrg 287117f1b4Smrg/** 297117f1b4Smrg * \file arrayobj.c 30af69d88dSmrg * 3101e04c3fSmrg * Implementation of Vertex Array Objects (VAOs), from OpenGL 3.1+ / 3201e04c3fSmrg * the GL_ARB_vertex_array_object extension. 337117f1b4Smrg * 347117f1b4Smrg * \todo 357117f1b4Smrg * The code in this file borrows a lot from bufferobj.c. There's a certain 367117f1b4Smrg * amount of cruft left over from that origin that may be unnecessary. 377117f1b4Smrg * 387117f1b4Smrg * \author Ian Romanick <idr@us.ibm.com> 397117f1b4Smrg * \author Brian Paul 407117f1b4Smrg */ 417117f1b4Smrg 427117f1b4Smrg 437117f1b4Smrg#include "glheader.h" 447117f1b4Smrg#include "hash.h" 453464ebd5Sriastradh#include "image.h" 467117f1b4Smrg#include "imports.h" 477117f1b4Smrg#include "context.h" 487117f1b4Smrg#include "bufferobj.h" 497117f1b4Smrg#include "arrayobj.h" 504a49301eSmrg#include "macros.h" 513464ebd5Sriastradh#include "mtypes.h" 5201e04c3fSmrg#include "state.h" 533464ebd5Sriastradh#include "varray.h" 5401e04c3fSmrg#include "util/bitscan.h" 5501e04c3fSmrg#include "util/u_atomic.h" 5601e04c3fSmrg#include "util/u_math.h" 5701e04c3fSmrg 5801e04c3fSmrg 5901e04c3fSmrgconst GLubyte 6001e04c3fSmrg_mesa_vao_attribute_map[ATTRIBUTE_MAP_MODE_MAX][VERT_ATTRIB_MAX] = 6101e04c3fSmrg{ 6201e04c3fSmrg /* ATTRIBUTE_MAP_MODE_IDENTITY 6301e04c3fSmrg * 6401e04c3fSmrg * Grab vertex processing attribute VERT_ATTRIB_POS from 6501e04c3fSmrg * the VAO attribute VERT_ATTRIB_POS, and grab vertex processing 6601e04c3fSmrg * attribute VERT_ATTRIB_GENERIC0 from the VAO attribute 6701e04c3fSmrg * VERT_ATTRIB_GENERIC0. 6801e04c3fSmrg */ 6901e04c3fSmrg { 7001e04c3fSmrg VERT_ATTRIB_POS, /* VERT_ATTRIB_POS */ 7101e04c3fSmrg VERT_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 7201e04c3fSmrg VERT_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 7301e04c3fSmrg VERT_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 7401e04c3fSmrg VERT_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 7501e04c3fSmrg VERT_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 7601e04c3fSmrg VERT_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 7701e04c3fSmrg VERT_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 7801e04c3fSmrg VERT_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 7901e04c3fSmrg VERT_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 8001e04c3fSmrg VERT_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 8101e04c3fSmrg VERT_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 8201e04c3fSmrg VERT_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 8301e04c3fSmrg VERT_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 8401e04c3fSmrg VERT_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 8501e04c3fSmrg VERT_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 8601e04c3fSmrg VERT_ATTRIB_GENERIC0, /* VERT_ATTRIB_GENERIC0 */ 8701e04c3fSmrg VERT_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 8801e04c3fSmrg VERT_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 8901e04c3fSmrg VERT_ATTRIB_GENERIC3, /* VERT_ATTRIB_GENERIC3 */ 9001e04c3fSmrg VERT_ATTRIB_GENERIC4, /* VERT_ATTRIB_GENERIC4 */ 9101e04c3fSmrg VERT_ATTRIB_GENERIC5, /* VERT_ATTRIB_GENERIC5 */ 9201e04c3fSmrg VERT_ATTRIB_GENERIC6, /* VERT_ATTRIB_GENERIC6 */ 9301e04c3fSmrg VERT_ATTRIB_GENERIC7, /* VERT_ATTRIB_GENERIC7 */ 9401e04c3fSmrg VERT_ATTRIB_GENERIC8, /* VERT_ATTRIB_GENERIC8 */ 9501e04c3fSmrg VERT_ATTRIB_GENERIC9, /* VERT_ATTRIB_GENERIC9 */ 9601e04c3fSmrg VERT_ATTRIB_GENERIC10, /* VERT_ATTRIB_GENERIC10 */ 9701e04c3fSmrg VERT_ATTRIB_GENERIC11, /* VERT_ATTRIB_GENERIC11 */ 9801e04c3fSmrg VERT_ATTRIB_GENERIC12, /* VERT_ATTRIB_GENERIC12 */ 9901e04c3fSmrg VERT_ATTRIB_GENERIC13, /* VERT_ATTRIB_GENERIC13 */ 10001e04c3fSmrg VERT_ATTRIB_GENERIC14, /* VERT_ATTRIB_GENERIC14 */ 10101e04c3fSmrg VERT_ATTRIB_GENERIC15 /* VERT_ATTRIB_GENERIC15 */ 10201e04c3fSmrg }, 10301e04c3fSmrg 10401e04c3fSmrg /* ATTRIBUTE_MAP_MODE_POSITION 10501e04c3fSmrg * 10601e04c3fSmrg * Grab vertex processing attribute VERT_ATTRIB_POS as well as 10701e04c3fSmrg * vertex processing attribute VERT_ATTRIB_GENERIC0 from the 10801e04c3fSmrg * VAO attribute VERT_ATTRIB_POS. 10901e04c3fSmrg */ 11001e04c3fSmrg { 11101e04c3fSmrg VERT_ATTRIB_POS, /* VERT_ATTRIB_POS */ 11201e04c3fSmrg VERT_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 11301e04c3fSmrg VERT_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 11401e04c3fSmrg VERT_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 11501e04c3fSmrg VERT_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 11601e04c3fSmrg VERT_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 11701e04c3fSmrg VERT_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 11801e04c3fSmrg VERT_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 11901e04c3fSmrg VERT_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 12001e04c3fSmrg VERT_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 12101e04c3fSmrg VERT_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 12201e04c3fSmrg VERT_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 12301e04c3fSmrg VERT_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 12401e04c3fSmrg VERT_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 12501e04c3fSmrg VERT_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 12601e04c3fSmrg VERT_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 12701e04c3fSmrg VERT_ATTRIB_POS, /* VERT_ATTRIB_GENERIC0 */ 12801e04c3fSmrg VERT_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 12901e04c3fSmrg VERT_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 13001e04c3fSmrg VERT_ATTRIB_GENERIC3, /* VERT_ATTRIB_GENERIC3 */ 13101e04c3fSmrg VERT_ATTRIB_GENERIC4, /* VERT_ATTRIB_GENERIC4 */ 13201e04c3fSmrg VERT_ATTRIB_GENERIC5, /* VERT_ATTRIB_GENERIC5 */ 13301e04c3fSmrg VERT_ATTRIB_GENERIC6, /* VERT_ATTRIB_GENERIC6 */ 13401e04c3fSmrg VERT_ATTRIB_GENERIC7, /* VERT_ATTRIB_GENERIC7 */ 13501e04c3fSmrg VERT_ATTRIB_GENERIC8, /* VERT_ATTRIB_GENERIC8 */ 13601e04c3fSmrg VERT_ATTRIB_GENERIC9, /* VERT_ATTRIB_GENERIC9 */ 13701e04c3fSmrg VERT_ATTRIB_GENERIC10, /* VERT_ATTRIB_GENERIC10 */ 13801e04c3fSmrg VERT_ATTRIB_GENERIC11, /* VERT_ATTRIB_GENERIC11 */ 13901e04c3fSmrg VERT_ATTRIB_GENERIC12, /* VERT_ATTRIB_GENERIC12 */ 14001e04c3fSmrg VERT_ATTRIB_GENERIC13, /* VERT_ATTRIB_GENERIC13 */ 14101e04c3fSmrg VERT_ATTRIB_GENERIC14, /* VERT_ATTRIB_GENERIC14 */ 14201e04c3fSmrg VERT_ATTRIB_GENERIC15 /* VERT_ATTRIB_GENERIC15 */ 14301e04c3fSmrg }, 14401e04c3fSmrg 14501e04c3fSmrg /* ATTRIBUTE_MAP_MODE_GENERIC0 14601e04c3fSmrg * 14701e04c3fSmrg * Grab vertex processing attribute VERT_ATTRIB_POS as well as 14801e04c3fSmrg * vertex processing attribute VERT_ATTRIB_GENERIC0 from the 14901e04c3fSmrg * VAO attribute VERT_ATTRIB_GENERIC0. 15001e04c3fSmrg */ 15101e04c3fSmrg { 15201e04c3fSmrg VERT_ATTRIB_GENERIC0, /* VERT_ATTRIB_POS */ 15301e04c3fSmrg VERT_ATTRIB_NORMAL, /* VERT_ATTRIB_NORMAL */ 15401e04c3fSmrg VERT_ATTRIB_COLOR0, /* VERT_ATTRIB_COLOR0 */ 15501e04c3fSmrg VERT_ATTRIB_COLOR1, /* VERT_ATTRIB_COLOR1 */ 15601e04c3fSmrg VERT_ATTRIB_FOG, /* VERT_ATTRIB_FOG */ 15701e04c3fSmrg VERT_ATTRIB_COLOR_INDEX, /* VERT_ATTRIB_COLOR_INDEX */ 15801e04c3fSmrg VERT_ATTRIB_EDGEFLAG, /* VERT_ATTRIB_EDGEFLAG */ 15901e04c3fSmrg VERT_ATTRIB_TEX0, /* VERT_ATTRIB_TEX0 */ 16001e04c3fSmrg VERT_ATTRIB_TEX1, /* VERT_ATTRIB_TEX1 */ 16101e04c3fSmrg VERT_ATTRIB_TEX2, /* VERT_ATTRIB_TEX2 */ 16201e04c3fSmrg VERT_ATTRIB_TEX3, /* VERT_ATTRIB_TEX3 */ 16301e04c3fSmrg VERT_ATTRIB_TEX4, /* VERT_ATTRIB_TEX4 */ 16401e04c3fSmrg VERT_ATTRIB_TEX5, /* VERT_ATTRIB_TEX5 */ 16501e04c3fSmrg VERT_ATTRIB_TEX6, /* VERT_ATTRIB_TEX6 */ 16601e04c3fSmrg VERT_ATTRIB_TEX7, /* VERT_ATTRIB_TEX7 */ 16701e04c3fSmrg VERT_ATTRIB_POINT_SIZE, /* VERT_ATTRIB_POINT_SIZE */ 16801e04c3fSmrg VERT_ATTRIB_GENERIC0, /* VERT_ATTRIB_GENERIC0 */ 16901e04c3fSmrg VERT_ATTRIB_GENERIC1, /* VERT_ATTRIB_GENERIC1 */ 17001e04c3fSmrg VERT_ATTRIB_GENERIC2, /* VERT_ATTRIB_GENERIC2 */ 17101e04c3fSmrg VERT_ATTRIB_GENERIC3, /* VERT_ATTRIB_GENERIC3 */ 17201e04c3fSmrg VERT_ATTRIB_GENERIC4, /* VERT_ATTRIB_GENERIC4 */ 17301e04c3fSmrg VERT_ATTRIB_GENERIC5, /* VERT_ATTRIB_GENERIC5 */ 17401e04c3fSmrg VERT_ATTRIB_GENERIC6, /* VERT_ATTRIB_GENERIC6 */ 17501e04c3fSmrg VERT_ATTRIB_GENERIC7, /* VERT_ATTRIB_GENERIC7 */ 17601e04c3fSmrg VERT_ATTRIB_GENERIC8, /* VERT_ATTRIB_GENERIC8 */ 17701e04c3fSmrg VERT_ATTRIB_GENERIC9, /* VERT_ATTRIB_GENERIC9 */ 17801e04c3fSmrg VERT_ATTRIB_GENERIC10, /* VERT_ATTRIB_GENERIC10 */ 17901e04c3fSmrg VERT_ATTRIB_GENERIC11, /* VERT_ATTRIB_GENERIC11 */ 18001e04c3fSmrg VERT_ATTRIB_GENERIC12, /* VERT_ATTRIB_GENERIC12 */ 18101e04c3fSmrg VERT_ATTRIB_GENERIC13, /* VERT_ATTRIB_GENERIC13 */ 18201e04c3fSmrg VERT_ATTRIB_GENERIC14, /* VERT_ATTRIB_GENERIC14 */ 18301e04c3fSmrg VERT_ATTRIB_GENERIC15 /* VERT_ATTRIB_GENERIC15 */ 18401e04c3fSmrg } 18501e04c3fSmrg}; 1867117f1b4Smrg 1877117f1b4Smrg 1887117f1b4Smrg/** 1897117f1b4Smrg * Look up the array object for the given ID. 190af69d88dSmrg * 1917117f1b4Smrg * \returns 1927117f1b4Smrg * Either a pointer to the array object with the specified ID or \c NULL for 1937117f1b4Smrg * a non-existent ID. The spec defines ID 0 as being technically 1947117f1b4Smrg * non-existent. 1957117f1b4Smrg */ 1967117f1b4Smrg 197af69d88dSmrgstruct gl_vertex_array_object * 198af69d88dSmrg_mesa_lookup_vao(struct gl_context *ctx, GLuint id) 1997117f1b4Smrg{ 20001e04c3fSmrg /* The ARB_direct_state_access specification says: 20101e04c3fSmrg * 20201e04c3fSmrg * "<vaobj> is [compatibility profile: 20301e04c3fSmrg * zero, indicating the default vertex array object, or] 20401e04c3fSmrg * the name of the vertex array object." 20501e04c3fSmrg */ 20601e04c3fSmrg if (id == 0) { 20701e04c3fSmrg if (ctx->API == API_OPENGL_COMPAT) 20801e04c3fSmrg return ctx->Array.DefaultVAO; 20901e04c3fSmrg 2104a49301eSmrg return NULL; 21101e04c3fSmrg } else { 21201e04c3fSmrg struct gl_vertex_array_object *vao; 21301e04c3fSmrg 21401e04c3fSmrg if (ctx->Array.LastLookedUpVAO && 21501e04c3fSmrg ctx->Array.LastLookedUpVAO->Name == id) { 21601e04c3fSmrg vao = ctx->Array.LastLookedUpVAO; 21701e04c3fSmrg } else { 21801e04c3fSmrg vao = (struct gl_vertex_array_object *) 21901e04c3fSmrg _mesa_HashLookupLocked(ctx->Array.Objects, id); 22001e04c3fSmrg 22101e04c3fSmrg _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao); 22201e04c3fSmrg } 22301e04c3fSmrg 22401e04c3fSmrg return vao; 22501e04c3fSmrg } 22601e04c3fSmrg} 22701e04c3fSmrg 22801e04c3fSmrg 22901e04c3fSmrg/** 23001e04c3fSmrg * Looks up the array object for the given ID. 23101e04c3fSmrg * 23201e04c3fSmrg * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION 23301e04c3fSmrg * error if the array object does not exist. It also returns the default 23401e04c3fSmrg * array object when ctx is a compatibility profile context and id is zero. 23501e04c3fSmrg */ 23601e04c3fSmrgstruct gl_vertex_array_object * 23701e04c3fSmrg_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller) 23801e04c3fSmrg{ 23901e04c3fSmrg /* The ARB_direct_state_access specification says: 24001e04c3fSmrg * 24101e04c3fSmrg * "<vaobj> is [compatibility profile: 24201e04c3fSmrg * zero, indicating the default vertex array object, or] 24301e04c3fSmrg * the name of the vertex array object." 24401e04c3fSmrg */ 24501e04c3fSmrg if (id == 0) { 24601e04c3fSmrg if (ctx->API == API_OPENGL_CORE) { 24701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 24801e04c3fSmrg "%s(zero is not valid vaobj name in a core profile " 24901e04c3fSmrg "context)", caller); 25001e04c3fSmrg return NULL; 25101e04c3fSmrg } 25201e04c3fSmrg 25301e04c3fSmrg return ctx->Array.DefaultVAO; 25401e04c3fSmrg } else { 25501e04c3fSmrg struct gl_vertex_array_object *vao; 25601e04c3fSmrg 25701e04c3fSmrg if (ctx->Array.LastLookedUpVAO && 25801e04c3fSmrg ctx->Array.LastLookedUpVAO->Name == id) { 25901e04c3fSmrg vao = ctx->Array.LastLookedUpVAO; 26001e04c3fSmrg } else { 26101e04c3fSmrg vao = (struct gl_vertex_array_object *) 26201e04c3fSmrg _mesa_HashLookupLocked(ctx->Array.Objects, id); 26301e04c3fSmrg 26401e04c3fSmrg /* The ARB_direct_state_access specification says: 26501e04c3fSmrg * 26601e04c3fSmrg * "An INVALID_OPERATION error is generated if <vaobj> is not 26701e04c3fSmrg * [compatibility profile: zero or] the name of an existing 26801e04c3fSmrg * vertex array object." 26901e04c3fSmrg */ 27001e04c3fSmrg if (!vao || !vao->EverBound) { 27101e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 27201e04c3fSmrg "%s(non-existent vaobj=%u)", caller, id); 27301e04c3fSmrg return NULL; 27401e04c3fSmrg } 27501e04c3fSmrg 27601e04c3fSmrg _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao); 27701e04c3fSmrg } 27801e04c3fSmrg 27901e04c3fSmrg return vao; 28001e04c3fSmrg } 2814a49301eSmrg} 2824a49301eSmrg 2834a49301eSmrg 2844a49301eSmrg/** 285af69d88dSmrg * For all the vertex binding points in the array object, unbind any pointers 2864a49301eSmrg * to any buffer objects (VBOs). 2874a49301eSmrg * This is done just prior to array object destruction. 2884a49301eSmrg */ 2894a49301eSmrgstatic void 290af69d88dSmrgunbind_array_object_vbos(struct gl_context *ctx, struct gl_vertex_array_object *obj) 2914a49301eSmrg{ 2924a49301eSmrg GLuint i; 2934a49301eSmrg 29401e04c3fSmrg for (i = 0; i < ARRAY_SIZE(obj->BufferBinding); i++) 29501e04c3fSmrg _mesa_reference_buffer_object(ctx, &obj->BufferBinding[i].BufferObj, NULL); 2967117f1b4Smrg} 2977117f1b4Smrg 2987117f1b4Smrg 2997117f1b4Smrg/** 3007117f1b4Smrg * Allocate and initialize a new vertex array object. 3017117f1b4Smrg */ 302af69d88dSmrgstruct gl_vertex_array_object * 303af69d88dSmrg_mesa_new_vao(struct gl_context *ctx, GLuint name) 3047117f1b4Smrg{ 305af69d88dSmrg struct gl_vertex_array_object *obj = CALLOC_STRUCT(gl_vertex_array_object); 3067117f1b4Smrg if (obj) 307af69d88dSmrg _mesa_initialize_vao(ctx, obj, name); 3087117f1b4Smrg return obj; 3097117f1b4Smrg} 3107117f1b4Smrg 3117117f1b4Smrg 3127117f1b4Smrg/** 3137117f1b4Smrg * Delete an array object. 3147117f1b4Smrg */ 3157117f1b4Smrgvoid 316af69d88dSmrg_mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj) 3177117f1b4Smrg{ 3184a49301eSmrg unbind_array_object_vbos(ctx, obj); 319af69d88dSmrg _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL); 320af69d88dSmrg free(obj->Label); 321cdc920a0Smrg free(obj); 3227117f1b4Smrg} 3237117f1b4Smrg 3247117f1b4Smrg 3254a49301eSmrg/** 326af69d88dSmrg * Set ptr to vao w/ reference counting. 327af69d88dSmrg * Note: this should only be called from the _mesa_reference_vao() 328af69d88dSmrg * inline function. 3294a49301eSmrg */ 3304a49301eSmrgvoid 331af69d88dSmrg_mesa_reference_vao_(struct gl_context *ctx, 332af69d88dSmrg struct gl_vertex_array_object **ptr, 333af69d88dSmrg struct gl_vertex_array_object *vao) 3344a49301eSmrg{ 335af69d88dSmrg assert(*ptr != vao); 3364a49301eSmrg 3374a49301eSmrg if (*ptr) { 3384a49301eSmrg /* Unreference the old array object */ 339af69d88dSmrg struct gl_vertex_array_object *oldObj = *ptr; 3404a49301eSmrg 34101e04c3fSmrg bool deleteFlag; 34201e04c3fSmrg if (oldObj->SharedAndImmutable) { 34301e04c3fSmrg deleteFlag = p_atomic_dec_zero(&oldObj->RefCount); 34401e04c3fSmrg } else { 34501e04c3fSmrg assert(oldObj->RefCount > 0); 34601e04c3fSmrg oldObj->RefCount--; 34701e04c3fSmrg deleteFlag = (oldObj->RefCount == 0); 3484a49301eSmrg } 3494a49301eSmrg 35001e04c3fSmrg if (deleteFlag) 35101e04c3fSmrg _mesa_delete_vao(ctx, oldObj); 35201e04c3fSmrg 3534a49301eSmrg *ptr = NULL; 3544a49301eSmrg } 35501e04c3fSmrg assert(!*ptr); 3564a49301eSmrg 357af69d88dSmrg if (vao) { 3584a49301eSmrg /* reference new array object */ 35901e04c3fSmrg if (vao->SharedAndImmutable) { 36001e04c3fSmrg p_atomic_inc(&vao->RefCount); 36101e04c3fSmrg } else { 36201e04c3fSmrg assert(vao->RefCount > 0); 363af69d88dSmrg vao->RefCount++; 3644a49301eSmrg } 36501e04c3fSmrg 36601e04c3fSmrg *ptr = vao; 3674a49301eSmrg } 3684a49301eSmrg} 3694a49301eSmrg 3704a49301eSmrg 37101e04c3fSmrg/** 37201e04c3fSmrg * Initialize attributes of a vertex array within a vertex array object. 37301e04c3fSmrg * \param vao the container vertex array object 37401e04c3fSmrg * \param index which array in the VAO to initialize 37501e04c3fSmrg * \param size number of components (1, 2, 3 or 4) per attribute 37601e04c3fSmrg * \param type datatype of the attribute (GL_FLOAT, GL_INT, etc). 37701e04c3fSmrg */ 3784a49301eSmrgstatic void 3793464ebd5Sriastradhinit_array(struct gl_context *ctx, 38001e04c3fSmrg struct gl_vertex_array_object *vao, 38101e04c3fSmrg gl_vert_attrib index, GLint size, GLint type) 3824a49301eSmrg{ 38301e04c3fSmrg assert(index < ARRAY_SIZE(vao->VertexAttrib)); 38401e04c3fSmrg struct gl_array_attributes *array = &vao->VertexAttrib[index]; 38501e04c3fSmrg assert(index < ARRAY_SIZE(vao->BufferBinding)); 38601e04c3fSmrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index]; 387af69d88dSmrg 3884a49301eSmrg array->Size = size; 3894a49301eSmrg array->Type = type; 3904a49301eSmrg array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */ 3914a49301eSmrg array->Stride = 0; 3924a49301eSmrg array->Ptr = NULL; 393af69d88dSmrg array->RelativeOffset = 0; 3944a49301eSmrg array->Enabled = GL_FALSE; 3954a49301eSmrg array->Normalized = GL_FALSE; 396af69d88dSmrg array->Integer = GL_FALSE; 39701e04c3fSmrg array->Doubles = GL_FALSE; 3983464ebd5Sriastradh array->_ElementSize = size * _mesa_sizeof_type(type); 39901e04c3fSmrg ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex, 40001e04c3fSmrg VERT_ATTRIB_MAX - 1); 40101e04c3fSmrg array->BufferBindingIndex = index; 402af69d88dSmrg 403af69d88dSmrg binding->Offset = 0; 404af69d88dSmrg binding->Stride = array->_ElementSize; 405af69d88dSmrg binding->BufferObj = NULL; 40601e04c3fSmrg binding->_BoundArrays = BITFIELD_BIT(index); 407af69d88dSmrg 4084a49301eSmrg /* Vertex array buffers */ 409af69d88dSmrg _mesa_reference_buffer_object(ctx, &binding->BufferObj, 4104a49301eSmrg ctx->Shared->NullBufferObj); 4114a49301eSmrg} 4124a49301eSmrg 4134a49301eSmrg 4144a49301eSmrg/** 415af69d88dSmrg * Initialize a gl_vertex_array_object's arrays. 4164a49301eSmrg */ 4177117f1b4Smrgvoid 418af69d88dSmrg_mesa_initialize_vao(struct gl_context *ctx, 41901e04c3fSmrg struct gl_vertex_array_object *vao, 420af69d88dSmrg GLuint name) 4217117f1b4Smrg{ 4227117f1b4Smrg GLuint i; 4237117f1b4Smrg 42401e04c3fSmrg vao->Name = name; 4257117f1b4Smrg 42601e04c3fSmrg vao->RefCount = 1; 42701e04c3fSmrg vao->SharedAndImmutable = false; 4284a49301eSmrg 4294a49301eSmrg /* Init the individual arrays */ 43001e04c3fSmrg for (i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) { 431af69d88dSmrg switch (i) { 432af69d88dSmrg case VERT_ATTRIB_NORMAL: 43301e04c3fSmrg init_array(ctx, vao, VERT_ATTRIB_NORMAL, 3, GL_FLOAT); 434af69d88dSmrg break; 435af69d88dSmrg case VERT_ATTRIB_COLOR1: 43601e04c3fSmrg init_array(ctx, vao, VERT_ATTRIB_COLOR1, 3, GL_FLOAT); 437af69d88dSmrg break; 438af69d88dSmrg case VERT_ATTRIB_FOG: 43901e04c3fSmrg init_array(ctx, vao, VERT_ATTRIB_FOG, 1, GL_FLOAT); 440af69d88dSmrg break; 441af69d88dSmrg case VERT_ATTRIB_COLOR_INDEX: 44201e04c3fSmrg init_array(ctx, vao, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT); 443af69d88dSmrg break; 444af69d88dSmrg case VERT_ATTRIB_EDGEFLAG: 44501e04c3fSmrg init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL); 446af69d88dSmrg break; 447af69d88dSmrg case VERT_ATTRIB_POINT_SIZE: 44801e04c3fSmrg init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT); 449af69d88dSmrg break; 450af69d88dSmrg default: 45101e04c3fSmrg init_array(ctx, vao, i, 4, GL_FLOAT); 452af69d88dSmrg break; 453af69d88dSmrg } 4547117f1b4Smrg } 4557117f1b4Smrg 45601e04c3fSmrg vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY; 45701e04c3fSmrg 45801e04c3fSmrg _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, 459af69d88dSmrg ctx->Shared->NullBufferObj); 4607117f1b4Smrg} 4617117f1b4Smrg 4627117f1b4Smrg 4637117f1b4Smrg/** 46401e04c3fSmrg * Compute the offset range for the provided binding. 46501e04c3fSmrg * 46601e04c3fSmrg * This is a helper function for the below. 4677117f1b4Smrg */ 4684a49301eSmrgstatic void 46901e04c3fSmrgcompute_vbo_offset_range(const struct gl_vertex_array_object *vao, 47001e04c3fSmrg const struct gl_vertex_buffer_binding *binding, 47101e04c3fSmrg GLsizeiptr* min, GLsizeiptr* max) 4727117f1b4Smrg{ 47301e04c3fSmrg /* The function is meant to work on VBO bindings */ 47401e04c3fSmrg assert(_mesa_is_bufferobj(binding->BufferObj)); 47501e04c3fSmrg 47601e04c3fSmrg /* Start with an inverted range of relative offsets. */ 47701e04c3fSmrg GLuint min_offset = ~(GLuint)0; 47801e04c3fSmrg GLuint max_offset = 0; 47901e04c3fSmrg 48001e04c3fSmrg /* We work on the unmapped originaly VAO array entries. */ 48101e04c3fSmrg GLbitfield mask = vao->_Enabled & binding->_BoundArrays; 48201e04c3fSmrg /* The binding should be active somehow, not to return inverted ranges */ 48301e04c3fSmrg assert(mask); 48401e04c3fSmrg while (mask) { 48501e04c3fSmrg const int i = u_bit_scan(&mask); 48601e04c3fSmrg const GLuint off = vao->VertexAttrib[i].RelativeOffset; 48701e04c3fSmrg min_offset = MIN2(off, min_offset); 48801e04c3fSmrg max_offset = MAX2(off, max_offset); 4897117f1b4Smrg } 49001e04c3fSmrg 49101e04c3fSmrg *min = binding->Offset + (GLsizeiptr)min_offset; 49201e04c3fSmrg *max = binding->Offset + (GLsizeiptr)max_offset; 4937117f1b4Smrg} 4947117f1b4Smrg 4957117f1b4Smrg 4967117f1b4Smrg/** 49701e04c3fSmrg * Update the unique binding and pos/generic0 map tracking in the vao. 49801e04c3fSmrg * 49901e04c3fSmrg * The idea is to build up information in the vao so that a consuming 50001e04c3fSmrg * backend can execute the following to set up buffer and vertex element 50101e04c3fSmrg * information: 50201e04c3fSmrg * 50301e04c3fSmrg * const GLbitfield inputs_read = VERT_BIT_ALL; // backend vp inputs 50401e04c3fSmrg * 50501e04c3fSmrg * // Attribute data is in a VBO. 50601e04c3fSmrg * GLbitfield vbomask = inputs_read & _mesa_draw_vbo_array_bits(ctx); 50701e04c3fSmrg * while (vbomask) { 50801e04c3fSmrg * // The attribute index to start pulling a binding 50901e04c3fSmrg * const gl_vert_attrib i = ffs(vbomask) - 1; 51001e04c3fSmrg * const struct gl_vertex_buffer_binding *const binding 51101e04c3fSmrg * = _mesa_draw_buffer_binding(vao, i); 51201e04c3fSmrg * 51301e04c3fSmrg * <insert code to handle the vertex buffer object at binding> 51401e04c3fSmrg * 51501e04c3fSmrg * const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding); 51601e04c3fSmrg * GLbitfield attrmask = vbomask & boundmask; 51701e04c3fSmrg * assert(attrmask); 51801e04c3fSmrg * // Walk attributes belonging to the binding 51901e04c3fSmrg * while (attrmask) { 52001e04c3fSmrg * const gl_vert_attrib attr = u_bit_scan(&attrmask); 52101e04c3fSmrg * const struct gl_array_attributes *const attrib 52201e04c3fSmrg * = _mesa_draw_array_attrib(vao, attr); 52301e04c3fSmrg * 52401e04c3fSmrg * <insert code to handle the vertex element refering to the binding> 52501e04c3fSmrg * } 52601e04c3fSmrg * vbomask &= ~boundmask; 52701e04c3fSmrg * } 52801e04c3fSmrg * 52901e04c3fSmrg * // Process user space buffers 53001e04c3fSmrg * GLbitfield usermask = inputs_read & _mesa_draw_user_array_bits(ctx); 53101e04c3fSmrg * while (usermask) { 53201e04c3fSmrg * // The attribute index to start pulling a binding 53301e04c3fSmrg * const gl_vert_attrib i = ffs(usermask) - 1; 53401e04c3fSmrg * const struct gl_vertex_buffer_binding *const binding 53501e04c3fSmrg * = _mesa_draw_buffer_binding(vao, i); 53601e04c3fSmrg * 53701e04c3fSmrg * <insert code to handle a set of interleaved user space arrays at binding> 53801e04c3fSmrg * 53901e04c3fSmrg * const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding); 54001e04c3fSmrg * GLbitfield attrmask = usermask & boundmask; 54101e04c3fSmrg * assert(attrmask); 54201e04c3fSmrg * // Walk interleaved attributes with a common stride and instance divisor 54301e04c3fSmrg * while (attrmask) { 54401e04c3fSmrg * const gl_vert_attrib attr = u_bit_scan(&attrmask); 54501e04c3fSmrg * const struct gl_array_attributes *const attrib 54601e04c3fSmrg * = _mesa_draw_array_attrib(vao, attr); 54701e04c3fSmrg * 54801e04c3fSmrg * <insert code to handle non vbo vertex arrays> 54901e04c3fSmrg * } 55001e04c3fSmrg * usermask &= ~boundmask; 55101e04c3fSmrg * } 55201e04c3fSmrg * 55301e04c3fSmrg * // Process values that should have better been uniforms in the application 55401e04c3fSmrg * GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx); 55501e04c3fSmrg * while (curmask) { 55601e04c3fSmrg * const gl_vert_attrib attr = u_bit_scan(&curmask); 55701e04c3fSmrg * const struct gl_array_attributes *const attrib 55801e04c3fSmrg * = _mesa_draw_current_attrib(ctx, attr); 55901e04c3fSmrg * 56001e04c3fSmrg * <insert code to handle current values> 56101e04c3fSmrg * } 56201e04c3fSmrg * 56301e04c3fSmrg * 56401e04c3fSmrg * Note that the scan below must not incoporate any context state. 56501e04c3fSmrg * The rationale is that once a VAO is finalized it should not 56601e04c3fSmrg * be touched anymore. That means, do not incorporate the 56701e04c3fSmrg * gl_context::Array._DrawVAOEnabledAttribs bitmask into this scan. 56801e04c3fSmrg * A backend driver may further reduce the handled vertex processing 56901e04c3fSmrg * inputs based on their vertex shader inputs. But scanning for 57001e04c3fSmrg * collapsable binding points to reduce relocs is done based on the 57101e04c3fSmrg * enabled arrays. 57201e04c3fSmrg * Also VAOs may be shared between contexts due to their use in dlists 57301e04c3fSmrg * thus no context state should bleed into the VAO. 5747117f1b4Smrg */ 57501e04c3fSmrgvoid 57601e04c3fSmrg_mesa_update_vao_derived_arrays(struct gl_context *ctx, 57701e04c3fSmrg struct gl_vertex_array_object *vao) 5787117f1b4Smrg{ 57901e04c3fSmrg /* Make sure we do not run into problems with shared objects */ 58001e04c3fSmrg assert(!vao->SharedAndImmutable || vao->NewArrays == 0); 58101e04c3fSmrg 58201e04c3fSmrg /* Limit used for common binding scanning below. */ 58301e04c3fSmrg const GLsizeiptr MaxRelativeOffset = 58401e04c3fSmrg ctx->Const.MaxVertexAttribRelativeOffset; 58501e04c3fSmrg 58601e04c3fSmrg /* The gl_vertex_array_object::_AttributeMapMode denotes the way 58701e04c3fSmrg * VERT_ATTRIB_{POS,GENERIC0} mapping is done. 58801e04c3fSmrg * 58901e04c3fSmrg * This mapping is used to map between the OpenGL api visible 59001e04c3fSmrg * VERT_ATTRIB_* arrays to mesa driver arrayinputs or shader inputs. 59101e04c3fSmrg * The mapping only depends on the enabled bits of the 59201e04c3fSmrg * VERT_ATTRIB_{POS,GENERIC0} arrays and is tracked in the VAO. 59301e04c3fSmrg * 59401e04c3fSmrg * This map needs to be applied when finally translating to the bitmasks 59501e04c3fSmrg * as consumed by the driver backends. The duplicate scanning is here 59601e04c3fSmrg * can as well be done in the OpenGL API numbering without this map. 59701e04c3fSmrg */ 59801e04c3fSmrg const gl_attribute_map_mode mode = vao->_AttributeMapMode; 59901e04c3fSmrg /* Enabled array bits. */ 60001e04c3fSmrg const GLbitfield enabled = vao->_Enabled; 60101e04c3fSmrg /* VBO array bits. */ 60201e04c3fSmrg const GLbitfield vbos = vao->VertexAttribBufferMask; 60301e04c3fSmrg 60401e04c3fSmrg /* Compute and store effectively enabled and mapped vbo arrays */ 60501e04c3fSmrg vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos); 60601e04c3fSmrg /* Walk those enabled arrays that have a real vbo attached */ 60701e04c3fSmrg GLbitfield mask = enabled; 60801e04c3fSmrg while (mask) { 60901e04c3fSmrg /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */ 61001e04c3fSmrg const int i = ffs(mask) - 1; 61101e04c3fSmrg /* The binding from the first to be processed attribute. */ 61201e04c3fSmrg const GLuint bindex = vao->VertexAttrib[i].BufferBindingIndex; 61301e04c3fSmrg struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex]; 61401e04c3fSmrg 61501e04c3fSmrg /* The scan goes different for user space arrays than vbos */ 61601e04c3fSmrg if (_mesa_is_bufferobj(binding->BufferObj)) { 61701e04c3fSmrg /* The bound arrays. */ 61801e04c3fSmrg const GLbitfield bound = enabled & binding->_BoundArrays; 61901e04c3fSmrg 62001e04c3fSmrg /* Start this current effective binding with the actual bound arrays */ 62101e04c3fSmrg GLbitfield eff_bound_arrays = bound; 62201e04c3fSmrg 62301e04c3fSmrg /* 62401e04c3fSmrg * If there is nothing left to scan just update the effective binding 62501e04c3fSmrg * information. If the VAO is already only using a single binding point 62601e04c3fSmrg * we end up here. So the overhead of this scan for an application 62701e04c3fSmrg * carefully preparing the VAO for draw is low. 62801e04c3fSmrg */ 6297117f1b4Smrg 63001e04c3fSmrg GLbitfield scanmask = mask & vbos & ~bound; 63101e04c3fSmrg /* Is there something left to scan? */ 63201e04c3fSmrg if (scanmask == 0) { 63301e04c3fSmrg /* Just update the back reference from the attrib to the binding and 63401e04c3fSmrg * the effective offset. 63501e04c3fSmrg */ 63601e04c3fSmrg GLbitfield attrmask = eff_bound_arrays; 63701e04c3fSmrg while (attrmask) { 63801e04c3fSmrg const int j = u_bit_scan(&attrmask); 63901e04c3fSmrg struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 64001e04c3fSmrg 64101e04c3fSmrg /* Update the index into the common binding point and offset */ 64201e04c3fSmrg attrib2->_EffBufferBindingIndex = bindex; 64301e04c3fSmrg attrib2->_EffRelativeOffset = attrib2->RelativeOffset; 64401e04c3fSmrg assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset); 64501e04c3fSmrg 64601e04c3fSmrg /* Only enabled arrays shall appear in the unique bindings */ 64701e04c3fSmrg assert(attrib2->Enabled); 64801e04c3fSmrg } 64901e04c3fSmrg /* Finally this is the set of effectively bound arrays with the 65001e04c3fSmrg * original binding offset. 65101e04c3fSmrg */ 65201e04c3fSmrg binding->_EffOffset = binding->Offset; 65301e04c3fSmrg /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 65401e04c3fSmrg binding->_EffBoundArrays = 65501e04c3fSmrg _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 65601e04c3fSmrg 65701e04c3fSmrg } else { 65801e04c3fSmrg /* In the VBO case, scan for attribute/binding 65901e04c3fSmrg * combinations with relative bindings in the range of 66001e04c3fSmrg * [0, ctx->Const.MaxVertexAttribRelativeOffset]. 66101e04c3fSmrg * Note that this does also go beyond just interleaved arrays 66201e04c3fSmrg * as long as they use the same VBO, binding parameters and the 66301e04c3fSmrg * offsets stay within bounds that the backend still can handle. 66401e04c3fSmrg */ 66501e04c3fSmrg 66601e04c3fSmrg GLsizeiptr min_offset, max_offset; 66701e04c3fSmrg compute_vbo_offset_range(vao, binding, &min_offset, &max_offset); 66801e04c3fSmrg assert(max_offset <= min_offset + MaxRelativeOffset); 66901e04c3fSmrg 67001e04c3fSmrg /* Now scan. */ 67101e04c3fSmrg while (scanmask) { 67201e04c3fSmrg /* Do not use u_bit_scan as we can walk multiple 67301e04c3fSmrg * attrib arrays at once 67401e04c3fSmrg */ 67501e04c3fSmrg const int j = ffs(scanmask) - 1; 67601e04c3fSmrg const struct gl_array_attributes *attrib2 = 67701e04c3fSmrg &vao->VertexAttrib[j]; 67801e04c3fSmrg const struct gl_vertex_buffer_binding *binding2 = 67901e04c3fSmrg &vao->BufferBinding[attrib2->BufferBindingIndex]; 68001e04c3fSmrg 68101e04c3fSmrg /* Remove those attrib bits from the mask that are bound to the 68201e04c3fSmrg * same effective binding point. 68301e04c3fSmrg */ 68401e04c3fSmrg const GLbitfield bound2 = enabled & binding2->_BoundArrays; 68501e04c3fSmrg scanmask &= ~bound2; 68601e04c3fSmrg 68701e04c3fSmrg /* Check if we have an identical binding */ 68801e04c3fSmrg if (binding->Stride != binding2->Stride) 68901e04c3fSmrg continue; 69001e04c3fSmrg if (binding->InstanceDivisor != binding2->InstanceDivisor) 69101e04c3fSmrg continue; 69201e04c3fSmrg if (binding->BufferObj != binding2->BufferObj) 69301e04c3fSmrg continue; 69401e04c3fSmrg /* Check if we can fold both bindings into a common binding */ 69501e04c3fSmrg GLsizeiptr min_offset2, max_offset2; 69601e04c3fSmrg compute_vbo_offset_range(vao, binding2, 69701e04c3fSmrg &min_offset2, &max_offset2); 69801e04c3fSmrg /* If the relative offset is within the limits ... */ 69901e04c3fSmrg if (min_offset + MaxRelativeOffset < max_offset2) 70001e04c3fSmrg continue; 70101e04c3fSmrg if (min_offset2 + MaxRelativeOffset < max_offset) 70201e04c3fSmrg continue; 70301e04c3fSmrg /* ... add this array to the effective binding */ 70401e04c3fSmrg eff_bound_arrays |= bound2; 70501e04c3fSmrg min_offset = MIN2(min_offset, min_offset2); 70601e04c3fSmrg max_offset = MAX2(max_offset, max_offset2); 70701e04c3fSmrg assert(max_offset <= min_offset + MaxRelativeOffset); 70801e04c3fSmrg } 70901e04c3fSmrg 71001e04c3fSmrg /* Update the back reference from the attrib to the binding */ 71101e04c3fSmrg GLbitfield attrmask = eff_bound_arrays; 71201e04c3fSmrg while (attrmask) { 71301e04c3fSmrg const int j = u_bit_scan(&attrmask); 71401e04c3fSmrg struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 71501e04c3fSmrg const struct gl_vertex_buffer_binding *binding2 = 71601e04c3fSmrg &vao->BufferBinding[attrib2->BufferBindingIndex]; 71701e04c3fSmrg 71801e04c3fSmrg /* Update the index into the common binding point and offset */ 71901e04c3fSmrg attrib2->_EffBufferBindingIndex = bindex; 72001e04c3fSmrg attrib2->_EffRelativeOffset = 72101e04c3fSmrg binding2->Offset + attrib2->RelativeOffset - min_offset; 72201e04c3fSmrg assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset); 72301e04c3fSmrg 72401e04c3fSmrg /* Only enabled arrays shall appear in the unique bindings */ 72501e04c3fSmrg assert(attrib2->Enabled); 72601e04c3fSmrg } 72701e04c3fSmrg /* Finally this is the set of effectively bound arrays */ 72801e04c3fSmrg binding->_EffOffset = min_offset; 72901e04c3fSmrg /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 73001e04c3fSmrg binding->_EffBoundArrays = 73101e04c3fSmrg _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 73201e04c3fSmrg } 7337117f1b4Smrg 73401e04c3fSmrg /* Mark all the effective bound arrays as processed. */ 73501e04c3fSmrg mask &= ~eff_bound_arrays; 7364a49301eSmrg 73701e04c3fSmrg } else { 73801e04c3fSmrg /* Scanning of common bindings for user space arrays. 73901e04c3fSmrg */ 740af69d88dSmrg 74101e04c3fSmrg const struct gl_array_attributes *attrib = &vao->VertexAttrib[i]; 74201e04c3fSmrg const GLbitfield bound = VERT_BIT(i); 743af69d88dSmrg 74401e04c3fSmrg /* Note that user space array pointers can only happen using a one 74501e04c3fSmrg * to one binding point to array mapping. 74601e04c3fSmrg * The OpenGL 4.x/ARB_vertex_attrib_binding api does not support 74701e04c3fSmrg * user space arrays collected at multiple binding points. 74801e04c3fSmrg * The only provider of user space interleaved arrays with a single 74901e04c3fSmrg * binding point is the mesa internal vbo module. But that one 75001e04c3fSmrg * provides a perfect interleaved set of arrays. 75101e04c3fSmrg * 75201e04c3fSmrg * If this would not be true we would potentially get attribute arrays 75301e04c3fSmrg * with user space pointers that may not lie within the 75401e04c3fSmrg * MaxRelativeOffset range but still attached to a single binding. 75501e04c3fSmrg * Then we would need to store the effective attribute and binding 75601e04c3fSmrg * grouping information in a seperate array beside 75701e04c3fSmrg * gl_array_attributes/gl_vertex_buffer_binding. 75801e04c3fSmrg */ 75901e04c3fSmrg assert(util_bitcount(binding->_BoundArrays & vao->_Enabled) == 1 76001e04c3fSmrg || (vao->_Enabled & ~binding->_BoundArrays) == 0); 761af69d88dSmrg 76201e04c3fSmrg /* Start this current effective binding with the array */ 76301e04c3fSmrg GLbitfield eff_bound_arrays = bound; 7644a49301eSmrg 76501e04c3fSmrg const GLubyte *ptr = attrib->Ptr; 76601e04c3fSmrg unsigned vertex_end = attrib->_ElementSize; 7674a49301eSmrg 76801e04c3fSmrg /* Walk other user space arrays and see which are interleaved 76901e04c3fSmrg * using the same binding parameters. 77001e04c3fSmrg */ 77101e04c3fSmrg GLbitfield scanmask = mask & ~vbos & ~bound; 77201e04c3fSmrg while (scanmask) { 77301e04c3fSmrg const int j = u_bit_scan(&scanmask); 77401e04c3fSmrg const struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 77501e04c3fSmrg const struct gl_vertex_buffer_binding *binding2 = 77601e04c3fSmrg &vao->BufferBinding[attrib2->BufferBindingIndex]; 77701e04c3fSmrg 77801e04c3fSmrg /* See the comment at the same assert above. */ 77901e04c3fSmrg assert(util_bitcount(binding2->_BoundArrays & vao->_Enabled) == 1 78001e04c3fSmrg || (vao->_Enabled & ~binding->_BoundArrays) == 0); 78101e04c3fSmrg 78201e04c3fSmrg /* Check if we have an identical binding */ 78301e04c3fSmrg if (binding->Stride != binding2->Stride) 78401e04c3fSmrg continue; 78501e04c3fSmrg if (binding->InstanceDivisor != binding2->InstanceDivisor) 78601e04c3fSmrg continue; 78701e04c3fSmrg if (ptr <= attrib2->Ptr) { 78801e04c3fSmrg if (ptr + binding->Stride < attrib2->Ptr + attrib2->_ElementSize) 78901e04c3fSmrg continue; 79001e04c3fSmrg unsigned end = attrib2->Ptr + attrib2->_ElementSize - ptr; 79101e04c3fSmrg vertex_end = MAX2(vertex_end, end); 79201e04c3fSmrg } else { 79301e04c3fSmrg if (attrib2->Ptr + binding->Stride < ptr + vertex_end) 79401e04c3fSmrg continue; 79501e04c3fSmrg vertex_end += (GLsizei)(ptr - attrib2->Ptr); 79601e04c3fSmrg ptr = attrib2->Ptr; 79701e04c3fSmrg } 79801e04c3fSmrg 79901e04c3fSmrg /* User space buffer object */ 80001e04c3fSmrg assert(!_mesa_is_bufferobj(binding2->BufferObj)); 80101e04c3fSmrg 80201e04c3fSmrg eff_bound_arrays |= VERT_BIT(j); 80301e04c3fSmrg } 804af69d88dSmrg 80501e04c3fSmrg /* Update the back reference from the attrib to the binding */ 80601e04c3fSmrg GLbitfield attrmask = eff_bound_arrays; 80701e04c3fSmrg while (attrmask) { 80801e04c3fSmrg const int j = u_bit_scan(&attrmask); 80901e04c3fSmrg struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j]; 81001e04c3fSmrg 81101e04c3fSmrg /* Update the index into the common binding point and the offset */ 81201e04c3fSmrg attrib2->_EffBufferBindingIndex = bindex; 81301e04c3fSmrg attrib2->_EffRelativeOffset = attrib2->Ptr - ptr; 81401e04c3fSmrg assert(attrib2->_EffRelativeOffset <= binding->Stride); 81501e04c3fSmrg 81601e04c3fSmrg /* Only enabled arrays shall appear in the unique bindings */ 81701e04c3fSmrg assert(attrib2->Enabled); 81801e04c3fSmrg } 81901e04c3fSmrg /* Finally this is the set of effectively bound arrays */ 82001e04c3fSmrg binding->_EffOffset = (GLintptr)ptr; 82101e04c3fSmrg /* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */ 82201e04c3fSmrg binding->_EffBoundArrays = 82301e04c3fSmrg _mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays); 82401e04c3fSmrg 82501e04c3fSmrg /* Mark all the effective bound arrays as processed. */ 82601e04c3fSmrg mask &= ~eff_bound_arrays; 82701e04c3fSmrg } 828af69d88dSmrg } 8294a49301eSmrg 83001e04c3fSmrg#ifndef NDEBUG 83101e04c3fSmrg /* Make sure the above code works as expected. */ 83201e04c3fSmrg for (gl_vert_attrib attr = 0; attr < VERT_ATTRIB_MAX; ++attr) { 83301e04c3fSmrg /* Query the original api defined attrib/binding information ... */ 83401e04c3fSmrg const unsigned char *const map =_mesa_vao_attribute_map[mode]; 83501e04c3fSmrg const struct gl_array_attributes *attrib = &vao->VertexAttrib[map[attr]]; 83601e04c3fSmrg if (attrib->Enabled) { 83701e04c3fSmrg const struct gl_vertex_buffer_binding *binding = 83801e04c3fSmrg &vao->BufferBinding[attrib->BufferBindingIndex]; 83901e04c3fSmrg /* ... and compare that with the computed attrib/binding */ 84001e04c3fSmrg const struct gl_vertex_buffer_binding *binding2 = 84101e04c3fSmrg &vao->BufferBinding[attrib->_EffBufferBindingIndex]; 84201e04c3fSmrg assert(binding->Stride == binding2->Stride); 84301e04c3fSmrg assert(binding->InstanceDivisor == binding2->InstanceDivisor); 84401e04c3fSmrg assert(binding->BufferObj == binding2->BufferObj); 84501e04c3fSmrg if (_mesa_is_bufferobj(binding->BufferObj)) { 84601e04c3fSmrg assert(attrib->_EffRelativeOffset <= MaxRelativeOffset); 84701e04c3fSmrg assert(binding->Offset + attrib->RelativeOffset == 84801e04c3fSmrg binding2->_EffOffset + attrib->_EffRelativeOffset); 84901e04c3fSmrg } else { 85001e04c3fSmrg assert(attrib->_EffRelativeOffset < binding->Stride); 85101e04c3fSmrg assert((GLintptr)attrib->Ptr == 85201e04c3fSmrg binding2->_EffOffset + attrib->_EffRelativeOffset); 85301e04c3fSmrg } 85401e04c3fSmrg } 85501e04c3fSmrg } 85601e04c3fSmrg#endif 857af69d88dSmrg} 858af69d88dSmrg 859af69d88dSmrg 860af69d88dSmrgvoid 86101e04c3fSmrg_mesa_set_vao_immutable(struct gl_context *ctx, 86201e04c3fSmrg struct gl_vertex_array_object *vao) 863af69d88dSmrg{ 86401e04c3fSmrg _mesa_update_vao_derived_arrays(ctx, vao); 86501e04c3fSmrg vao->NewArrays = 0; 86601e04c3fSmrg vao->SharedAndImmutable = true; 86701e04c3fSmrg} 868af69d88dSmrg 869af69d88dSmrg 87001e04c3fSmrgbool 87101e04c3fSmrg_mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao) 87201e04c3fSmrg{ 87301e04c3fSmrg /* Walk those enabled arrays that have the default vbo attached */ 87401e04c3fSmrg GLbitfield mask = vao->_Enabled & ~vao->VertexAttribBufferMask; 875af69d88dSmrg 87601e04c3fSmrg while (mask) { 87701e04c3fSmrg /* Do not use u_bit_scan64 as we can walk multiple 87801e04c3fSmrg * attrib arrays at once 87901e04c3fSmrg */ 88001e04c3fSmrg const int i = ffs(mask) - 1; 88101e04c3fSmrg const struct gl_array_attributes *attrib_array = 88201e04c3fSmrg &vao->VertexAttrib[i]; 88301e04c3fSmrg const struct gl_vertex_buffer_binding *buffer_binding = 88401e04c3fSmrg &vao->BufferBinding[attrib_array->BufferBindingIndex]; 88501e04c3fSmrg 88601e04c3fSmrg /* Only enabled arrays shall appear in the _Enabled bitmask */ 88701e04c3fSmrg assert(attrib_array->Enabled); 88801e04c3fSmrg /* We have already masked out vao->VertexAttribBufferMask */ 88901e04c3fSmrg assert(!_mesa_is_bufferobj(buffer_binding->BufferObj)); 89001e04c3fSmrg 89101e04c3fSmrg /* Bail out once we find the first non vbo with a non zero stride */ 89201e04c3fSmrg if (buffer_binding->Stride != 0) 89301e04c3fSmrg return false; 89401e04c3fSmrg 89501e04c3fSmrg /* Note that we cannot use the xor variant since the _BoundArray mask 89601e04c3fSmrg * may contain array attributes that are bound but not enabled. 89701e04c3fSmrg */ 89801e04c3fSmrg mask &= ~buffer_binding->_BoundArrays; 899af69d88dSmrg } 90001e04c3fSmrg 90101e04c3fSmrg return true; 902c1f859d4Smrg} 903c1f859d4Smrg 90401e04c3fSmrgbool 90501e04c3fSmrg_mesa_all_buffers_are_unmapped(const struct gl_vertex_array_object *vao) 90601e04c3fSmrg{ 90701e04c3fSmrg /* Walk the enabled arrays that have a vbo attached */ 90801e04c3fSmrg GLbitfield mask = vao->_Enabled & vao->VertexAttribBufferMask; 90901e04c3fSmrg 91001e04c3fSmrg while (mask) { 91101e04c3fSmrg const int i = ffs(mask) - 1; 91201e04c3fSmrg const struct gl_array_attributes *attrib_array = 91301e04c3fSmrg &vao->VertexAttrib[i]; 91401e04c3fSmrg const struct gl_vertex_buffer_binding *buffer_binding = 91501e04c3fSmrg &vao->BufferBinding[attrib_array->BufferBindingIndex]; 91601e04c3fSmrg 91701e04c3fSmrg /* Only enabled arrays shall appear in the _Enabled bitmask */ 91801e04c3fSmrg assert(attrib_array->Enabled); 91901e04c3fSmrg /* We have already masked with vao->VertexAttribBufferMask */ 92001e04c3fSmrg assert(_mesa_is_bufferobj(buffer_binding->BufferObj)); 92101e04c3fSmrg 92201e04c3fSmrg /* Bail out once we find the first disallowed mapping */ 92301e04c3fSmrg if (_mesa_check_disallowed_mapping(buffer_binding->BufferObj)) 92401e04c3fSmrg return false; 92501e04c3fSmrg 92601e04c3fSmrg /* We have handled everything that is bound to this buffer_binding. */ 92701e04c3fSmrg mask &= ~buffer_binding->_BoundArrays; 92801e04c3fSmrg } 92901e04c3fSmrg 93001e04c3fSmrg return true; 93101e04c3fSmrg} 932c1f859d4Smrg 9337117f1b4Smrg/**********************************************************************/ 9347117f1b4Smrg/* API Functions */ 9357117f1b4Smrg/**********************************************************************/ 9367117f1b4Smrg 9374a49301eSmrg 9387117f1b4Smrg/** 93901e04c3fSmrg * ARB version of glBindVertexArray() 9407117f1b4Smrg */ 94101e04c3fSmrgstatic ALWAYS_INLINE void 94201e04c3fSmrgbind_vertex_array(struct gl_context *ctx, GLuint id, bool no_error) 9437117f1b4Smrg{ 94401e04c3fSmrg struct gl_vertex_array_object *const oldObj = ctx->Array.VAO; 945af69d88dSmrg struct gl_vertex_array_object *newObj = NULL; 9467117f1b4Smrg 94701e04c3fSmrg assert(oldObj != NULL); 9487117f1b4Smrg 94901e04c3fSmrg if (oldObj->Name == id) 9507117f1b4Smrg return; /* rebinding the same array object- no change */ 9517117f1b4Smrg 9527117f1b4Smrg /* 9534a49301eSmrg * Get pointer to new array object (newObj) 9547117f1b4Smrg */ 9557117f1b4Smrg if (id == 0) { 9567117f1b4Smrg /* The spec says there is no array object named 0, but we use 9577117f1b4Smrg * one internally because it simplifies things. 9587117f1b4Smrg */ 959af69d88dSmrg newObj = ctx->Array.DefaultVAO; 9607117f1b4Smrg } 9617117f1b4Smrg else { 9627117f1b4Smrg /* non-default array object */ 963af69d88dSmrg newObj = _mesa_lookup_vao(ctx, id); 96401e04c3fSmrg if (!no_error && !newObj) { 96501e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 96601e04c3fSmrg "glBindVertexArray(non-gen name)"); 96701e04c3fSmrg return; 9687117f1b4Smrg } 969af69d88dSmrg 97001e04c3fSmrg newObj->EverBound = GL_TRUE; 971af69d88dSmrg } 972af69d88dSmrg 97301e04c3fSmrg /* The _DrawArrays pointer is pointing at the VAO being unbound and 97401e04c3fSmrg * that VAO may be in the process of being deleted. If it's not going 97501e04c3fSmrg * to be deleted, this will have no effect, because the pointer needs 97601e04c3fSmrg * to be updated by the VBO module anyway. 97701e04c3fSmrg * 97801e04c3fSmrg * Before the VBO module can update the pointer, we have to set it 97901e04c3fSmrg * to NULL for drivers not to set up arrays which are not bound, 98001e04c3fSmrg * or to prevent a crash if the VAO being unbound is going to be 98101e04c3fSmrg * deleted. 98201e04c3fSmrg */ 98301e04c3fSmrg _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0); 9847117f1b4Smrg 9857117f1b4Smrg ctx->NewState |= _NEW_ARRAY; 986af69d88dSmrg _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj); 9874a49301eSmrg} 9884a49301eSmrg 9894a49301eSmrg 9904a49301eSmrgvoid GLAPIENTRY 99101e04c3fSmrg_mesa_BindVertexArray_no_error(GLuint id) 9924a49301eSmrg{ 9934a49301eSmrg GET_CURRENT_CONTEXT(ctx); 99401e04c3fSmrg bind_vertex_array(ctx, id, true); 9954a49301eSmrg} 9964a49301eSmrg 9974a49301eSmrg 9984a49301eSmrgvoid GLAPIENTRY 99901e04c3fSmrg_mesa_BindVertexArray(GLuint id) 10004a49301eSmrg{ 10014a49301eSmrg GET_CURRENT_CONTEXT(ctx); 100201e04c3fSmrg bind_vertex_array(ctx, id, false); 10037117f1b4Smrg} 10047117f1b4Smrg 10057117f1b4Smrg 10067117f1b4Smrg/** 10077117f1b4Smrg * Delete a set of array objects. 1008af69d88dSmrg * 10097117f1b4Smrg * \param n Number of array objects to delete. 10107117f1b4Smrg * \param ids Array of \c n array object IDs. 10117117f1b4Smrg */ 101201e04c3fSmrgstatic void 101301e04c3fSmrgdelete_vertex_arrays(struct gl_context *ctx, GLsizei n, const GLuint *ids) 10147117f1b4Smrg{ 10157117f1b4Smrg GLsizei i; 10167117f1b4Smrg 10177117f1b4Smrg for (i = 0; i < n; i++) { 101801e04c3fSmrg /* IDs equal to 0 should be silently ignored. */ 101901e04c3fSmrg if (!ids[i]) 102001e04c3fSmrg continue; 102101e04c3fSmrg 1022af69d88dSmrg struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]); 10237117f1b4Smrg 102401e04c3fSmrg if (obj) { 102501e04c3fSmrg assert(obj->Name == ids[i]); 10267117f1b4Smrg 102701e04c3fSmrg /* If the array object is currently bound, the spec says "the binding 102801e04c3fSmrg * for that object reverts to zero and the default vertex array 102901e04c3fSmrg * becomes current." 103001e04c3fSmrg */ 103101e04c3fSmrg if (obj == ctx->Array.VAO) 103201e04c3fSmrg _mesa_BindVertexArray_no_error(0); 10337117f1b4Smrg 103401e04c3fSmrg /* The ID is immediately freed for re-use */ 103501e04c3fSmrg _mesa_HashRemoveLocked(ctx->Array.Objects, obj->Name); 103601e04c3fSmrg 103701e04c3fSmrg if (ctx->Array.LastLookedUpVAO == obj) 103801e04c3fSmrg _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL); 103901e04c3fSmrg if (ctx->Array._DrawVAO == obj) 104001e04c3fSmrg _mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0); 10414a49301eSmrg 10424a49301eSmrg /* Unreference the array object. 10434a49301eSmrg * If refcount hits zero, the object will be deleted. 10444a49301eSmrg */ 1045af69d88dSmrg _mesa_reference_vao(ctx, &obj, NULL); 10467117f1b4Smrg } 10477117f1b4Smrg } 10487117f1b4Smrg} 10497117f1b4Smrg 10507117f1b4Smrg 105101e04c3fSmrgvoid GLAPIENTRY 105201e04c3fSmrg_mesa_DeleteVertexArrays_no_error(GLsizei n, const GLuint *ids) 105301e04c3fSmrg{ 105401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 105501e04c3fSmrg delete_vertex_arrays(ctx, n, ids); 105601e04c3fSmrg} 105701e04c3fSmrg 105801e04c3fSmrg 105901e04c3fSmrgvoid GLAPIENTRY 106001e04c3fSmrg_mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids) 106101e04c3fSmrg{ 106201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 106301e04c3fSmrg 106401e04c3fSmrg if (n < 0) { 106501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)"); 106601e04c3fSmrg return; 106701e04c3fSmrg } 106801e04c3fSmrg 106901e04c3fSmrg delete_vertex_arrays(ctx, n, ids); 107001e04c3fSmrg} 107101e04c3fSmrg 107201e04c3fSmrg 10737117f1b4Smrg/** 10747117f1b4Smrg * Generate a set of unique array object IDs and store them in \c arrays. 107501e04c3fSmrg * Helper for _mesa_GenVertexArrays() and _mesa_CreateVertexArrays() 107601e04c3fSmrg * below. 107701e04c3fSmrg * 10787117f1b4Smrg * \param n Number of IDs to generate. 10797117f1b4Smrg * \param arrays Array of \c n locations to store the IDs. 108001e04c3fSmrg * \param create Indicates that the objects should also be created. 108101e04c3fSmrg * \param func The name of the GL entry point. 10827117f1b4Smrg */ 1083af69d88dSmrgstatic void 108401e04c3fSmrggen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays, 108501e04c3fSmrg bool create, const char *func) 10867117f1b4Smrg{ 10877117f1b4Smrg GLuint first; 10887117f1b4Smrg GLint i; 10897117f1b4Smrg 109001e04c3fSmrg if (!arrays) 10917117f1b4Smrg return; 10927117f1b4Smrg 10934a49301eSmrg first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); 10947117f1b4Smrg 109501e04c3fSmrg /* For the sake of simplicity we create the array objects in both 109601e04c3fSmrg * the Gen* and Create* cases. The only difference is the value of 109701e04c3fSmrg * EverBound, which is set to true in the Create* case. 109801e04c3fSmrg */ 10997117f1b4Smrg for (i = 0; i < n; i++) { 1100af69d88dSmrg struct gl_vertex_array_object *obj; 11017117f1b4Smrg GLuint name = first + i; 11027117f1b4Smrg 110301e04c3fSmrg obj = _mesa_new_vao(ctx, name); 11047117f1b4Smrg if (!obj) { 110501e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 11067117f1b4Smrg return; 11077117f1b4Smrg } 110801e04c3fSmrg obj->EverBound = create; 110901e04c3fSmrg _mesa_HashInsertLocked(ctx->Array.Objects, obj->Name, obj); 11107117f1b4Smrg arrays[i] = first + i; 11117117f1b4Smrg } 11124a49301eSmrg} 11134a49301eSmrg 11144a49301eSmrg 111501e04c3fSmrgstatic void 111601e04c3fSmrggen_vertex_arrays_err(struct gl_context *ctx, GLsizei n, GLuint *arrays, 111701e04c3fSmrg bool create, const char *func) 111801e04c3fSmrg{ 111901e04c3fSmrg if (n < 0) { 112001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); 112101e04c3fSmrg return; 112201e04c3fSmrg } 112301e04c3fSmrg 112401e04c3fSmrg gen_vertex_arrays(ctx, n, arrays, create, func); 112501e04c3fSmrg} 112601e04c3fSmrg 112701e04c3fSmrg 11284a49301eSmrg/** 11294a49301eSmrg * ARB version of glGenVertexArrays() 11304a49301eSmrg * All arrays will be required to live in VBOs. 11314a49301eSmrg */ 113201e04c3fSmrgvoid GLAPIENTRY 113301e04c3fSmrg_mesa_GenVertexArrays_no_error(GLsizei n, GLuint *arrays) 113401e04c3fSmrg{ 113501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 113601e04c3fSmrg gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays"); 113701e04c3fSmrg} 113801e04c3fSmrg 113901e04c3fSmrg 11404a49301eSmrgvoid GLAPIENTRY 11414a49301eSmrg_mesa_GenVertexArrays(GLsizei n, GLuint *arrays) 11424a49301eSmrg{ 11434a49301eSmrg GET_CURRENT_CONTEXT(ctx); 114401e04c3fSmrg gen_vertex_arrays_err(ctx, n, arrays, false, "glGenVertexArrays"); 11454a49301eSmrg} 11464a49301eSmrg 11477117f1b4Smrg 11484a49301eSmrg/** 114901e04c3fSmrg * ARB_direct_state_access 115001e04c3fSmrg * Generates ID's and creates the array objects. 11514a49301eSmrg */ 11524a49301eSmrgvoid GLAPIENTRY 115301e04c3fSmrg_mesa_CreateVertexArrays_no_error(GLsizei n, GLuint *arrays) 11544a49301eSmrg{ 11554a49301eSmrg GET_CURRENT_CONTEXT(ctx); 115601e04c3fSmrg gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays"); 115701e04c3fSmrg} 115801e04c3fSmrg 115901e04c3fSmrg 116001e04c3fSmrgvoid GLAPIENTRY 116101e04c3fSmrg_mesa_CreateVertexArrays(GLsizei n, GLuint *arrays) 116201e04c3fSmrg{ 116301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 116401e04c3fSmrg gen_vertex_arrays_err(ctx, n, arrays, true, "glCreateVertexArrays"); 11657117f1b4Smrg} 11667117f1b4Smrg 11677117f1b4Smrg 11687117f1b4Smrg/** 11697117f1b4Smrg * Determine if ID is the name of an array object. 1170af69d88dSmrg * 11717117f1b4Smrg * \param id ID of the potential array object. 1172af69d88dSmrg * \return \c GL_TRUE if \c id is the name of a array object, 11737117f1b4Smrg * \c GL_FALSE otherwise. 11747117f1b4Smrg */ 11757117f1b4SmrgGLboolean GLAPIENTRY 1176af69d88dSmrg_mesa_IsVertexArray( GLuint id ) 11777117f1b4Smrg{ 1178af69d88dSmrg struct gl_vertex_array_object * obj; 11797117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 11807117f1b4Smrg ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 11817117f1b4Smrg 1182af69d88dSmrg obj = _mesa_lookup_vao(ctx, id); 11837117f1b4Smrg 118401e04c3fSmrg return obj != NULL && obj->EverBound; 118501e04c3fSmrg} 118601e04c3fSmrg 118701e04c3fSmrg 118801e04c3fSmrg/** 118901e04c3fSmrg * Sets the element array buffer binding of a vertex array object. 119001e04c3fSmrg * 119101e04c3fSmrg * This is the ARB_direct_state_access equivalent of 119201e04c3fSmrg * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer). 119301e04c3fSmrg */ 119401e04c3fSmrgstatic ALWAYS_INLINE void 119501e04c3fSmrgvertex_array_element_buffer(struct gl_context *ctx, GLuint vaobj, GLuint buffer, 119601e04c3fSmrg bool no_error) 119701e04c3fSmrg{ 119801e04c3fSmrg struct gl_vertex_array_object *vao; 119901e04c3fSmrg struct gl_buffer_object *bufObj; 120001e04c3fSmrg 120101e04c3fSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 120201e04c3fSmrg 120301e04c3fSmrg if (!no_error) { 120401e04c3fSmrg /* The GL_ARB_direct_state_access specification says: 120501e04c3fSmrg * 120601e04c3fSmrg * "An INVALID_OPERATION error is generated by 120701e04c3fSmrg * VertexArrayElementBuffer if <vaobj> is not [compatibility profile: 120801e04c3fSmrg * zero or] the name of an existing vertex array object." 120901e04c3fSmrg */ 121001e04c3fSmrg vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer"); 121101e04c3fSmrg if (!vao) 121201e04c3fSmrg return; 121301e04c3fSmrg } else { 121401e04c3fSmrg vao = _mesa_lookup_vao(ctx, vaobj); 121501e04c3fSmrg } 121601e04c3fSmrg 121701e04c3fSmrg if (buffer != 0) { 121801e04c3fSmrg if (!no_error) { 121901e04c3fSmrg /* The GL_ARB_direct_state_access specification says: 122001e04c3fSmrg * 122101e04c3fSmrg * "An INVALID_OPERATION error is generated if <buffer> is not zero 122201e04c3fSmrg * or the name of an existing buffer object." 122301e04c3fSmrg */ 122401e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 122501e04c3fSmrg "glVertexArrayElementBuffer"); 122601e04c3fSmrg } else { 122701e04c3fSmrg bufObj = _mesa_lookup_bufferobj(ctx, buffer); 122801e04c3fSmrg } 122901e04c3fSmrg } else { 123001e04c3fSmrg bufObj = ctx->Shared->NullBufferObj; 123101e04c3fSmrg } 123201e04c3fSmrg 123301e04c3fSmrg if (bufObj) 123401e04c3fSmrg _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj); 123501e04c3fSmrg} 123601e04c3fSmrg 123701e04c3fSmrg 123801e04c3fSmrgvoid GLAPIENTRY 123901e04c3fSmrg_mesa_VertexArrayElementBuffer_no_error(GLuint vaobj, GLuint buffer) 124001e04c3fSmrg{ 124101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 124201e04c3fSmrg vertex_array_element_buffer(ctx, vaobj, buffer, true); 124301e04c3fSmrg} 124401e04c3fSmrg 124501e04c3fSmrg 124601e04c3fSmrgvoid GLAPIENTRY 124701e04c3fSmrg_mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer) 124801e04c3fSmrg{ 124901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 125001e04c3fSmrg vertex_array_element_buffer(ctx, vaobj, buffer, false); 125101e04c3fSmrg} 125201e04c3fSmrg 125301e04c3fSmrg 125401e04c3fSmrgvoid GLAPIENTRY 125501e04c3fSmrg_mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param) 125601e04c3fSmrg{ 125701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 125801e04c3fSmrg struct gl_vertex_array_object *vao; 125901e04c3fSmrg 126001e04c3fSmrg ASSERT_OUTSIDE_BEGIN_END(ctx); 126101e04c3fSmrg 126201e04c3fSmrg /* The GL_ARB_direct_state_access specification says: 126301e04c3fSmrg * 126401e04c3fSmrg * "An INVALID_OPERATION error is generated if <vaobj> is not 126501e04c3fSmrg * [compatibility profile: zero or] the name of an existing 126601e04c3fSmrg * vertex array object." 126701e04c3fSmrg */ 126801e04c3fSmrg vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv"); 126901e04c3fSmrg if (!vao) 127001e04c3fSmrg return; 127101e04c3fSmrg 127201e04c3fSmrg /* The GL_ARB_direct_state_access specification says: 127301e04c3fSmrg * 127401e04c3fSmrg * "An INVALID_ENUM error is generated if <pname> is not 127501e04c3fSmrg * ELEMENT_ARRAY_BUFFER_BINDING." 127601e04c3fSmrg */ 127701e04c3fSmrg if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) { 127801e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 127901e04c3fSmrg "glGetVertexArrayiv(pname != " 128001e04c3fSmrg "GL_ELEMENT_ARRAY_BUFFER_BINDING)"); 128101e04c3fSmrg return; 128201e04c3fSmrg } 128301e04c3fSmrg 128401e04c3fSmrg param[0] = vao->IndexBufferObj->Name; 12857117f1b4Smrg} 1286