Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
      5  * (C) Copyright IBM Corporation 2006
      6  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included
     16  * in all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24  * OTHER DEALINGS IN THE SOFTWARE.
     25  */
     26 
     27 
     28 /**
     29  * \file arrayobj.c
     30  *
     31  * Implementation of Vertex Array Objects (VAOs), from OpenGL 3.1+,
     32  * the GL_ARB_vertex_array_object extension, or the older
     33  * GL_APPLE_vertex_array_object extension.
     34  *
     35  * \todo
     36  * The code in this file borrows a lot from bufferobj.c.  There's a certain
     37  * amount of cruft left over from that origin that may be unnecessary.
     38  *
     39  * \author Ian Romanick <idr (at) us.ibm.com>
     40  * \author Brian Paul
     41  */
     42 
     43 
     44 #include "glheader.h"
     45 #include "hash.h"
     46 #include "image.h"
     47 #include "imports.h"
     48 #include "context.h"
     49 #include "bufferobj.h"
     50 #include "arrayobj.h"
     51 #include "macros.h"
     52 #include "mtypes.h"
     53 #include "varray.h"
     54 #include "main/dispatch.h"
     55 #include "util/bitscan.h"
     56 
     57 
     58 /**
     59  * Look up the array object for the given ID.
     60  *
     61  * \returns
     62  * Either a pointer to the array object with the specified ID or \c NULL for
     63  * a non-existent ID.  The spec defines ID 0 as being technically
     64  * non-existent.
     65  */
     66 
     67 struct gl_vertex_array_object *
     68 _mesa_lookup_vao(struct gl_context *ctx, GLuint id)
     69 {
     70    if (id == 0)
     71       return NULL;
     72    else
     73       return (struct gl_vertex_array_object *)
     74          _mesa_HashLookup(ctx->Array.Objects, id);
     75 }
     76 
     77 
     78 /**
     79  * Looks up the array object for the given ID.
     80  *
     81  * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION
     82  * error if the array object does not exist. It also returns the default
     83  * array object when ctx is a compatibility profile context and id is zero.
     84  */
     85 struct gl_vertex_array_object *
     86 _mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller)
     87 {
     88    /* The ARB_direct_state_access specification says:
     89     *
     90     *    "<vaobj> is [compatibility profile:
     91     *     zero, indicating the default vertex array object, or]
     92     *     the name of the vertex array object."
     93     */
     94    if (id == 0) {
     95       if (ctx->API == API_OPENGL_CORE) {
     96          _mesa_error(ctx, GL_INVALID_OPERATION,
     97                      "%s(zero is not valid vaobj name in a core profile "
     98                      "context)", caller);
     99          return NULL;
    100       }
    101 
    102       return ctx->Array.DefaultVAO;
    103    } else {
    104       struct gl_vertex_array_object *vao;
    105 
    106       if (ctx->Array.LastLookedUpVAO &&
    107           ctx->Array.LastLookedUpVAO->Name == id) {
    108          vao = ctx->Array.LastLookedUpVAO;
    109       } else {
    110          vao = (struct gl_vertex_array_object *)
    111             _mesa_HashLookup(ctx->Array.Objects, id);
    112 
    113          /* The ARB_direct_state_access specification says:
    114           *
    115           *    "An INVALID_OPERATION error is generated if <vaobj> is not
    116           *     [compatibility profile: zero or] the name of an existing
    117           *     vertex array object."
    118           */
    119          if (!vao || !vao->EverBound) {
    120             _mesa_error(ctx, GL_INVALID_OPERATION,
    121                         "%s(non-existent vaobj=%u)", caller, id);
    122             return NULL;
    123          }
    124 
    125          _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao);
    126       }
    127 
    128       return vao;
    129    }
    130 }
    131 
    132 
    133 /**
    134  * For all the vertex binding points in the array object, unbind any pointers
    135  * to any buffer objects (VBOs).
    136  * This is done just prior to array object destruction.
    137  */
    138 static void
    139 unbind_array_object_vbos(struct gl_context *ctx, struct gl_vertex_array_object *obj)
    140 {
    141    GLuint i;
    142 
    143    for (i = 0; i < ARRAY_SIZE(obj->BufferBinding); i++)
    144       _mesa_reference_buffer_object(ctx, &obj->BufferBinding[i].BufferObj, NULL);
    145 
    146    for (i = 0; i < ARRAY_SIZE(obj->_VertexAttrib); i++)
    147       _mesa_reference_buffer_object(ctx, &obj->_VertexAttrib[i].BufferObj, NULL);
    148 }
    149 
    150 
    151 /**
    152  * Allocate and initialize a new vertex array object.
    153  */
    154 struct gl_vertex_array_object *
    155 _mesa_new_vao(struct gl_context *ctx, GLuint name)
    156 {
    157    struct gl_vertex_array_object *obj = CALLOC_STRUCT(gl_vertex_array_object);
    158    if (obj)
    159       _mesa_initialize_vao(ctx, obj, name);
    160    return obj;
    161 }
    162 
    163 
    164 /**
    165  * Delete an array object.
    166  */
    167 void
    168 _mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj)
    169 {
    170    unbind_array_object_vbos(ctx, obj);
    171    _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL);
    172    mtx_destroy(&obj->Mutex);
    173    free(obj->Label);
    174    free(obj);
    175 }
    176 
    177 
    178 /**
    179  * Set ptr to vao w/ reference counting.
    180  * Note: this should only be called from the _mesa_reference_vao()
    181  * inline function.
    182  */
    183 void
    184 _mesa_reference_vao_(struct gl_context *ctx,
    185                      struct gl_vertex_array_object **ptr,
    186                      struct gl_vertex_array_object *vao)
    187 {
    188    assert(*ptr != vao);
    189 
    190    if (*ptr) {
    191       /* Unreference the old array object */
    192       GLboolean deleteFlag = GL_FALSE;
    193       struct gl_vertex_array_object *oldObj = *ptr;
    194 
    195       mtx_lock(&oldObj->Mutex);
    196       assert(oldObj->RefCount > 0);
    197       oldObj->RefCount--;
    198       deleteFlag = (oldObj->RefCount == 0);
    199       mtx_unlock(&oldObj->Mutex);
    200 
    201       if (deleteFlag)
    202          _mesa_delete_vao(ctx, oldObj);
    203 
    204       *ptr = NULL;
    205    }
    206    assert(!*ptr);
    207 
    208    if (vao) {
    209       /* reference new array object */
    210       mtx_lock(&vao->Mutex);
    211       if (vao->RefCount == 0) {
    212          /* this array's being deleted (look just above) */
    213          /* Not sure this can every really happen.  Warn if it does. */
    214          _mesa_problem(NULL, "referencing deleted array object");
    215          *ptr = NULL;
    216       }
    217       else {
    218          vao->RefCount++;
    219          *ptr = vao;
    220       }
    221       mtx_unlock(&vao->Mutex);
    222    }
    223 }
    224 
    225 
    226 /**
    227  * Initialize attribtes of a vertex array within a vertex array object.
    228  * \param vao  the container vertex array object
    229  * \param index  which array in the VAO to initialize
    230  * \param size  number of components (1, 2, 3 or 4) per attribute
    231  * \param type  datatype of the attribute (GL_FLOAT, GL_INT, etc).
    232  */
    233 static void
    234 init_array(struct gl_context *ctx,
    235            struct gl_vertex_array_object *vao,
    236            GLuint index, GLint size, GLint type)
    237 {
    238    struct gl_array_attributes *array = &vao->VertexAttrib[index];
    239    struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
    240 
    241    array->Size = size;
    242    array->Type = type;
    243    array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
    244    array->Stride = 0;
    245    array->Ptr = NULL;
    246    array->RelativeOffset = 0;
    247    array->Enabled = GL_FALSE;
    248    array->Normalized = GL_FALSE;
    249    array->Integer = GL_FALSE;
    250    array->Doubles = GL_FALSE;
    251    array->_ElementSize = size * _mesa_sizeof_type(type);
    252    array->BufferBindingIndex = index;
    253 
    254    binding->Offset = 0;
    255    binding->Stride = array->_ElementSize;
    256    binding->BufferObj = NULL;
    257    binding->_BoundArrays = BITFIELD64_BIT(index);
    258 
    259    /* Vertex array buffers */
    260    _mesa_reference_buffer_object(ctx, &binding->BufferObj,
    261                                  ctx->Shared->NullBufferObj);
    262 }
    263 
    264 
    265 /**
    266  * Initialize a gl_vertex_array_object's arrays.
    267  */
    268 void
    269 _mesa_initialize_vao(struct gl_context *ctx,
    270                      struct gl_vertex_array_object *vao,
    271                      GLuint name)
    272 {
    273    GLuint i;
    274 
    275    vao->Name = name;
    276 
    277    mtx_init(&vao->Mutex, mtx_plain);
    278    vao->RefCount = 1;
    279 
    280    /* Init the individual arrays */
    281    for (i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) {
    282       switch (i) {
    283       case VERT_ATTRIB_WEIGHT:
    284          init_array(ctx, vao, VERT_ATTRIB_WEIGHT, 1, GL_FLOAT);
    285          break;
    286       case VERT_ATTRIB_NORMAL:
    287          init_array(ctx, vao, VERT_ATTRIB_NORMAL, 3, GL_FLOAT);
    288          break;
    289       case VERT_ATTRIB_COLOR1:
    290          init_array(ctx, vao, VERT_ATTRIB_COLOR1, 3, GL_FLOAT);
    291          break;
    292       case VERT_ATTRIB_FOG:
    293          init_array(ctx, vao, VERT_ATTRIB_FOG, 1, GL_FLOAT);
    294          break;
    295       case VERT_ATTRIB_COLOR_INDEX:
    296          init_array(ctx, vao, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT);
    297          break;
    298       case VERT_ATTRIB_EDGEFLAG:
    299          init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL);
    300          break;
    301       case VERT_ATTRIB_POINT_SIZE:
    302          init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT);
    303          break;
    304       default:
    305          init_array(ctx, vao, i, 4, GL_FLOAT);
    306          break;
    307       }
    308    }
    309 
    310    _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj,
    311                                  ctx->Shared->NullBufferObj);
    312 }
    313 
    314 
    315 /**
    316  * Add the given array object to the array object pool.
    317  */
    318 static void
    319 save_array_object(struct gl_context *ctx, struct gl_vertex_array_object *vao)
    320 {
    321    if (vao->Name > 0) {
    322       /* insert into hash table */
    323       _mesa_HashInsert(ctx->Array.Objects, vao->Name, vao);
    324    }
    325 }
    326 
    327 
    328 /**
    329  * Remove the given array object from the array object pool.
    330  * Do not deallocate the array object though.
    331  */
    332 static void
    333 remove_array_object(struct gl_context *ctx, struct gl_vertex_array_object *vao)
    334 {
    335    if (vao->Name > 0) {
    336       /* remove from hash table */
    337       _mesa_HashRemove(ctx->Array.Objects, vao->Name);
    338    }
    339 }
    340 
    341 
    342 /**
    343  * Updates the derived gl_vertex_arrays when a gl_vertex_attrib_array
    344  * or a gl_vertex_buffer_binding has changed.
    345  */
    346 void
    347 _mesa_update_vao_client_arrays(struct gl_context *ctx,
    348                                struct gl_vertex_array_object *vao)
    349 {
    350    GLbitfield64 arrays = vao->NewArrays;
    351 
    352    while (arrays) {
    353       const int attrib = u_bit_scan64(&arrays);
    354       struct gl_vertex_array *client_array = &vao->_VertexAttrib[attrib];
    355       const struct gl_array_attributes *attrib_array =
    356          &vao->VertexAttrib[attrib];
    357       const struct gl_vertex_buffer_binding *buffer_binding =
    358          &vao->BufferBinding[attrib_array->BufferBindingIndex];
    359 
    360       _mesa_update_client_array(ctx, client_array, attrib_array,
    361                                 buffer_binding);
    362    }
    363 }
    364 
    365 
    366 bool
    367 _mesa_all_varyings_in_vbos(const struct gl_vertex_array_object *vao)
    368 {
    369    /* Walk those enabled arrays that have the default vbo attached */
    370    GLbitfield64 mask = vao->_Enabled & ~vao->VertexAttribBufferMask;
    371 
    372    while (mask) {
    373       /* Do not use u_bit_scan64 as we can walk multiple
    374        * attrib arrays at once
    375        */
    376       const int i = ffsll(mask) - 1;
    377       const struct gl_array_attributes *attrib_array =
    378          &vao->VertexAttrib[i];
    379       const struct gl_vertex_buffer_binding *buffer_binding =
    380          &vao->BufferBinding[attrib_array->BufferBindingIndex];
    381 
    382       /* Only enabled arrays shall appear in the _Enabled bitmask */
    383       assert(attrib_array->Enabled);
    384       /* We have already masked out vao->VertexAttribBufferMask  */
    385       assert(!_mesa_is_bufferobj(buffer_binding->BufferObj));
    386 
    387       /* Bail out once we find the first non vbo with a non zero stride */
    388       if (buffer_binding->Stride != 0)
    389          return false;
    390 
    391       /* Note that we cannot use the xor variant since the _BoundArray mask
    392        * may contain array attributes that are bound but not enabled.
    393        */
    394       mask &= ~buffer_binding->_BoundArrays;
    395    }
    396 
    397    return true;
    398 }
    399 
    400 bool
    401 _mesa_all_buffers_are_unmapped(const struct gl_vertex_array_object *vao)
    402 {
    403    /* Walk the enabled arrays that have a vbo attached */
    404    GLbitfield64 mask = vao->_Enabled & vao->VertexAttribBufferMask;
    405 
    406    while (mask) {
    407       const int i = ffsll(mask) - 1;
    408       const struct gl_array_attributes *attrib_array =
    409          &vao->VertexAttrib[i];
    410       const struct gl_vertex_buffer_binding *buffer_binding =
    411          &vao->BufferBinding[attrib_array->BufferBindingIndex];
    412 
    413       /* Only enabled arrays shall appear in the _Enabled bitmask */
    414       assert(attrib_array->Enabled);
    415       /* We have already masked with vao->VertexAttribBufferMask  */
    416       assert(_mesa_is_bufferobj(buffer_binding->BufferObj));
    417 
    418       /* Bail out once we find the first disallowed mapping */
    419       if (_mesa_check_disallowed_mapping(buffer_binding->BufferObj))
    420          return false;
    421 
    422       /* We have handled everything that is bound to this buffer_binding. */
    423       mask &= ~buffer_binding->_BoundArrays;
    424    }
    425 
    426    return true;
    427 }
    428 
    429 /**********************************************************************/
    430 /* API Functions                                                      */
    431 /**********************************************************************/
    432 
    433 
    434 /**
    435  * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE().
    436  * \param genRequired  specifies behavour when id was not generated with
    437  *                     glGenVertexArrays().
    438  */
    439 static void
    440 bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired)
    441 {
    442    struct gl_vertex_array_object * const oldObj = ctx->Array.VAO;
    443    struct gl_vertex_array_object *newObj = NULL;
    444 
    445    assert(oldObj != NULL);
    446 
    447    if ( oldObj->Name == id )
    448       return;   /* rebinding the same array object- no change */
    449 
    450    /*
    451     * Get pointer to new array object (newObj)
    452     */
    453    if (id == 0) {
    454       /* The spec says there is no array object named 0, but we use
    455        * one internally because it simplifies things.
    456        */
    457       newObj = ctx->Array.DefaultVAO;
    458    }
    459    else {
    460       /* non-default array object */
    461       newObj = _mesa_lookup_vao(ctx, id);
    462       if (!newObj) {
    463          if (genRequired) {
    464             _mesa_error(ctx, GL_INVALID_OPERATION,
    465                         "glBindVertexArray(non-gen name)");
    466             return;
    467          }
    468 
    469          /* For APPLE version, generate a new array object now */
    470 	 newObj = _mesa_new_vao(ctx, id);
    471          if (!newObj) {
    472             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
    473             return;
    474          }
    475 
    476          save_array_object(ctx, newObj);
    477       }
    478 
    479       if (!newObj->EverBound) {
    480          /* The "Interactions with APPLE_vertex_array_object" section of the
    481           * GL_ARB_vertex_array_object spec says:
    482           *
    483           *     "The first bind call, either BindVertexArray or
    484           *     BindVertexArrayAPPLE, determines the semantic of the object."
    485           */
    486          newObj->ARBsemantics = genRequired;
    487          newObj->EverBound = GL_TRUE;
    488       }
    489    }
    490 
    491    if (ctx->Array.DrawMethod == DRAW_ARRAYS) {
    492       /* The _DrawArrays pointer is pointing at the VAO being unbound and
    493        * that VAO may be in the process of being deleted. If it's not going
    494        * to be deleted, this will have no effect, because the pointer needs
    495        * to be updated by the VBO module anyway.
    496        *
    497        * Before the VBO module can update the pointer, we have to set it
    498        * to NULL for drivers not to set up arrays which are not bound,
    499        * or to prevent a crash if the VAO being unbound is going to be
    500        * deleted.
    501        */
    502       ctx->Array._DrawArrays = NULL;
    503       ctx->Array.DrawMethod = DRAW_NONE;
    504    }
    505 
    506    ctx->NewState |= _NEW_ARRAY;
    507    _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj);
    508 }
    509 
    510 
    511 /**
    512  * ARB version of glBindVertexArray()
    513  * This function behaves differently from glBindVertexArrayAPPLE() in
    514  * that this function requires all ids to have been previously generated
    515  * by glGenVertexArrays[APPLE]().
    516  */
    517 void GLAPIENTRY
    518 _mesa_BindVertexArray( GLuint id )
    519 {
    520    GET_CURRENT_CONTEXT(ctx);
    521    bind_vertex_array(ctx, id, GL_TRUE);
    522 }
    523 
    524 
    525 /**
    526  * Bind a new array.
    527  *
    528  * \todo
    529  * The binding could be done more efficiently by comparing the non-NULL
    530  * pointers in the old and new objects.  The only arrays that are "dirty" are
    531  * the ones that are non-NULL in either object.
    532  */
    533 void GLAPIENTRY
    534 _mesa_BindVertexArrayAPPLE( GLuint id )
    535 {
    536    GET_CURRENT_CONTEXT(ctx);
    537    bind_vertex_array(ctx, id, GL_FALSE);
    538 }
    539 
    540 
    541 /**
    542  * Delete a set of array objects.
    543  *
    544  * \param n      Number of array objects to delete.
    545  * \param ids    Array of \c n array object IDs.
    546  */
    547 void GLAPIENTRY
    548 _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
    549 {
    550    GET_CURRENT_CONTEXT(ctx);
    551    GLsizei i;
    552 
    553    if (n < 0) {
    554       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)");
    555       return;
    556    }
    557 
    558    for (i = 0; i < n; i++) {
    559       struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]);
    560 
    561       if ( obj != NULL ) {
    562 	 assert( obj->Name == ids[i] );
    563 
    564 	 /* If the array object is currently bound, the spec says "the binding
    565 	  * for that object reverts to zero and the default vertex array
    566 	  * becomes current."
    567 	  */
    568 	 if ( obj == ctx->Array.VAO ) {
    569 	    _mesa_BindVertexArray(0);
    570 	 }
    571 
    572 	 /* The ID is immediately freed for re-use */
    573 	 remove_array_object(ctx, obj);
    574 
    575          if (ctx->Array.LastLookedUpVAO == obj)
    576             _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL);
    577 
    578          /* Unreference the array object.
    579           * If refcount hits zero, the object will be deleted.
    580           */
    581          _mesa_reference_vao(ctx, &obj, NULL);
    582       }
    583    }
    584 }
    585 
    586 
    587 /**
    588  * Generate a set of unique array object IDs and store them in \c arrays.
    589  * Helper for _mesa_GenVertexArrays[APPLE]() and _mesa_CreateVertexArrays()
    590  * below.
    591  *
    592  * \param n       Number of IDs to generate.
    593  * \param arrays  Array of \c n locations to store the IDs.
    594  * \param create  Indicates that the objects should also be created.
    595  * \param func    The name of the GL entry point.
    596  */
    597 static void
    598 gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
    599                   bool create, const char *func)
    600 {
    601    GLuint first;
    602    GLint i;
    603 
    604    if (n < 0) {
    605       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
    606       return;
    607    }
    608 
    609    if (!arrays) {
    610       return;
    611    }
    612 
    613    first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n);
    614 
    615    /* For the sake of simplicity we create the array objects in both
    616     * the Gen* and Create* cases.  The only difference is the value of
    617     * EverBound, which is set to true in the Create* case.
    618     */
    619    for (i = 0; i < n; i++) {
    620       struct gl_vertex_array_object *obj;
    621       GLuint name = first + i;
    622 
    623       obj = _mesa_new_vao(ctx, name);
    624       if (!obj) {
    625          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
    626          return;
    627       }
    628       obj->EverBound = create;
    629       save_array_object(ctx, obj);
    630       arrays[i] = first + i;
    631    }
    632 }
    633 
    634 
    635 /**
    636  * ARB version of glGenVertexArrays()
    637  * All arrays will be required to live in VBOs.
    638  */
    639 void GLAPIENTRY
    640 _mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
    641 {
    642    GET_CURRENT_CONTEXT(ctx);
    643    gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays");
    644 }
    645 
    646 
    647 /**
    648  * APPLE version of glGenVertexArraysAPPLE()
    649  * Arrays may live in VBOs or ordinary memory.
    650  */
    651 void GLAPIENTRY
    652 _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
    653 {
    654    GET_CURRENT_CONTEXT(ctx);
    655    gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArraysAPPLE");
    656 }
    657 
    658 
    659 /**
    660  * ARB_direct_state_access
    661  * Generates ID's and creates the array objects.
    662  */
    663 void GLAPIENTRY
    664 _mesa_CreateVertexArrays(GLsizei n, GLuint *arrays)
    665 {
    666    GET_CURRENT_CONTEXT(ctx);
    667    gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays");
    668 }
    669 
    670 
    671 /**
    672  * Determine if ID is the name of an array object.
    673  *
    674  * \param id  ID of the potential array object.
    675  * \return  \c GL_TRUE if \c id is the name of a array object,
    676  *          \c GL_FALSE otherwise.
    677  */
    678 GLboolean GLAPIENTRY
    679 _mesa_IsVertexArray( GLuint id )
    680 {
    681    struct gl_vertex_array_object * obj;
    682    GET_CURRENT_CONTEXT(ctx);
    683    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
    684 
    685    if (id == 0)
    686       return GL_FALSE;
    687 
    688    obj = _mesa_lookup_vao(ctx, id);
    689    if (obj == NULL)
    690       return GL_FALSE;
    691 
    692    return obj->EverBound;
    693 }
    694 
    695 
    696 /**
    697  * Sets the element array buffer binding of a vertex array object.
    698  *
    699  * This is the ARB_direct_state_access equivalent of
    700  * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer).
    701  */
    702 void GLAPIENTRY
    703 _mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer)
    704 {
    705    GET_CURRENT_CONTEXT(ctx);
    706    struct gl_vertex_array_object *vao;
    707    struct gl_buffer_object *bufObj;
    708 
    709    ASSERT_OUTSIDE_BEGIN_END(ctx);
    710 
    711    /* The GL_ARB_direct_state_access specification says:
    712     *
    713     *    "An INVALID_OPERATION error is generated by VertexArrayElementBuffer
    714     *     if <vaobj> is not [compatibility profile: zero or] the name of an
    715     *     existing vertex array object."
    716     */
    717    vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer");
    718    if (!vao)
    719       return;
    720 
    721    /* The GL_ARB_direct_state_access specification says:
    722     *
    723     *    "An INVALID_OPERATION error is generated if <buffer> is not zero or
    724     *     the name of an existing buffer object."
    725     */
    726    if (buffer != 0)
    727       bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
    728                                           "glVertexArrayElementBuffer");
    729    else
    730       bufObj = ctx->Shared->NullBufferObj;
    731 
    732    if (bufObj)
    733       _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
    734 }
    735 
    736 
    737 void GLAPIENTRY
    738 _mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param)
    739 {
    740    GET_CURRENT_CONTEXT(ctx);
    741    struct gl_vertex_array_object *vao;
    742 
    743    ASSERT_OUTSIDE_BEGIN_END(ctx);
    744 
    745    /* The GL_ARB_direct_state_access specification says:
    746     *
    747     *   "An INVALID_OPERATION error is generated if <vaobj> is not
    748     *    [compatibility profile: zero or] the name of an existing
    749     *    vertex array object."
    750     */
    751    vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv");
    752    if (!vao)
    753       return;
    754 
    755    /* The GL_ARB_direct_state_access specification says:
    756     *
    757     *   "An INVALID_ENUM error is generated if <pname> is not
    758     *    ELEMENT_ARRAY_BUFFER_BINDING."
    759     */
    760    if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
    761       _mesa_error(ctx, GL_INVALID_ENUM,
    762                   "glGetVertexArrayiv(pname != "
    763                   "GL_ELEMENT_ARRAY_BUFFER_BINDING)");
    764       return;
    765    }
    766 
    767    param[0] = vao->IndexBufferObj->Name;
    768 }
    769