Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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@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.  
  56.  
  57. /**
  58.  * Look up the array object for the given ID.
  59.  *
  60.  * \returns
  61.  * Either a pointer to the array object with the specified ID or \c NULL for
  62.  * a non-existent ID.  The spec defines ID 0 as being technically
  63.  * non-existent.
  64.  */
  65.  
  66. struct gl_vertex_array_object *
  67. _mesa_lookup_vao(struct gl_context *ctx, GLuint id)
  68. {
  69.    if (id == 0)
  70.       return NULL;
  71.    else
  72.       return (struct gl_vertex_array_object *)
  73.          _mesa_HashLookup(ctx->Array.Objects, id);
  74. }
  75.  
  76.  
  77. /**
  78.  * Looks up the array object for the given ID.
  79.  *
  80.  * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION
  81.  * error if the array object does not exist. It also returns the default
  82.  * array object when ctx is a compatibility profile context and id is zero.
  83.  */
  84. struct gl_vertex_array_object *
  85. _mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller)
  86. {
  87.    /* The ARB_direct_state_access specification says:
  88.     *
  89.     *    "<vaobj> is [compatibility profile:
  90.     *     zero, indicating the default vertex array object, or]
  91.     *     the name of the vertex array object."
  92.     */
  93.    if (id == 0) {
  94.       if (ctx->API == API_OPENGL_CORE) {
  95.          _mesa_error(ctx, GL_INVALID_OPERATION,
  96.                      "%s(zero is not valid vaobj name in a core profile "
  97.                      "context)", caller);
  98.          return NULL;
  99.       }
  100.  
  101.       return ctx->Array.DefaultVAO;
  102.    } else {
  103.       struct gl_vertex_array_object *vao;
  104.  
  105.       if (ctx->Array.LastLookedUpVAO &&
  106.           ctx->Array.LastLookedUpVAO->Name == id) {
  107.          vao = ctx->Array.LastLookedUpVAO;
  108.       } else {
  109.          vao = (struct gl_vertex_array_object *)
  110.             _mesa_HashLookup(ctx->Array.Objects, id);
  111.  
  112.          /* The ARB_direct_state_access specification says:
  113.           *
  114.           *    "An INVALID_OPERATION error is generated if <vaobj> is not
  115.           *     [compatibility profile: zero or] the name of an existing
  116.           *     vertex array object."
  117.           */
  118.          if (!vao || !vao->EverBound) {
  119.             _mesa_error(ctx, GL_INVALID_OPERATION,
  120.                         "%s(non-existent vaobj=%u)", caller, id);
  121.             return NULL;
  122.          }
  123.  
  124.          _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao);
  125.       }
  126.  
  127.       return vao;
  128.    }
  129. }
  130.  
  131.  
  132. /**
  133.  * For all the vertex binding points in the array object, unbind any pointers
  134.  * to any buffer objects (VBOs).
  135.  * This is done just prior to array object destruction.
  136.  */
  137. static void
  138. unbind_array_object_vbos(struct gl_context *ctx, struct gl_vertex_array_object *obj)
  139. {
  140.    GLuint i;
  141.  
  142.    for (i = 0; i < ARRAY_SIZE(obj->VertexBinding); i++)
  143.       _mesa_reference_buffer_object(ctx, &obj->VertexBinding[i].BufferObj, NULL);
  144.  
  145.    for (i = 0; i < ARRAY_SIZE(obj->_VertexAttrib); i++)
  146.       _mesa_reference_buffer_object(ctx, &obj->_VertexAttrib[i].BufferObj, NULL);
  147. }
  148.  
  149.  
  150. /**
  151.  * Allocate and initialize a new vertex array object.
  152.  *
  153.  * This function is intended to be called via
  154.  * \c dd_function_table::NewArrayObject.
  155.  */
  156. struct gl_vertex_array_object *
  157. _mesa_new_vao(struct gl_context *ctx, GLuint name)
  158. {
  159.    struct gl_vertex_array_object *obj = CALLOC_STRUCT(gl_vertex_array_object);
  160.    if (obj)
  161.       _mesa_initialize_vao(ctx, obj, name);
  162.    return obj;
  163. }
  164.  
  165.  
  166. /**
  167.  * Delete an array object.
  168.  *
  169.  * This function is intended to be called via
  170.  * \c dd_function_table::DeleteArrayObject.
  171.  */
  172. void
  173. _mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj)
  174. {
  175.    unbind_array_object_vbos(ctx, obj);
  176.    _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL);
  177.    mtx_destroy(&obj->Mutex);
  178.    free(obj->Label);
  179.    free(obj);
  180. }
  181.  
  182.  
  183. /**
  184.  * Set ptr to vao w/ reference counting.
  185.  * Note: this should only be called from the _mesa_reference_vao()
  186.  * inline function.
  187.  */
  188. void
  189. _mesa_reference_vao_(struct gl_context *ctx,
  190.                      struct gl_vertex_array_object **ptr,
  191.                      struct gl_vertex_array_object *vao)
  192. {
  193.    assert(*ptr != vao);
  194.  
  195.    if (*ptr) {
  196.       /* Unreference the old array object */
  197.       GLboolean deleteFlag = GL_FALSE;
  198.       struct gl_vertex_array_object *oldObj = *ptr;
  199.  
  200.       mtx_lock(&oldObj->Mutex);
  201.       assert(oldObj->RefCount > 0);
  202.       oldObj->RefCount--;
  203. #if 0
  204.       printf("ArrayObj %p %d DECR to %d\n",
  205.              (void *) oldObj, oldObj->Name, oldObj->RefCount);
  206. #endif
  207.       deleteFlag = (oldObj->RefCount == 0);
  208.       mtx_unlock(&oldObj->Mutex);
  209.  
  210.       if (deleteFlag) {
  211.          assert(ctx->Driver.DeleteArrayObject);
  212.          ctx->Driver.DeleteArrayObject(ctx, oldObj);
  213.       }
  214.  
  215.       *ptr = NULL;
  216.    }
  217.    assert(!*ptr);
  218.  
  219.    if (vao) {
  220.       /* reference new array object */
  221.       mtx_lock(&vao->Mutex);
  222.       if (vao->RefCount == 0) {
  223.          /* this array's being deleted (look just above) */
  224.          /* Not sure this can every really happen.  Warn if it does. */
  225.          _mesa_problem(NULL, "referencing deleted array object");
  226.          *ptr = NULL;
  227.       }
  228.       else {
  229.          vao->RefCount++;
  230. #if 0
  231.          printf("ArrayObj %p %d INCR to %d\n",
  232.                 (void *) vao, vao->Name, vao->RefCount);
  233. #endif
  234.          *ptr = vao;
  235.       }
  236.       mtx_unlock(&vao->Mutex);
  237.    }
  238. }
  239.  
  240.  
  241.  
  242. static void
  243. init_array(struct gl_context *ctx,
  244.            struct gl_vertex_array_object *obj, GLuint index, GLint size, GLint type)
  245. {
  246.    struct gl_vertex_attrib_array *array = &obj->VertexAttrib[index];
  247.    struct gl_vertex_buffer_binding *binding = &obj->VertexBinding[index];
  248.  
  249.    array->Size = size;
  250.    array->Type = type;
  251.    array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
  252.    array->Stride = 0;
  253.    array->Ptr = NULL;
  254.    array->RelativeOffset = 0;
  255.    array->Enabled = GL_FALSE;
  256.    array->Normalized = GL_FALSE;
  257.    array->Integer = GL_FALSE;
  258.    array->Doubles = GL_FALSE;
  259.    array->_ElementSize = size * _mesa_sizeof_type(type);
  260.    array->VertexBinding = index;
  261.  
  262.    binding->Offset = 0;
  263.    binding->Stride = array->_ElementSize;
  264.    binding->BufferObj = NULL;
  265.    binding->_BoundArrays = BITFIELD64_BIT(index);
  266.  
  267.    /* Vertex array buffers */
  268.    _mesa_reference_buffer_object(ctx, &binding->BufferObj,
  269.                                  ctx->Shared->NullBufferObj);
  270. }
  271.  
  272.  
  273. /**
  274.  * Initialize a gl_vertex_array_object's arrays.
  275.  */
  276. void
  277. _mesa_initialize_vao(struct gl_context *ctx,
  278.                      struct gl_vertex_array_object *obj,
  279.                      GLuint name)
  280. {
  281.    GLuint i;
  282.  
  283.    obj->Name = name;
  284.  
  285.    mtx_init(&obj->Mutex, mtx_plain);
  286.    obj->RefCount = 1;
  287.  
  288.    /* Init the individual arrays */
  289.    for (i = 0; i < ARRAY_SIZE(obj->VertexAttrib); i++) {
  290.       switch (i) {
  291.       case VERT_ATTRIB_WEIGHT:
  292.          init_array(ctx, obj, VERT_ATTRIB_WEIGHT, 1, GL_FLOAT);
  293.          break;
  294.       case VERT_ATTRIB_NORMAL:
  295.          init_array(ctx, obj, VERT_ATTRIB_NORMAL, 3, GL_FLOAT);
  296.          break;
  297.       case VERT_ATTRIB_COLOR1:
  298.          init_array(ctx, obj, VERT_ATTRIB_COLOR1, 3, GL_FLOAT);
  299.          break;
  300.       case VERT_ATTRIB_FOG:
  301.          init_array(ctx, obj, VERT_ATTRIB_FOG, 1, GL_FLOAT);
  302.          break;
  303.       case VERT_ATTRIB_COLOR_INDEX:
  304.          init_array(ctx, obj, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT);
  305.          break;
  306.       case VERT_ATTRIB_EDGEFLAG:
  307.          init_array(ctx, obj, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL);
  308.          break;
  309.       case VERT_ATTRIB_POINT_SIZE:
  310.          init_array(ctx, obj, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT);
  311.          break;
  312.       default:
  313.          init_array(ctx, obj, i, 4, GL_FLOAT);
  314.          break;
  315.       }
  316.    }
  317.  
  318.    _mesa_reference_buffer_object(ctx, &obj->IndexBufferObj,
  319.                                  ctx->Shared->NullBufferObj);
  320. }
  321.  
  322.  
  323. /**
  324.  * Add the given array object to the array object pool.
  325.  */
  326. static void
  327. save_array_object( struct gl_context *ctx, struct gl_vertex_array_object *obj )
  328. {
  329.    if (obj->Name > 0) {
  330.       /* insert into hash table */
  331.       _mesa_HashInsert(ctx->Array.Objects, obj->Name, obj);
  332.    }
  333. }
  334.  
  335.  
  336. /**
  337.  * Remove the given array object from the array object pool.
  338.  * Do not deallocate the array object though.
  339.  */
  340. static void
  341. remove_array_object( struct gl_context *ctx, struct gl_vertex_array_object *obj )
  342. {
  343.    if (obj->Name > 0) {
  344.       /* remove from hash table */
  345.       _mesa_HashRemove(ctx->Array.Objects, obj->Name);
  346.    }
  347. }
  348.  
  349.  
  350. /**
  351.  * Updates the derived gl_client_arrays when a gl_vertex_attrib_array
  352.  * or a gl_vertex_buffer_binding has changed.
  353.  */
  354. void
  355. _mesa_update_vao_client_arrays(struct gl_context *ctx,
  356.                                struct gl_vertex_array_object *vao)
  357. {
  358.    GLbitfield64 arrays = vao->NewArrays;
  359.  
  360.    while (arrays) {
  361.       struct gl_client_array *client_array;
  362.       struct gl_vertex_attrib_array *attrib_array;
  363.       struct gl_vertex_buffer_binding *buffer_binding;
  364.  
  365.       GLint attrib = ffsll(arrays) - 1;
  366.       arrays ^= BITFIELD64_BIT(attrib);
  367.  
  368.       attrib_array = &vao->VertexAttrib[attrib];
  369.       buffer_binding = &vao->VertexBinding[attrib_array->VertexBinding];
  370.       client_array = &vao->_VertexAttrib[attrib];
  371.  
  372.       _mesa_update_client_array(ctx, client_array, attrib_array,
  373.                                 buffer_binding);
  374.    }
  375. }
  376.  
  377.  
  378. /**********************************************************************/
  379. /* API Functions                                                      */
  380. /**********************************************************************/
  381.  
  382.  
  383. /**
  384.  * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE().
  385.  * \param genRequired  specifies behavour when id was not generated with
  386.  *                     glGenVertexArrays().
  387.  */
  388. static void
  389. bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired)
  390. {
  391.    struct gl_vertex_array_object * const oldObj = ctx->Array.VAO;
  392.    struct gl_vertex_array_object *newObj = NULL;
  393.  
  394.    assert(oldObj != NULL);
  395.  
  396.    if ( oldObj->Name == id )
  397.       return;   /* rebinding the same array object- no change */
  398.  
  399.    /*
  400.     * Get pointer to new array object (newObj)
  401.     */
  402.    if (id == 0) {
  403.       /* The spec says there is no array object named 0, but we use
  404.        * one internally because it simplifies things.
  405.        */
  406.       newObj = ctx->Array.DefaultVAO;
  407.    }
  408.    else {
  409.       /* non-default array object */
  410.       newObj = _mesa_lookup_vao(ctx, id);
  411.       if (!newObj) {
  412.          if (genRequired) {
  413.             _mesa_error(ctx, GL_INVALID_OPERATION,
  414.                         "glBindVertexArray(non-gen name)");
  415.             return;
  416.          }
  417.  
  418.          /* For APPLE version, generate a new array object now */
  419.          newObj = (*ctx->Driver.NewArrayObject)(ctx, id);
  420.          if (!newObj) {
  421.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
  422.             return;
  423.          }
  424.  
  425.          save_array_object(ctx, newObj);
  426.       }
  427.  
  428.       if (!newObj->EverBound) {
  429.          /* The "Interactions with APPLE_vertex_array_object" section of the
  430.           * GL_ARB_vertex_array_object spec says:
  431.           *
  432.           *     "The first bind call, either BindVertexArray or
  433.           *     BindVertexArrayAPPLE, determines the semantic of the object."
  434.           */
  435.          newObj->ARBsemantics = genRequired;
  436.          newObj->EverBound = GL_TRUE;
  437.       }
  438.    }
  439.  
  440.    if (ctx->Array.DrawMethod == DRAW_ARRAYS) {
  441.       /* The _DrawArrays pointer is pointing at the VAO being unbound and
  442.        * that VAO may be in the process of being deleted. If it's not going
  443.        * to be deleted, this will have no effect, because the pointer needs
  444.        * to be updated by the VBO module anyway.
  445.        *
  446.        * Before the VBO module can update the pointer, we have to set it
  447.        * to NULL for drivers not to set up arrays which are not bound,
  448.        * or to prevent a crash if the VAO being unbound is going to be
  449.        * deleted.
  450.        */
  451.       ctx->Array._DrawArrays = NULL;
  452.       ctx->Array.DrawMethod = DRAW_NONE;
  453.    }
  454.  
  455.    ctx->NewState |= _NEW_ARRAY;
  456.    _mesa_reference_vao(ctx, &ctx->Array.VAO, newObj);
  457.  
  458.    /* Pass BindVertexArray call to device driver */
  459.    if (ctx->Driver.BindArrayObject && newObj)
  460.       ctx->Driver.BindArrayObject(ctx, newObj);
  461. }
  462.  
  463.  
  464. /**
  465.  * ARB version of glBindVertexArray()
  466.  * This function behaves differently from glBindVertexArrayAPPLE() in
  467.  * that this function requires all ids to have been previously generated
  468.  * by glGenVertexArrays[APPLE]().
  469.  */
  470. void GLAPIENTRY
  471. _mesa_BindVertexArray( GLuint id )
  472. {
  473.    GET_CURRENT_CONTEXT(ctx);
  474.    bind_vertex_array(ctx, id, GL_TRUE);
  475. }
  476.  
  477.  
  478. /**
  479.  * Bind a new array.
  480.  *
  481.  * \todo
  482.  * The binding could be done more efficiently by comparing the non-NULL
  483.  * pointers in the old and new objects.  The only arrays that are "dirty" are
  484.  * the ones that are non-NULL in either object.
  485.  */
  486. void GLAPIENTRY
  487. _mesa_BindVertexArrayAPPLE( GLuint id )
  488. {
  489.    GET_CURRENT_CONTEXT(ctx);
  490.    bind_vertex_array(ctx, id, GL_FALSE);
  491. }
  492.  
  493.  
  494. /**
  495.  * Delete a set of array objects.
  496.  *
  497.  * \param n      Number of array objects to delete.
  498.  * \param ids    Array of \c n array object IDs.
  499.  */
  500. void GLAPIENTRY
  501. _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids)
  502. {
  503.    GET_CURRENT_CONTEXT(ctx);
  504.    GLsizei i;
  505.  
  506.    if (n < 0) {
  507.       _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArray(n)");
  508.       return;
  509.    }
  510.  
  511.    for (i = 0; i < n; i++) {
  512.       struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, ids[i]);
  513.  
  514.       if ( obj != NULL ) {
  515.          assert( obj->Name == ids[i] );
  516.  
  517.          /* If the array object is currently bound, the spec says "the binding
  518.           * for that object reverts to zero and the default vertex array
  519.           * becomes current."
  520.           */
  521.          if ( obj == ctx->Array.VAO ) {
  522.             _mesa_BindVertexArray(0);
  523.          }
  524.  
  525.          /* The ID is immediately freed for re-use */
  526.          remove_array_object(ctx, obj);
  527.  
  528.          if (ctx->Array.LastLookedUpVAO == obj)
  529.             _mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, NULL);
  530.  
  531.          /* Unreference the array object.
  532.           * If refcount hits zero, the object will be deleted.
  533.           */
  534.          _mesa_reference_vao(ctx, &obj, NULL);
  535.       }
  536.    }
  537. }
  538.  
  539.  
  540. /**
  541.  * Generate a set of unique array object IDs and store them in \c arrays.
  542.  * Helper for _mesa_GenVertexArrays[APPLE]() and _mesa_CreateVertexArrays()
  543.  * below.
  544.  *
  545.  * \param n       Number of IDs to generate.
  546.  * \param arrays  Array of \c n locations to store the IDs.
  547.  * \param create  Indicates that the objects should also be created.
  548.  * \param func    The name of the GL entry point.
  549.  */
  550. static void
  551. gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
  552.                   bool create, const char *func)
  553. {
  554.    GLuint first;
  555.    GLint i;
  556.  
  557.    if (n < 0) {
  558.       _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
  559.       return;
  560.    }
  561.  
  562.    if (!arrays) {
  563.       return;
  564.    }
  565.  
  566.    first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n);
  567.  
  568.    /* For the sake of simplicity we create the array objects in both
  569.     * the Gen* and Create* cases.  The only difference is the value of
  570.     * EverBound, which is set to true in the Create* case.
  571.     */
  572.    for (i = 0; i < n; i++) {
  573.       struct gl_vertex_array_object *obj;
  574.       GLuint name = first + i;
  575.  
  576.       obj = (*ctx->Driver.NewArrayObject)( ctx, name );
  577.       if (!obj) {
  578.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
  579.          return;
  580.       }
  581.       obj->EverBound = create;
  582.       save_array_object(ctx, obj);
  583.       arrays[i] = first + i;
  584.    }
  585. }
  586.  
  587.  
  588. /**
  589.  * ARB version of glGenVertexArrays()
  590.  * All arrays will be required to live in VBOs.
  591.  */
  592. void GLAPIENTRY
  593. _mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
  594. {
  595.    GET_CURRENT_CONTEXT(ctx);
  596.    gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArrays");
  597. }
  598.  
  599.  
  600. /**
  601.  * APPLE version of glGenVertexArraysAPPLE()
  602.  * Arrays may live in VBOs or ordinary memory.
  603.  */
  604. void GLAPIENTRY
  605. _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
  606. {
  607.    GET_CURRENT_CONTEXT(ctx);
  608.    gen_vertex_arrays(ctx, n, arrays, false, "glGenVertexArraysAPPLE");
  609. }
  610.  
  611.  
  612. /**
  613.  * ARB_direct_state_access
  614.  * Generates ID's and creates the array objects.
  615.  */
  616. void GLAPIENTRY
  617. _mesa_CreateVertexArrays(GLsizei n, GLuint *arrays)
  618. {
  619.    GET_CURRENT_CONTEXT(ctx);
  620.  
  621.    if (!ctx->Extensions.ARB_direct_state_access) {
  622.       _mesa_error(ctx, GL_INVALID_OPERATION,
  623.                    "glCreateVertexArrays(GL_ARB_direct_state_access "
  624.                    "is not supported");
  625.       return;
  626.    }
  627.  
  628.    gen_vertex_arrays(ctx, n, arrays, true, "glCreateVertexArrays");
  629. }
  630.  
  631.  
  632. /**
  633.  * Determine if ID is the name of an array object.
  634.  *
  635.  * \param id  ID of the potential array object.
  636.  * \return  \c GL_TRUE if \c id is the name of a array object,
  637.  *          \c GL_FALSE otherwise.
  638.  */
  639. GLboolean GLAPIENTRY
  640. _mesa_IsVertexArray( GLuint id )
  641. {
  642.    struct gl_vertex_array_object * obj;
  643.    GET_CURRENT_CONTEXT(ctx);
  644.    ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
  645.  
  646.    if (id == 0)
  647.       return GL_FALSE;
  648.  
  649.    obj = _mesa_lookup_vao(ctx, id);
  650.    if (obj == NULL)
  651.       return GL_FALSE;
  652.  
  653.    return obj->EverBound;
  654. }
  655.  
  656.  
  657. /**
  658.  * Sets the element array buffer binding of a vertex array object.
  659.  *
  660.  * This is the ARB_direct_state_access equivalent of
  661.  * glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer).
  662.  */
  663. void GLAPIENTRY
  664. _mesa_VertexArrayElementBuffer(GLuint vaobj, GLuint buffer)
  665. {
  666.    GET_CURRENT_CONTEXT(ctx);
  667.    struct gl_vertex_array_object *vao;
  668.    struct gl_buffer_object *bufObj;
  669.  
  670.    if (!ctx->Extensions.ARB_direct_state_access) {
  671.       _mesa_error(ctx, GL_INVALID_OPERATION,
  672.                    "glVertexArrayElementBuffer(GL_ARB_direct_state_access "
  673.                    "is not supported");
  674.       return;
  675.    }
  676.  
  677.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  678.  
  679.    /* The GL_ARB_direct_state_access specification says:
  680.     *
  681.     *    "An INVALID_OPERATION error is generated by VertexArrayElementBuffer
  682.     *     if <vaobj> is not [compatibility profile: zero or] the name of an
  683.     *     existing vertex array object."
  684.     */
  685.    vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer");
  686.    if (!vao)
  687.       return;
  688.  
  689.    /* The GL_ARB_direct_state_access specification says:
  690.     *
  691.     *    "An INVALID_OPERATION error is generated if <buffer> is not zero or
  692.     *     the name of an existing buffer object."
  693.     */
  694.    if (buffer != 0)
  695.       bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
  696.                                           "glVertexArrayElementBuffer");
  697.    else
  698.       bufObj = ctx->Shared->NullBufferObj;
  699.  
  700.    if (bufObj)
  701.       _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
  702. }
  703.  
  704.  
  705. void GLAPIENTRY
  706. _mesa_GetVertexArrayiv(GLuint vaobj, GLenum pname, GLint *param)
  707. {
  708.    GET_CURRENT_CONTEXT(ctx);
  709.    struct gl_vertex_array_object *vao;
  710.  
  711.    ASSERT_OUTSIDE_BEGIN_END(ctx);
  712.  
  713.    if (!ctx->Extensions.ARB_direct_state_access) {
  714.       _mesa_error(ctx, GL_INVALID_OPERATION,
  715.                    "glGetVertexArrayiv(GL_ARB_direct_state_access "
  716.                    "is not supported");
  717.       return;
  718.    }
  719.  
  720.    /* The GL_ARB_direct_state_access specification says:
  721.     *
  722.     *   "An INVALID_OPERATION error is generated if <vaobj> is not
  723.     *    [compatibility profile: zero or] the name of an existing
  724.     *    vertex array object."
  725.     */
  726.    vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv");
  727.    if (!vao)
  728.       return;
  729.  
  730.    /* The GL_ARB_direct_state_access specification says:
  731.     *
  732.     *   "An INVALID_ENUM error is generated if <pname> is not
  733.     *    ELEMENT_ARRAY_BUFFER_BINDING."
  734.     */
  735.    if (pname != GL_ELEMENT_ARRAY_BUFFER_BINDING) {
  736.       _mesa_error(ctx, GL_INVALID_ENUM,
  737.                   "glGetVertexArrayiv(pname != "
  738.                   "GL_ELEMENT_ARRAY_BUFFER_BINDING)");
  739.       return;
  740.    }
  741.  
  742.    param[0] = vao->IndexBufferObj->Name;
  743. }
  744.