varray.c revision 01e04c3f
17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg *
4c1f859d4Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
54a49301eSmrg * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
67117f1b4Smrg *
77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
87117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
97117f1b4Smrg * to deal in the Software without restriction, including without limitation
107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
127117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
137117f1b4Smrg *
147117f1b4Smrg * The above copyright notice and this permission notice shall be included
157117f1b4Smrg * in all copies or substantial portions of the Software.
167117f1b4Smrg *
177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
247117f1b4Smrg */
257117f1b4Smrg
267117f1b4Smrg
2701e04c3fSmrg#include <stdio.h>
28af69d88dSmrg#include <inttypes.h>  /* for PRId64 macro */
29af69d88dSmrg
307117f1b4Smrg#include "glheader.h"
317117f1b4Smrg#include "imports.h"
327117f1b4Smrg#include "bufferobj.h"
337117f1b4Smrg#include "context.h"
347117f1b4Smrg#include "enable.h"
357117f1b4Smrg#include "enums.h"
364a49301eSmrg#include "hash.h"
373464ebd5Sriastradh#include "image.h"
383464ebd5Sriastradh#include "macros.h"
397117f1b4Smrg#include "mtypes.h"
407117f1b4Smrg#include "varray.h"
417117f1b4Smrg#include "arrayobj.h"
42cdc920a0Smrg#include "main/dispatch.h"
437117f1b4Smrg
447117f1b4Smrg
453464ebd5Sriastradh/** Used to do error checking for GL_EXT_vertex_array_bgra */
463464ebd5Sriastradh#define BGRA_OR_4  5
473464ebd5Sriastradh
483464ebd5Sriastradh
493464ebd5Sriastradh/** Used to indicate which GL datatypes are accepted by each of the
503464ebd5Sriastradh * glVertex/Color/Attrib/EtcPointer() functions.
513464ebd5Sriastradh */
52af69d88dSmrg#define BOOL_BIT                          (1 << 0)
53af69d88dSmrg#define BYTE_BIT                          (1 << 1)
54af69d88dSmrg#define UNSIGNED_BYTE_BIT                 (1 << 2)
55af69d88dSmrg#define SHORT_BIT                         (1 << 3)
56af69d88dSmrg#define UNSIGNED_SHORT_BIT                (1 << 4)
57af69d88dSmrg#define INT_BIT                           (1 << 5)
58af69d88dSmrg#define UNSIGNED_INT_BIT                  (1 << 6)
59af69d88dSmrg#define HALF_BIT                          (1 << 7)
60af69d88dSmrg#define FLOAT_BIT                         (1 << 8)
61af69d88dSmrg#define DOUBLE_BIT                        (1 << 9)
62af69d88dSmrg#define FIXED_ES_BIT                      (1 << 10)
63af69d88dSmrg#define FIXED_GL_BIT                      (1 << 11)
64af69d88dSmrg#define UNSIGNED_INT_2_10_10_10_REV_BIT   (1 << 12)
65af69d88dSmrg#define INT_2_10_10_10_REV_BIT            (1 << 13)
66af69d88dSmrg#define UNSIGNED_INT_10F_11F_11F_REV_BIT  (1 << 14)
67af69d88dSmrg#define ALL_TYPE_BITS                    ((1 << 15) - 1)
683464ebd5Sriastradh
6901e04c3fSmrg#define ATTRIB_FORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
7001e04c3fSmrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT | \
7101e04c3fSmrg                                  INT_BIT | UNSIGNED_INT_BIT | \
7201e04c3fSmrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT | \
7301e04c3fSmrg                                  FIXED_GL_BIT | \
7401e04c3fSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT | \
7501e04c3fSmrg                                  INT_2_10_10_10_REV_BIT | \
7601e04c3fSmrg                                  UNSIGNED_INT_10F_11F_11F_REV_BIT)
7701e04c3fSmrg
7801e04c3fSmrg#define ATTRIB_IFORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
7901e04c3fSmrg                                   SHORT_BIT | UNSIGNED_SHORT_BIT | \
8001e04c3fSmrg                                   INT_BIT | UNSIGNED_INT_BIT)
8101e04c3fSmrg
8201e04c3fSmrg#define ATTRIB_LFORMAT_TYPES_MASK DOUBLE_BIT
8301e04c3fSmrg
843464ebd5Sriastradh
853464ebd5Sriastradh/** Convert GL datatype enum into a <type>_BIT value seen above */
863464ebd5Sriastradhstatic GLbitfield
873464ebd5Sriastradhtype_to_bit(const struct gl_context *ctx, GLenum type)
883464ebd5Sriastradh{
893464ebd5Sriastradh   switch (type) {
903464ebd5Sriastradh   case GL_BOOL:
913464ebd5Sriastradh      return BOOL_BIT;
923464ebd5Sriastradh   case GL_BYTE:
933464ebd5Sriastradh      return BYTE_BIT;
943464ebd5Sriastradh   case GL_UNSIGNED_BYTE:
953464ebd5Sriastradh      return UNSIGNED_BYTE_BIT;
963464ebd5Sriastradh   case GL_SHORT:
973464ebd5Sriastradh      return SHORT_BIT;
983464ebd5Sriastradh   case GL_UNSIGNED_SHORT:
993464ebd5Sriastradh      return UNSIGNED_SHORT_BIT;
1003464ebd5Sriastradh   case GL_INT:
1013464ebd5Sriastradh      return INT_BIT;
1023464ebd5Sriastradh   case GL_UNSIGNED_INT:
1033464ebd5Sriastradh      return UNSIGNED_INT_BIT;
1043464ebd5Sriastradh   case GL_HALF_FLOAT:
10501e04c3fSmrg   case GL_HALF_FLOAT_OES:
1063464ebd5Sriastradh      if (ctx->Extensions.ARB_half_float_vertex)
1073464ebd5Sriastradh         return HALF_BIT;
1083464ebd5Sriastradh      else
1093464ebd5Sriastradh         return 0x0;
1103464ebd5Sriastradh   case GL_FLOAT:
1113464ebd5Sriastradh      return FLOAT_BIT;
1123464ebd5Sriastradh   case GL_DOUBLE:
1133464ebd5Sriastradh      return DOUBLE_BIT;
1143464ebd5Sriastradh   case GL_FIXED:
115af69d88dSmrg      return _mesa_is_desktop_gl(ctx) ? FIXED_GL_BIT : FIXED_ES_BIT;
116af69d88dSmrg   case GL_UNSIGNED_INT_2_10_10_10_REV:
117af69d88dSmrg      return UNSIGNED_INT_2_10_10_10_REV_BIT;
118af69d88dSmrg   case GL_INT_2_10_10_10_REV:
119af69d88dSmrg      return INT_2_10_10_10_REV_BIT;
120af69d88dSmrg   case GL_UNSIGNED_INT_10F_11F_11F_REV:
121af69d88dSmrg      return UNSIGNED_INT_10F_11F_11F_REV_BIT;
1223464ebd5Sriastradh   default:
1233464ebd5Sriastradh      return 0;
1243464ebd5Sriastradh   }
1253464ebd5Sriastradh}
1263464ebd5Sriastradh
1273464ebd5Sriastradh
1287117f1b4Smrg/**
12901e04c3fSmrg * Depending on the position and generic0 attributes enable flags select
13001e04c3fSmrg * the one that is used for both attributes.
13101e04c3fSmrg * The generic0 attribute takes precedence.
1327117f1b4Smrg */
13301e04c3fSmrgstatic inline void
13401e04c3fSmrgupdate_attribute_map_mode(const struct gl_context *ctx,
13501e04c3fSmrg                          struct gl_vertex_array_object *vao)
136af69d88dSmrg{
13701e04c3fSmrg   /*
13801e04c3fSmrg    * There is no need to change the mapping away from the
13901e04c3fSmrg    * identity mapping if we are not in compat mode.
14001e04c3fSmrg    */
14101e04c3fSmrg   if (ctx->API != API_OPENGL_COMPAT)
14201e04c3fSmrg      return;
14301e04c3fSmrg   /* The generic0 attribute superseeds the position attribute */
14401e04c3fSmrg   const GLbitfield enabled = vao->_Enabled;
14501e04c3fSmrg   if (enabled & VERT_BIT_GENERIC0)
14601e04c3fSmrg      vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_GENERIC0;
14701e04c3fSmrg   else if (enabled & VERT_BIT_POS)
14801e04c3fSmrg      vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_POSITION;
14901e04c3fSmrg   else
15001e04c3fSmrg      vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY;
15101e04c3fSmrg}
15201e04c3fSmrg
153af69d88dSmrg
15401e04c3fSmrg/**
15501e04c3fSmrg * Sets the BufferBindingIndex field for the vertex attribute given by
15601e04c3fSmrg * attribIndex.
15701e04c3fSmrg */
15801e04c3fSmrgvoid
15901e04c3fSmrg_mesa_vertex_attrib_binding(struct gl_context *ctx,
16001e04c3fSmrg                            struct gl_vertex_array_object *vao,
16101e04c3fSmrg                            gl_vert_attrib attribIndex,
16201e04c3fSmrg                            GLuint bindingIndex)
16301e04c3fSmrg{
16401e04c3fSmrg   struct gl_array_attributes *array = &vao->VertexAttrib[attribIndex];
16501e04c3fSmrg   assert(!vao->SharedAndImmutable);
166af69d88dSmrg
16701e04c3fSmrg   if (array->BufferBindingIndex != bindingIndex) {
16801e04c3fSmrg      const GLbitfield array_bit = VERT_BIT(attribIndex);
169af69d88dSmrg
17001e04c3fSmrg      if (_mesa_is_bufferobj(vao->BufferBinding[bindingIndex].BufferObj))
17101e04c3fSmrg         vao->VertexAttribBufferMask |= array_bit;
17201e04c3fSmrg      else
17301e04c3fSmrg         vao->VertexAttribBufferMask &= ~array_bit;
174af69d88dSmrg
17501e04c3fSmrg      vao->BufferBinding[array->BufferBindingIndex]._BoundArrays &= ~array_bit;
17601e04c3fSmrg      vao->BufferBinding[bindingIndex]._BoundArrays |= array_bit;
177af69d88dSmrg
17801e04c3fSmrg      array->BufferBindingIndex = bindingIndex;
17901e04c3fSmrg
18001e04c3fSmrg      vao->NewArrays |= vao->_Enabled & array_bit;
18101e04c3fSmrg      if (vao == ctx->Array.VAO)
18201e04c3fSmrg         ctx->NewState |= _NEW_ARRAY;
183af69d88dSmrg   }
184af69d88dSmrg}
185af69d88dSmrg
186af69d88dSmrg
187af69d88dSmrg/**
188af69d88dSmrg * Binds a buffer object to the vertex buffer binding point given by index,
189af69d88dSmrg * and sets the Offset and Stride fields.
190af69d88dSmrg */
19101e04c3fSmrgvoid
19201e04c3fSmrg_mesa_bind_vertex_buffer(struct gl_context *ctx,
19301e04c3fSmrg                         struct gl_vertex_array_object *vao,
19401e04c3fSmrg                         GLuint index,
19501e04c3fSmrg                         struct gl_buffer_object *vbo,
19601e04c3fSmrg                         GLintptr offset, GLsizei stride)
197af69d88dSmrg{
19801e04c3fSmrg   assert(index < ARRAY_SIZE(vao->BufferBinding));
19901e04c3fSmrg   assert(!vao->SharedAndImmutable);
20001e04c3fSmrg   struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
201af69d88dSmrg
202af69d88dSmrg   if (binding->BufferObj != vbo ||
203af69d88dSmrg       binding->Offset != offset ||
204af69d88dSmrg       binding->Stride != stride) {
205af69d88dSmrg
206af69d88dSmrg      _mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo);
207af69d88dSmrg
208af69d88dSmrg      binding->Offset = offset;
209af69d88dSmrg      binding->Stride = stride;
210af69d88dSmrg
21101e04c3fSmrg      if (!_mesa_is_bufferobj(vbo))
21201e04c3fSmrg         vao->VertexAttribBufferMask &= ~binding->_BoundArrays;
21301e04c3fSmrg      else
21401e04c3fSmrg         vao->VertexAttribBufferMask |= binding->_BoundArrays;
21501e04c3fSmrg
21601e04c3fSmrg      vao->NewArrays |= vao->_Enabled & binding->_BoundArrays;
21701e04c3fSmrg      if (vao == ctx->Array.VAO)
21801e04c3fSmrg         ctx->NewState |= _NEW_ARRAY;
219af69d88dSmrg   }
220af69d88dSmrg}
221af69d88dSmrg
222af69d88dSmrg
223af69d88dSmrg/**
224af69d88dSmrg * Sets the InstanceDivisor field in the vertex buffer binding point
225af69d88dSmrg * given by bindingIndex.
226af69d88dSmrg */
227af69d88dSmrgstatic void
22801e04c3fSmrgvertex_binding_divisor(struct gl_context *ctx,
22901e04c3fSmrg                       struct gl_vertex_array_object *vao,
23001e04c3fSmrg                       GLuint bindingIndex,
231af69d88dSmrg                       GLuint divisor)
232af69d88dSmrg{
233af69d88dSmrg   struct gl_vertex_buffer_binding *binding =
23401e04c3fSmrg      &vao->BufferBinding[bindingIndex];
23501e04c3fSmrg   assert(!vao->SharedAndImmutable);
236af69d88dSmrg
237af69d88dSmrg   if (binding->InstanceDivisor != divisor) {
238af69d88dSmrg      binding->InstanceDivisor = divisor;
23901e04c3fSmrg      vao->NewArrays |= vao->_Enabled & binding->_BoundArrays;
24001e04c3fSmrg      if (vao == ctx->Array.VAO)
24101e04c3fSmrg         ctx->NewState |= _NEW_ARRAY;
242af69d88dSmrg   }
243af69d88dSmrg}
244af69d88dSmrg
245af69d88dSmrg
246af69d88dSmrg/**
247af69d88dSmrg * Examine the API profile and extensions to determine which types are legal
248af69d88dSmrg * for vertex arrays.  This is called once from update_array_format().
249af69d88dSmrg */
250af69d88dSmrgstatic GLbitfield
251af69d88dSmrgget_legal_types_mask(const struct gl_context *ctx)
252af69d88dSmrg{
253af69d88dSmrg   GLbitfield legalTypesMask = ALL_TYPE_BITS;
254af69d88dSmrg
255af69d88dSmrg   if (_mesa_is_gles(ctx)) {
256af69d88dSmrg      legalTypesMask &= ~(FIXED_GL_BIT |
257af69d88dSmrg                          DOUBLE_BIT |
258af69d88dSmrg                          UNSIGNED_INT_10F_11F_11F_REV_BIT);
259af69d88dSmrg
260af69d88dSmrg      /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
261af69d88dSmrg       * 3.0.  The 2_10_10_10 types are added in OpenGL ES 3.0 or
262af69d88dSmrg       * GL_OES_vertex_type_10_10_10_2.  GL_HALF_FLOAT data is not allowed
263af69d88dSmrg       * until 3.0 or with the GL_OES_vertex_half float extension, which isn't
264af69d88dSmrg       * quite as trivial as we'd like because it uses a different enum value
265af69d88dSmrg       * for GL_HALF_FLOAT_OES.
266af69d88dSmrg       */
267af69d88dSmrg      if (ctx->Version < 30) {
268af69d88dSmrg         legalTypesMask &= ~(UNSIGNED_INT_BIT |
269af69d88dSmrg                             INT_BIT |
270af69d88dSmrg                             UNSIGNED_INT_2_10_10_10_REV_BIT |
27101e04c3fSmrg                             INT_2_10_10_10_REV_BIT);
27201e04c3fSmrg
27301e04c3fSmrg         if (!_mesa_has_OES_vertex_half_float(ctx))
27401e04c3fSmrg            legalTypesMask &= ~HALF_BIT;
275af69d88dSmrg      }
276af69d88dSmrg   }
277af69d88dSmrg   else {
278af69d88dSmrg      legalTypesMask &= ~FIXED_ES_BIT;
279af69d88dSmrg
280af69d88dSmrg      if (!ctx->Extensions.ARB_ES2_compatibility)
281af69d88dSmrg         legalTypesMask &= ~FIXED_GL_BIT;
282af69d88dSmrg
283af69d88dSmrg      if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
284af69d88dSmrg         legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
285af69d88dSmrg                             INT_2_10_10_10_REV_BIT);
286af69d88dSmrg
287af69d88dSmrg      if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev)
288af69d88dSmrg         legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT;
289af69d88dSmrg   }
290af69d88dSmrg
291af69d88dSmrg   return legalTypesMask;
292af69d88dSmrg}
293af69d88dSmrg
29401e04c3fSmrgstatic GLenum
29501e04c3fSmrgget_array_format(const struct gl_context *ctx, GLint sizeMax, GLint *size)
29601e04c3fSmrg{
29701e04c3fSmrg   GLenum format = GL_RGBA;
29801e04c3fSmrg
29901e04c3fSmrg   /* Do size parameter checking.
30001e04c3fSmrg    * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and
30101e04c3fSmrg    * must be handled specially.
30201e04c3fSmrg    */
30301e04c3fSmrg   if (ctx->Extensions.EXT_vertex_array_bgra && sizeMax == BGRA_OR_4 &&
30401e04c3fSmrg       *size == GL_BGRA) {
30501e04c3fSmrg      format = GL_BGRA;
30601e04c3fSmrg      *size = 4;
30701e04c3fSmrg   }
30801e04c3fSmrg
30901e04c3fSmrg   return format;
31001e04c3fSmrg}
31101e04c3fSmrg
31201e04c3fSmrg
31301e04c3fSmrg/**
31401e04c3fSmrg * \param attrib         The index of the attribute array
31501e04c3fSmrg * \param size           Components per element (1, 2, 3 or 4)
31601e04c3fSmrg * \param type           Datatype of each component (GL_FLOAT, GL_INT, etc)
31701e04c3fSmrg * \param format         Either GL_RGBA or GL_BGRA.
31801e04c3fSmrg * \param normalized     Whether integer types are converted to floats in [-1, 1]
31901e04c3fSmrg * \param integer        Integer-valued values (will not be normalized to [-1, 1])
32001e04c3fSmrg * \param doubles        Double values not reduced to floats
32101e04c3fSmrg * \param relativeOffset Offset of the first element relative to the binding
32201e04c3fSmrg *                       offset.
32301e04c3fSmrg */
32401e04c3fSmrgvoid
32501e04c3fSmrg_mesa_update_array_format(struct gl_context *ctx,
32601e04c3fSmrg                          struct gl_vertex_array_object *vao,
32701e04c3fSmrg                          gl_vert_attrib attrib, GLint size, GLenum type,
32801e04c3fSmrg                          GLenum format, GLboolean normalized,
32901e04c3fSmrg                          GLboolean integer, GLboolean doubles,
33001e04c3fSmrg                          GLuint relativeOffset)
33101e04c3fSmrg{
33201e04c3fSmrg   struct gl_array_attributes *const array = &vao->VertexAttrib[attrib];
33301e04c3fSmrg   GLint elementSize;
33401e04c3fSmrg
33501e04c3fSmrg   assert(!vao->SharedAndImmutable);
33601e04c3fSmrg   assert(size <= 4);
33701e04c3fSmrg
33801e04c3fSmrg   elementSize = _mesa_bytes_per_vertex_attrib(size, type);
33901e04c3fSmrg   assert(elementSize != -1);
34001e04c3fSmrg
34101e04c3fSmrg   array->Size = size;
34201e04c3fSmrg   array->Type = type;
34301e04c3fSmrg   array->Format = format;
34401e04c3fSmrg   array->Normalized = normalized;
34501e04c3fSmrg   array->Integer = integer;
34601e04c3fSmrg   array->Doubles = doubles;
34701e04c3fSmrg   array->RelativeOffset = relativeOffset;
34801e04c3fSmrg   array->_ElementSize = elementSize;
34901e04c3fSmrg
35001e04c3fSmrg   vao->NewArrays |= vao->_Enabled & VERT_BIT(attrib);
35101e04c3fSmrg   if (vao == ctx->Array.VAO)
35201e04c3fSmrg      ctx->NewState |= _NEW_ARRAY;
35301e04c3fSmrg}
354af69d88dSmrg
355af69d88dSmrg/**
35601e04c3fSmrg * Does error checking of the format in an attrib array.
357af69d88dSmrg *
35801e04c3fSmrg * Called by *Pointer() and VertexAttrib*Format().
359af69d88dSmrg *
360af69d88dSmrg * \param func         Name of calling function used for error reporting
361af69d88dSmrg * \param attrib       The index of the attribute array
362af69d88dSmrg * \param legalTypes   Bitmask of *_BIT above indicating legal datatypes
363af69d88dSmrg * \param sizeMin      Min allowable size value
364af69d88dSmrg * \param sizeMax      Max allowable size value (may also be BGRA_OR_4)
365af69d88dSmrg * \param size         Components per element (1, 2, 3 or 4)
366af69d88dSmrg * \param type         Datatype of each component (GL_FLOAT, GL_INT, etc)
367af69d88dSmrg * \param normalized   Whether integer types are converted to floats in [-1, 1]
368af69d88dSmrg * \param integer      Integer-valued values (will not be normalized to [-1, 1])
36901e04c3fSmrg * \param doubles      Double values not reduced to floats
370af69d88dSmrg * \param relativeOffset Offset of the first element relative to the binding offset.
37101e04c3fSmrg * \return bool True if validation is successful, False otherwise.
372af69d88dSmrg */
373af69d88dSmrgstatic bool
37401e04c3fSmrgvalidate_array_format(struct gl_context *ctx, const char *func,
37501e04c3fSmrg                      struct gl_vertex_array_object *vao,
37601e04c3fSmrg                      GLuint attrib, GLbitfield legalTypesMask,
37701e04c3fSmrg                      GLint sizeMin, GLint sizeMax,
37801e04c3fSmrg                      GLint size, GLenum type, GLboolean normalized,
37901e04c3fSmrg                      GLboolean integer, GLboolean doubles,
38001e04c3fSmrg                      GLuint relativeOffset, GLenum format)
38101e04c3fSmrg{
3823464ebd5Sriastradh   GLbitfield typeBit;
3833464ebd5Sriastradh
38401e04c3fSmrg   /* at most, one of these bools can be true */
38501e04c3fSmrg   assert((int) normalized + (int) integer + (int) doubles <= 1);
38601e04c3fSmrg
38701e04c3fSmrg   if (ctx->Array.LegalTypesMask == 0 || ctx->Array.LegalTypesMaskAPI != ctx->API) {
38801e04c3fSmrg      /* Compute the LegalTypesMask only once, unless the context API has
38901e04c3fSmrg       * changed, in which case we want to compute it again.  We can't do this
39001e04c3fSmrg       * in _mesa_init_varrays() below because extensions are not yet enabled
39101e04c3fSmrg       * at that point.
392af69d88dSmrg       */
393af69d88dSmrg      ctx->Array.LegalTypesMask = get_legal_types_mask(ctx);
39401e04c3fSmrg      ctx->Array.LegalTypesMaskAPI = ctx->API;
3953464ebd5Sriastradh   }
396af69d88dSmrg
397af69d88dSmrg   legalTypesMask &= ctx->Array.LegalTypesMask;
398af69d88dSmrg
399af69d88dSmrg   if (_mesa_is_gles(ctx) && sizeMax == BGRA_OR_4) {
400af69d88dSmrg      /* BGRA ordering is not supported in ES contexts.
401af69d88dSmrg       */
402af69d88dSmrg      sizeMax = 4;
4033464ebd5Sriastradh   }
4043464ebd5Sriastradh
4053464ebd5Sriastradh   typeBit = type_to_bit(ctx, type);
4063464ebd5Sriastradh   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
4073464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
40801e04c3fSmrg                  func, _mesa_enum_to_string(type));
409af69d88dSmrg      return false;
4103464ebd5Sriastradh   }
4113464ebd5Sriastradh
41201e04c3fSmrg   if (format == GL_BGRA) {
413af69d88dSmrg      /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
414af69d88dSmrg       *
415af69d88dSmrg       * "An INVALID_OPERATION error is generated under any of the following
416af69d88dSmrg       *  conditions:
417af69d88dSmrg       *    ...
418af69d88dSmrg       *    • size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV
419af69d88dSmrg       *      or UNSIGNED_INT_2_10_10_10_REV;
420af69d88dSmrg       *    ...
421af69d88dSmrg       *    • size is BGRA and normalized is FALSE;"
422af69d88dSmrg       */
423af69d88dSmrg      bool bgra_error = false;
424af69d88dSmrg
425af69d88dSmrg      if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
426af69d88dSmrg         if (type != GL_UNSIGNED_INT_2_10_10_10_REV &&
427af69d88dSmrg             type != GL_INT_2_10_10_10_REV &&
428af69d88dSmrg             type != GL_UNSIGNED_BYTE)
429af69d88dSmrg            bgra_error = true;
430af69d88dSmrg      } else if (type != GL_UNSIGNED_BYTE)
431af69d88dSmrg         bgra_error = true;
432af69d88dSmrg
433af69d88dSmrg      if (bgra_error) {
434af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)",
43501e04c3fSmrg                     func, _mesa_enum_to_string(type));
436af69d88dSmrg         return false;
437af69d88dSmrg      }
438af69d88dSmrg
439af69d88dSmrg      if (!normalized) {
440af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
441af69d88dSmrg                     "%s(size=GL_BGRA and normalized=GL_FALSE)", func);
442af69d88dSmrg         return false;
4433464ebd5Sriastradh      }
4443464ebd5Sriastradh   }
4453464ebd5Sriastradh   else if (size < sizeMin || size > sizeMax || size > 4) {
4463464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
447af69d88dSmrg      return false;
448af69d88dSmrg   }
449af69d88dSmrg
450af69d88dSmrg   if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
451af69d88dSmrg       (type == GL_UNSIGNED_INT_2_10_10_10_REV ||
452af69d88dSmrg        type == GL_INT_2_10_10_10_REV) && size != 4) {
453af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
454af69d88dSmrg      return false;
455af69d88dSmrg   }
456af69d88dSmrg
457af69d88dSmrg   /* The ARB_vertex_attrib_binding_spec says:
458af69d88dSmrg    *
459af69d88dSmrg    *   An INVALID_VALUE error is generated if <relativeoffset> is larger than
460af69d88dSmrg    *   the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.
461af69d88dSmrg    */
462af69d88dSmrg   if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) {
463af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
464af69d88dSmrg                  "%s(relativeOffset=%d > "
465af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)",
466af69d88dSmrg                  func, relativeOffset);
467af69d88dSmrg      return false;
468af69d88dSmrg   }
469af69d88dSmrg
470af69d88dSmrg   if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev &&
471af69d88dSmrg         type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) {
472af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
473af69d88dSmrg      return false;
4743464ebd5Sriastradh   }
4753464ebd5Sriastradh
476af69d88dSmrg   return true;
477af69d88dSmrg}
478af69d88dSmrg
479af69d88dSmrg/**
48001e04c3fSmrg * Do error checking for glVertex/Color/TexCoord/...Pointer functions.
481af69d88dSmrg *
482af69d88dSmrg * \param func  name of calling function used for error reporting
483af69d88dSmrg * \param attrib  the attribute array index to update
484af69d88dSmrg * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
485af69d88dSmrg * \param sizeMin  min allowable size value
486af69d88dSmrg * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
487af69d88dSmrg * \param size  components per element (1, 2, 3 or 4)
488af69d88dSmrg * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
489af69d88dSmrg * \param stride  stride between elements, in elements
490af69d88dSmrg * \param normalized  are integer types converted to floats in [-1, 1]?
491af69d88dSmrg * \param integer  integer-valued values (will not be normalized to [-1,1])
49201e04c3fSmrg * \param doubles  Double values not reduced to floats
493af69d88dSmrg * \param ptr  the address (or offset inside VBO) of the array data
494af69d88dSmrg */
495af69d88dSmrgstatic void
49601e04c3fSmrgvalidate_array(struct gl_context *ctx, const char *func,
49701e04c3fSmrg               GLuint attrib, GLbitfield legalTypesMask,
49801e04c3fSmrg               GLint sizeMin, GLint sizeMax,
49901e04c3fSmrg               GLint size, GLenum type, GLsizei stride,
50001e04c3fSmrg               GLboolean normalized, GLboolean integer, GLboolean doubles,
50101e04c3fSmrg               const GLvoid *ptr)
502af69d88dSmrg{
50301e04c3fSmrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
504af69d88dSmrg
505af69d88dSmrg   /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says:
506af69d88dSmrg    *
507af69d88dSmrg    *     "Client vertex arrays - all vertex array attribute pointers must
508af69d88dSmrg    *     refer to buffer objects (section 2.9.2). The default vertex array
509af69d88dSmrg    *     object (the name zero) is also deprecated. Calling
510af69d88dSmrg    *     VertexAttribPointer when no buffer object or no vertex array object
511af69d88dSmrg    *     is bound will generate an INVALID_OPERATION error..."
512af69d88dSmrg    *
513af69d88dSmrg    * The check for VBOs is handled below.
514af69d88dSmrg    */
51501e04c3fSmrg   if (ctx->API == API_OPENGL_CORE && (vao == ctx->Array.DefaultVAO)) {
516af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)",
517af69d88dSmrg                  func);
518af69d88dSmrg      return;
519af69d88dSmrg   }
520af69d88dSmrg
5213464ebd5Sriastradh   if (stride < 0) {
5223464ebd5Sriastradh      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
5233464ebd5Sriastradh      return;
5243464ebd5Sriastradh   }
5254a49301eSmrg
52601e04c3fSmrg   if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 &&
52701e04c3fSmrg       stride > ctx->Const.MaxVertexAttribStride) {
52801e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
52901e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
53001e04c3fSmrg      return;
53101e04c3fSmrg   }
53201e04c3fSmrg
533af69d88dSmrg   /* Page 29 (page 44 of the PDF) of the OpenGL 3.3 spec says:
534af69d88dSmrg    *
535af69d88dSmrg    *     "An INVALID_OPERATION error is generated under any of the following
536af69d88dSmrg    *     conditions:
537af69d88dSmrg    *
538af69d88dSmrg    *     ...
539af69d88dSmrg    *
540af69d88dSmrg    *     * any of the *Pointer commands specifying the location and
541af69d88dSmrg    *       organization of vertex array data are called while zero is bound
542af69d88dSmrg    *       to the ARRAY_BUFFER buffer object binding point (see section
543af69d88dSmrg    *       2.9.6), and the pointer argument is not NULL."
544af69d88dSmrg    */
54501e04c3fSmrg   if (ptr != NULL && vao != ctx->Array.DefaultVAO &&
546af69d88dSmrg       !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) {
5473464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
5484a49301eSmrg      return;
5494a49301eSmrg   }
55001e04c3fSmrg}
5514a49301eSmrg
55201e04c3fSmrg
55301e04c3fSmrgstatic bool
55401e04c3fSmrgvalidate_array_and_format(struct gl_context *ctx, const char *func,
55501e04c3fSmrg                          GLuint attrib, GLbitfield legalTypes,
55601e04c3fSmrg                          GLint sizeMin, GLint sizeMax,
55701e04c3fSmrg                          GLint size, GLenum type, GLsizei stride,
55801e04c3fSmrg                          GLboolean normalized, GLboolean integer,
55901e04c3fSmrg                          GLboolean doubles, GLenum format, const GLvoid *ptr,
56001e04c3fSmrg                          struct gl_vertex_array_object *vao)
56101e04c3fSmrg{
56201e04c3fSmrg   validate_array(ctx, func, attrib, legalTypes, sizeMin, sizeMax, size,
56301e04c3fSmrg                  type, stride, normalized, integer, doubles, ptr);
56401e04c3fSmrg
56501e04c3fSmrg   return validate_array_format(ctx, func, vao, attrib, legalTypes, sizeMin,
56601e04c3fSmrg                                sizeMax, size, type, normalized, integer,
56701e04c3fSmrg                                doubles, 0, format);
56801e04c3fSmrg}
56901e04c3fSmrg
57001e04c3fSmrg
57101e04c3fSmrg/**
57201e04c3fSmrg * Update state for glVertex/Color/TexCoord/...Pointer functions.
57301e04c3fSmrg *
57401e04c3fSmrg * \param attrib  the attribute array index to update
57501e04c3fSmrg * \param format  Either GL_RGBA or GL_BGRA.
57601e04c3fSmrg * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
57701e04c3fSmrg * \param size  components per element (1, 2, 3 or 4)
57801e04c3fSmrg * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
57901e04c3fSmrg * \param stride  stride between elements, in elements
58001e04c3fSmrg * \param normalized  are integer types converted to floats in [-1, 1]?
58101e04c3fSmrg * \param integer  integer-valued values (will not be normalized to [-1,1])
58201e04c3fSmrg * \param doubles  Double values not reduced to floats
58301e04c3fSmrg * \param ptr  the address (or offset inside VBO) of the array data
58401e04c3fSmrg */
58501e04c3fSmrgstatic void
58601e04c3fSmrgupdate_array(struct gl_context *ctx,
58701e04c3fSmrg             GLuint attrib, GLenum format,
58801e04c3fSmrg             GLint sizeMax,
58901e04c3fSmrg             GLint size, GLenum type, GLsizei stride,
59001e04c3fSmrg             GLboolean normalized, GLboolean integer, GLboolean doubles,
59101e04c3fSmrg             const GLvoid *ptr)
59201e04c3fSmrg{
59301e04c3fSmrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
59401e04c3fSmrg
59501e04c3fSmrg   _mesa_update_array_format(ctx, vao, attrib, size, type, format,
59601e04c3fSmrg                             normalized, integer, doubles, 0);
5973464ebd5Sriastradh
598af69d88dSmrg   /* Reset the vertex attrib binding */
59901e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao, attrib, attrib);
6004a49301eSmrg
601af69d88dSmrg   /* The Stride and Ptr fields are not set by update_array_format() */
60201e04c3fSmrg   struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
603af69d88dSmrg   array->Stride = stride;
60401e04c3fSmrg   /* For updating the pointer we would need to add the vao->NewArrays flag
60501e04c3fSmrg    * to the VAO. But but that is done already unconditionally in
60601e04c3fSmrg    * _mesa_update_array_format called above.
60701e04c3fSmrg    */
60801e04c3fSmrg   assert((vao->NewArrays | ~vao->_Enabled) & VERT_BIT(attrib));
60901e04c3fSmrg   array->Ptr = ptr;
610c1f859d4Smrg
611af69d88dSmrg   /* Update the vertex buffer binding */
61201e04c3fSmrg   GLsizei effectiveStride = stride != 0 ? stride : array->_ElementSize;
61301e04c3fSmrg   _mesa_bind_vertex_buffer(ctx, vao, attrib,
61401e04c3fSmrg                            ctx->Array.ArrayBufferObj, (GLintptr) ptr,
61501e04c3fSmrg                            effectiveStride);
61601e04c3fSmrg}
61701e04c3fSmrg
61801e04c3fSmrgvoid GLAPIENTRY
61901e04c3fSmrg_mesa_VertexPointer_no_error(GLint size, GLenum type, GLsizei stride,
62001e04c3fSmrg                             const GLvoid *ptr)
62101e04c3fSmrg{
62201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
62301e04c3fSmrg
62401e04c3fSmrg   update_array(ctx, VERT_ATTRIB_POS, GL_RGBA, 4, size, type, stride,
62501e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
6267117f1b4Smrg}
6277117f1b4Smrg
6287117f1b4Smrg
6297117f1b4Smrgvoid GLAPIENTRY
6307117f1b4Smrg_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
6317117f1b4Smrg{
6327117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
63301e04c3fSmrg
63401e04c3fSmrg   GLenum format = GL_RGBA;
635af69d88dSmrg   GLbitfield legalTypes = (ctx->API == API_OPENGLES)
636af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
637af69d88dSmrg      : (SHORT_BIT | INT_BIT | FLOAT_BIT |
638af69d88dSmrg         DOUBLE_BIT | HALF_BIT |
639af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
640af69d88dSmrg         INT_2_10_10_10_REV_BIT);
6417117f1b4Smrg
64201e04c3fSmrg   if (!validate_array_and_format(ctx, "glVertexPointer", VERT_ATTRIB_POS,
64301e04c3fSmrg                                  legalTypes, 2, 4, size, type, stride,
64401e04c3fSmrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format,
64501e04c3fSmrg                                  ptr, ctx->Array.VAO))
64601e04c3fSmrg      return;
64701e04c3fSmrg
64801e04c3fSmrg   update_array(ctx, VERT_ATTRIB_POS, format, 4, size, type, stride,
64901e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
65001e04c3fSmrg}
65101e04c3fSmrg
65201e04c3fSmrg
65301e04c3fSmrgvoid GLAPIENTRY
65401e04c3fSmrg_mesa_NormalPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr )
65501e04c3fSmrg{
65601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
6577117f1b4Smrg
65801e04c3fSmrg   update_array(ctx, VERT_ATTRIB_NORMAL, GL_RGBA, 3, 3, type, stride, GL_TRUE,
65901e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
6607117f1b4Smrg}
6617117f1b4Smrg
6627117f1b4Smrg
6637117f1b4Smrgvoid GLAPIENTRY
6647117f1b4Smrg_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
6657117f1b4Smrg{
6667117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
66701e04c3fSmrg
66801e04c3fSmrg   GLenum format = GL_RGBA;
669af69d88dSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
670af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
671af69d88dSmrg      : (BYTE_BIT | SHORT_BIT | INT_BIT |
672af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
673af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
674af69d88dSmrg         INT_2_10_10_10_REV_BIT);
675af69d88dSmrg
67601e04c3fSmrg   if (!validate_array_and_format(ctx, "glNormalPointer",
67701e04c3fSmrg                                  VERT_ATTRIB_NORMAL, legalTypes, 3, 3, 3,
67801e04c3fSmrg                                  type, stride, GL_TRUE, GL_FALSE,
67901e04c3fSmrg                                  GL_FALSE, format, ptr, ctx->Array.VAO))
68001e04c3fSmrg      return;
68101e04c3fSmrg
68201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_NORMAL, format, 3, 3, type, stride, GL_TRUE,
68301e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
68401e04c3fSmrg}
68501e04c3fSmrg
68601e04c3fSmrg
68701e04c3fSmrgvoid GLAPIENTRY
68801e04c3fSmrg_mesa_ColorPointer_no_error(GLint size, GLenum type, GLsizei stride,
68901e04c3fSmrg                            const GLvoid *ptr)
69001e04c3fSmrg{
69101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
6927117f1b4Smrg
69301e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
69401e04c3fSmrg   update_array(ctx, VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size,
69501e04c3fSmrg                type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
6967117f1b4Smrg}
6977117f1b4Smrg
6987117f1b4Smrg
6997117f1b4Smrgvoid GLAPIENTRY
7007117f1b4Smrg_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
7017117f1b4Smrg{
7027117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
70301e04c3fSmrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3;
70401e04c3fSmrg
70501e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
706af69d88dSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
707af69d88dSmrg      ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT)
708af69d88dSmrg      : (BYTE_BIT | UNSIGNED_BYTE_BIT |
709af69d88dSmrg         SHORT_BIT | UNSIGNED_SHORT_BIT |
710af69d88dSmrg         INT_BIT | UNSIGNED_INT_BIT |
711af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
712af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
713af69d88dSmrg         INT_2_10_10_10_REV_BIT);
714af69d88dSmrg
71501e04c3fSmrg   if (!validate_array_and_format(ctx, "glColorPointer",
71601e04c3fSmrg                                  VERT_ATTRIB_COLOR0, legalTypes, sizeMin,
71701e04c3fSmrg                                  BGRA_OR_4, size, type, stride, GL_TRUE,
71801e04c3fSmrg                                  GL_FALSE, GL_FALSE, format, ptr,
71901e04c3fSmrg                                  ctx->Array.VAO))
72001e04c3fSmrg      return;
72101e04c3fSmrg
72201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size,
72301e04c3fSmrg                type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
72401e04c3fSmrg}
72501e04c3fSmrg
72601e04c3fSmrg
72701e04c3fSmrgvoid GLAPIENTRY
72801e04c3fSmrg_mesa_FogCoordPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr)
72901e04c3fSmrg{
73001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
731af69d88dSmrg
73201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_FOG, GL_RGBA, 1, 1, type, stride, GL_FALSE,
73301e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
7347117f1b4Smrg}
7357117f1b4Smrg
7367117f1b4Smrg
7377117f1b4Smrgvoid GLAPIENTRY
738af69d88dSmrg_mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
7397117f1b4Smrg{
7407117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
7417117f1b4Smrg
74201e04c3fSmrg   GLenum format = GL_RGBA;
74301e04c3fSmrg   const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
74401e04c3fSmrg
74501e04c3fSmrg   if (!validate_array_and_format(ctx, "glFogCoordPointer",
74601e04c3fSmrg                                  VERT_ATTRIB_FOG, legalTypes, 1, 1, 1,
74701e04c3fSmrg                                  type, stride, GL_FALSE, GL_FALSE,
74801e04c3fSmrg                                  GL_FALSE, format, ptr, ctx->Array.VAO))
74901e04c3fSmrg      return;
75001e04c3fSmrg
75101e04c3fSmrg   update_array(ctx, VERT_ATTRIB_FOG, format, 1, 1, type, stride, GL_FALSE,
75201e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
75301e04c3fSmrg}
75401e04c3fSmrg
75501e04c3fSmrg
75601e04c3fSmrgvoid GLAPIENTRY
75701e04c3fSmrg_mesa_IndexPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr)
75801e04c3fSmrg{
75901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
760af69d88dSmrg
76101e04c3fSmrg   update_array(ctx, VERT_ATTRIB_COLOR_INDEX, GL_RGBA, 1, 1, type, stride,
76201e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
7637117f1b4Smrg}
7647117f1b4Smrg
7657117f1b4Smrg
7667117f1b4Smrgvoid GLAPIENTRY
7677117f1b4Smrg_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
7687117f1b4Smrg{
7697117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
7707117f1b4Smrg
77101e04c3fSmrg   GLenum format = GL_RGBA;
77201e04c3fSmrg   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT |
77301e04c3fSmrg                                     FLOAT_BIT | DOUBLE_BIT);
77401e04c3fSmrg
77501e04c3fSmrg   if (!validate_array_and_format(ctx, "glIndexPointer",
77601e04c3fSmrg                                  VERT_ATTRIB_COLOR_INDEX,
77701e04c3fSmrg                                  legalTypes, 1, 1, 1, type, stride,
77801e04c3fSmrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format,
77901e04c3fSmrg                                  ptr, ctx->Array.VAO))
78001e04c3fSmrg      return;
78101e04c3fSmrg
78201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_COLOR_INDEX, format, 1, 1, type, stride,
78301e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
78401e04c3fSmrg}
78501e04c3fSmrg
78601e04c3fSmrg
78701e04c3fSmrgvoid GLAPIENTRY
78801e04c3fSmrg_mesa_SecondaryColorPointer_no_error(GLint size, GLenum type,
78901e04c3fSmrg                                     GLsizei stride, const GLvoid *ptr)
79001e04c3fSmrg{
79101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
792af69d88dSmrg
79301e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
79401e04c3fSmrg   update_array(ctx, VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type,
79501e04c3fSmrg                stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
7967117f1b4Smrg}
7977117f1b4Smrg
7987117f1b4Smrg
7997117f1b4Smrgvoid GLAPIENTRY
800af69d88dSmrg_mesa_SecondaryColorPointer(GLint size, GLenum type,
8017117f1b4Smrg			       GLsizei stride, const GLvoid *ptr)
8027117f1b4Smrg{
80301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
80401e04c3fSmrg
80501e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
8063464ebd5Sriastradh   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
8073464ebd5Sriastradh                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
8083464ebd5Sriastradh                                  INT_BIT | UNSIGNED_INT_BIT |
809af69d88dSmrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
810af69d88dSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
811af69d88dSmrg                                  INT_2_10_10_10_REV_BIT);
8127117f1b4Smrg
81301e04c3fSmrg   if (!validate_array_and_format(ctx, "glSecondaryColorPointer",
81401e04c3fSmrg                                  VERT_ATTRIB_COLOR1, legalTypes, 3,
81501e04c3fSmrg                                  BGRA_OR_4, size, type, stride,
81601e04c3fSmrg                                  GL_TRUE, GL_FALSE, GL_FALSE, format, ptr,
81701e04c3fSmrg                                  ctx->Array.VAO))
81801e04c3fSmrg      return;
81901e04c3fSmrg
82001e04c3fSmrg   update_array(ctx, VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type,
82101e04c3fSmrg                stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
82201e04c3fSmrg}
82301e04c3fSmrg
82401e04c3fSmrg
82501e04c3fSmrgvoid GLAPIENTRY
82601e04c3fSmrg_mesa_TexCoordPointer_no_error(GLint size, GLenum type, GLsizei stride,
82701e04c3fSmrg                               const GLvoid *ptr)
82801e04c3fSmrg{
82901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
83001e04c3fSmrg   const GLuint unit = ctx->Array.ActiveTexture;
831af69d88dSmrg
83201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_TEX(unit), GL_RGBA, 4, size, type,
83301e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
8347117f1b4Smrg}
8357117f1b4Smrg
8367117f1b4Smrg
8377117f1b4Smrgvoid GLAPIENTRY
8387117f1b4Smrg_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
8397117f1b4Smrg                      const GLvoid *ptr)
8407117f1b4Smrg{
8417117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
84201e04c3fSmrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1;
84301e04c3fSmrg   const GLuint unit = ctx->Array.ActiveTexture;
84401e04c3fSmrg
84501e04c3fSmrg   GLenum format = GL_RGBA;
84601e04c3fSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
847af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
848af69d88dSmrg      : (SHORT_BIT | INT_BIT |
849af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
850af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
851af69d88dSmrg         INT_2_10_10_10_REV_BIT);
8527117f1b4Smrg
85301e04c3fSmrg   if (!validate_array_and_format(ctx, "glTexCoordPointer",
85401e04c3fSmrg                                  VERT_ATTRIB_TEX(unit), legalTypes,
85501e04c3fSmrg                                  sizeMin, 4, size, type, stride,
85601e04c3fSmrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format, ptr,
85701e04c3fSmrg                                  ctx->Array.VAO))
85801e04c3fSmrg      return;
85901e04c3fSmrg
86001e04c3fSmrg   update_array(ctx, VERT_ATTRIB_TEX(unit), format, 4, size, type,
86101e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
86201e04c3fSmrg}
86301e04c3fSmrg
86401e04c3fSmrg
86501e04c3fSmrgvoid GLAPIENTRY
86601e04c3fSmrg_mesa_EdgeFlagPointer_no_error(GLsizei stride, const GLvoid *ptr)
86701e04c3fSmrg{
86801e04c3fSmrg   /* this is the same type that glEdgeFlag uses */
86901e04c3fSmrg   const GLboolean integer = GL_FALSE;
87001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
871cdc920a0Smrg
87201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_EDGEFLAG, GL_RGBA, 1, 1, GL_UNSIGNED_BYTE,
87301e04c3fSmrg                stride, GL_FALSE, integer, GL_FALSE, ptr);
8747117f1b4Smrg}
8757117f1b4Smrg
8767117f1b4Smrg
8777117f1b4Smrgvoid GLAPIENTRY
8787117f1b4Smrg_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
8797117f1b4Smrg{
880af69d88dSmrg   /* this is the same type that glEdgeFlag uses */
881af69d88dSmrg   const GLboolean integer = GL_FALSE;
8827117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
8837117f1b4Smrg
88401e04c3fSmrg   GLenum format = GL_RGBA;
88501e04c3fSmrg   const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
88601e04c3fSmrg
88701e04c3fSmrg   if (!validate_array_and_format(ctx, "glEdgeFlagPointer",
88801e04c3fSmrg                                  VERT_ATTRIB_EDGEFLAG, legalTypes,
88901e04c3fSmrg                                  1, 1, 1, GL_UNSIGNED_BYTE, stride,
89001e04c3fSmrg                                  GL_FALSE, integer, GL_FALSE, format, ptr,
89101e04c3fSmrg                                  ctx->Array.VAO))
89201e04c3fSmrg      return;
893af69d88dSmrg
89401e04c3fSmrg   update_array(ctx, VERT_ATTRIB_EDGEFLAG, format, 1, 1, GL_UNSIGNED_BYTE,
89501e04c3fSmrg                stride, GL_FALSE, integer, GL_FALSE, ptr);
8967117f1b4Smrg}
8977117f1b4Smrg
8987117f1b4Smrg
899c1f859d4Smrgvoid GLAPIENTRY
90001e04c3fSmrg_mesa_PointSizePointerOES_no_error(GLenum type, GLsizei stride,
90101e04c3fSmrg                                   const GLvoid *ptr)
902c1f859d4Smrg{
903c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
904af69d88dSmrg
90501e04c3fSmrg   update_array(ctx, VERT_ATTRIB_POINT_SIZE, GL_RGBA, 1, 1, type, stride,
90601e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
90701e04c3fSmrg}
90801e04c3fSmrg
90901e04c3fSmrg
91001e04c3fSmrgvoid GLAPIENTRY
91101e04c3fSmrg_mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr)
91201e04c3fSmrg{
91301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
914c1f859d4Smrg
91501e04c3fSmrg   GLenum format = GL_RGBA;
9163464ebd5Sriastradh   if (ctx->API != API_OPENGLES) {
9173464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION,
9183464ebd5Sriastradh                  "glPointSizePointer(ES 1.x only)");
919c1f859d4Smrg      return;
920c1f859d4Smrg   }
92101e04c3fSmrg
92201e04c3fSmrg   const GLbitfield legalTypes = (FLOAT_BIT | FIXED_ES_BIT);
92301e04c3fSmrg
92401e04c3fSmrg   if (!validate_array_and_format(ctx, "glPointSizePointer",
92501e04c3fSmrg                                  VERT_ATTRIB_POINT_SIZE, legalTypes,
92601e04c3fSmrg                                  1, 1, 1, type, stride, GL_FALSE, GL_FALSE,
92701e04c3fSmrg                                  GL_FALSE, format, ptr, ctx->Array.VAO))
92801e04c3fSmrg      return;
92901e04c3fSmrg
93001e04c3fSmrg   update_array(ctx, VERT_ATTRIB_POINT_SIZE, format, 1, 1, type, stride,
93101e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
93201e04c3fSmrg}
93301e04c3fSmrg
93401e04c3fSmrg
93501e04c3fSmrgvoid GLAPIENTRY
93601e04c3fSmrg_mesa_VertexAttribPointer_no_error(GLuint index, GLint size, GLenum type,
93701e04c3fSmrg                                   GLboolean normalized,
93801e04c3fSmrg                                   GLsizei stride, const GLvoid *ptr)
93901e04c3fSmrg{
94001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
94101e04c3fSmrg
94201e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
94301e04c3fSmrg   update_array(ctx, VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4,
94401e04c3fSmrg                size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr);
945c1f859d4Smrg}
946c1f859d4Smrg
947c1f859d4Smrg
9484a49301eSmrg/**
9494a49301eSmrg * Set a generic vertex attribute array.
9504a49301eSmrg * Note that these arrays DO NOT alias the conventional GL vertex arrays
9514a49301eSmrg * (position, normal, color, fog, texcoord, etc).
9524a49301eSmrg */
9537117f1b4Smrgvoid GLAPIENTRY
954af69d88dSmrg_mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type,
9557117f1b4Smrg                             GLboolean normalized,
9567117f1b4Smrg                             GLsizei stride, const GLvoid *ptr)
9577117f1b4Smrg{
95801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
95901e04c3fSmrg
96001e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
96101e04c3fSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
96201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(idx)");
96301e04c3fSmrg      return;
96401e04c3fSmrg   }
96501e04c3fSmrg
9663464ebd5Sriastradh   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
9673464ebd5Sriastradh                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
9683464ebd5Sriastradh                                  INT_BIT | UNSIGNED_INT_BIT |
9693464ebd5Sriastradh                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
970af69d88dSmrg                                  FIXED_ES_BIT | FIXED_GL_BIT |
971af69d88dSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
972af69d88dSmrg                                  INT_2_10_10_10_REV_BIT |
973af69d88dSmrg                                  UNSIGNED_INT_10F_11F_11F_REV_BIT);
9747117f1b4Smrg
97501e04c3fSmrg   if (!validate_array_and_format(ctx, "glVertexAttribPointer",
97601e04c3fSmrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
97701e04c3fSmrg                                  1, BGRA_OR_4, size, type, stride,
97801e04c3fSmrg                                  normalized, GL_FALSE, GL_FALSE, format,
97901e04c3fSmrg                                  ptr, ctx->Array.VAO))
9807117f1b4Smrg      return;
9817117f1b4Smrg
98201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4,
98301e04c3fSmrg                size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr);
98401e04c3fSmrg}
98501e04c3fSmrg
98601e04c3fSmrg
98701e04c3fSmrgvoid GLAPIENTRY
98801e04c3fSmrg_mesa_VertexAttribIPointer_no_error(GLuint index, GLint size, GLenum type,
98901e04c3fSmrg                                    GLsizei stride, const GLvoid *ptr)
99001e04c3fSmrg{
99101e04c3fSmrg   const GLboolean normalized = GL_FALSE;
99201e04c3fSmrg   const GLboolean integer = GL_TRUE;
99301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
99401e04c3fSmrg
99501e04c3fSmrg   update_array(ctx, VERT_ATTRIB_GENERIC(index), GL_RGBA, 4,  size, type,
99601e04c3fSmrg                stride, normalized, integer, GL_FALSE, ptr);
9973464ebd5Sriastradh}
9983464ebd5Sriastradh
9993464ebd5Sriastradh
10003464ebd5Sriastradh/**
10013464ebd5Sriastradh * GL_EXT_gpu_shader4 / GL 3.0.
10023464ebd5Sriastradh * Set an integer-valued vertex attribute array.
10033464ebd5Sriastradh * Note that these arrays DO NOT alias the conventional GL vertex arrays
10043464ebd5Sriastradh * (position, normal, color, fog, texcoord, etc).
10053464ebd5Sriastradh */
10063464ebd5Sriastradhvoid GLAPIENTRY
10073464ebd5Sriastradh_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
10083464ebd5Sriastradh                           GLsizei stride, const GLvoid *ptr)
10093464ebd5Sriastradh{
10103464ebd5Sriastradh   const GLboolean normalized = GL_FALSE;
10113464ebd5Sriastradh   const GLboolean integer = GL_TRUE;
10123464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
10133464ebd5Sriastradh
101401e04c3fSmrg   GLenum format = GL_RGBA;
1015af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
10163464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)");
10173464ebd5Sriastradh      return;
10187117f1b4Smrg   }
10197117f1b4Smrg
102001e04c3fSmrg   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
102101e04c3fSmrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
102201e04c3fSmrg                                  INT_BIT | UNSIGNED_INT_BIT);
102301e04c3fSmrg
102401e04c3fSmrg   if (!validate_array_and_format(ctx, "glVertexAttribIPointer",
102501e04c3fSmrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
102601e04c3fSmrg                                  1, 4, size, type, stride,
102701e04c3fSmrg                                  normalized, integer, GL_FALSE, format,
102801e04c3fSmrg                                  ptr, ctx->Array.VAO))
102901e04c3fSmrg      return;
103001e04c3fSmrg
103101e04c3fSmrg   update_array(ctx, VERT_ATTRIB_GENERIC(index), format, 4,  size, type,
103201e04c3fSmrg                stride, normalized, integer, GL_FALSE, ptr);
10333464ebd5Sriastradh}
10343464ebd5Sriastradh
10353464ebd5Sriastradh
103601e04c3fSmrgvoid GLAPIENTRY
103701e04c3fSmrg_mesa_VertexAttribLPointer_no_error(GLuint index, GLint size, GLenum type,
103801e04c3fSmrg                                    GLsizei stride, const GLvoid *ptr)
103901e04c3fSmrg{
104001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
104101e04c3fSmrg
104201e04c3fSmrg   update_array(ctx, VERT_ATTRIB_GENERIC(index), GL_RGBA, 4, size, type,
104301e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr);
104401e04c3fSmrg}
104501e04c3fSmrg
10463464ebd5Sriastradh
10473464ebd5Sriastradhvoid GLAPIENTRY
104801e04c3fSmrg_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type,
104901e04c3fSmrg                           GLsizei stride, const GLvoid *ptr)
10503464ebd5Sriastradh{
10513464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
10523464ebd5Sriastradh
105301e04c3fSmrg   GLenum format = GL_RGBA;
1054af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
105501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribLPointer(index)");
10567117f1b4Smrg      return;
10577117f1b4Smrg   }
10587117f1b4Smrg
105901e04c3fSmrg   const GLbitfield legalTypes = DOUBLE_BIT;
106001e04c3fSmrg
106101e04c3fSmrg   if (!validate_array_and_format(ctx, "glVertexAttribLPointer",
106201e04c3fSmrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
106301e04c3fSmrg                                  1, 4, size, type, stride,
106401e04c3fSmrg                                  GL_FALSE, GL_FALSE, GL_TRUE, format,
106501e04c3fSmrg                                  ptr, ctx->Array.VAO))
106601e04c3fSmrg      return;
106701e04c3fSmrg
106801e04c3fSmrg   update_array(ctx, VERT_ATTRIB_GENERIC(index), format, 4, size, type,
106901e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr);
107001e04c3fSmrg}
107101e04c3fSmrg
1072af69d88dSmrg
107301e04c3fSmrgvoid
107401e04c3fSmrg_mesa_enable_vertex_array_attrib(struct gl_context *ctx,
107501e04c3fSmrg                                 struct gl_vertex_array_object *vao,
107601e04c3fSmrg                                 gl_vert_attrib attrib)
107701e04c3fSmrg{
107801e04c3fSmrg   assert(attrib < ARRAY_SIZE(vao->VertexAttrib));
107901e04c3fSmrg   assert(!vao->SharedAndImmutable);
10803464ebd5Sriastradh
108101e04c3fSmrg   if (!vao->VertexAttrib[attrib].Enabled) {
1082af69d88dSmrg      /* was disabled, now being enabled */
108301e04c3fSmrg      vao->VertexAttrib[attrib].Enabled = GL_TRUE;
108401e04c3fSmrg      const GLbitfield array_bit = VERT_BIT(attrib);
108501e04c3fSmrg      vao->_Enabled |= array_bit;
108601e04c3fSmrg      vao->NewArrays |= array_bit;
108701e04c3fSmrg
108801e04c3fSmrg      if (vao == ctx->Array.VAO)
108901e04c3fSmrg         ctx->NewState |= _NEW_ARRAY;
109001e04c3fSmrg
109101e04c3fSmrg      /* Update the map mode if needed */
109201e04c3fSmrg      if (array_bit & (VERT_BIT_POS|VERT_BIT_GENERIC0))
109301e04c3fSmrg         update_attribute_map_mode(ctx, vao);
109401e04c3fSmrg   }
109501e04c3fSmrg}
109601e04c3fSmrg
109701e04c3fSmrgstatic void
109801e04c3fSmrgenable_vertex_array_attrib(struct gl_context *ctx,
109901e04c3fSmrg                           struct gl_vertex_array_object *vao,
110001e04c3fSmrg                           GLuint index,
110101e04c3fSmrg                           const char *func)
110201e04c3fSmrg{
110301e04c3fSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
110401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
110501e04c3fSmrg      return;
1106af69d88dSmrg   }
110701e04c3fSmrg
110801e04c3fSmrg   _mesa_enable_vertex_array_attrib(ctx, vao, VERT_ATTRIB_GENERIC(index));
11093464ebd5Sriastradh}
11103464ebd5Sriastradh
11113464ebd5Sriastradh
11123464ebd5Sriastradhvoid GLAPIENTRY
111301e04c3fSmrg_mesa_EnableVertexAttribArray(GLuint index)
111401e04c3fSmrg{
111501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
111601e04c3fSmrg   enable_vertex_array_attrib(ctx, ctx->Array.VAO, index,
111701e04c3fSmrg                              "glEnableVertexAttribArray");
111801e04c3fSmrg}
111901e04c3fSmrg
112001e04c3fSmrg
112101e04c3fSmrgvoid GLAPIENTRY
112201e04c3fSmrg_mesa_EnableVertexAttribArray_no_error(GLuint index)
112301e04c3fSmrg{
112401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
112501e04c3fSmrg   _mesa_enable_vertex_array_attrib(ctx, ctx->Array.VAO,
112601e04c3fSmrg                                    VERT_ATTRIB_GENERIC(index));
112701e04c3fSmrg}
112801e04c3fSmrg
112901e04c3fSmrg
113001e04c3fSmrgvoid GLAPIENTRY
113101e04c3fSmrg_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index)
11323464ebd5Sriastradh{
113301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
1134af69d88dSmrg   struct gl_vertex_array_object *vao;
113501e04c3fSmrg
113601e04c3fSmrg   /* The ARB_direct_state_access specification says:
113701e04c3fSmrg    *
113801e04c3fSmrg    *   "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
113901e04c3fSmrg    *    and DisableVertexArrayAttrib if <vaobj> is not
114001e04c3fSmrg    *    [compatibility profile: zero or] the name of an existing vertex
114101e04c3fSmrg    *    array object."
114201e04c3fSmrg    */
114301e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glEnableVertexArrayAttrib");
114401e04c3fSmrg   if (!vao)
114501e04c3fSmrg      return;
114601e04c3fSmrg
114701e04c3fSmrg   enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttrib");
114801e04c3fSmrg}
114901e04c3fSmrg
115001e04c3fSmrg
115101e04c3fSmrgvoid GLAPIENTRY
115201e04c3fSmrg_mesa_EnableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index)
115301e04c3fSmrg{
115401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
115501e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
115601e04c3fSmrg   _mesa_enable_vertex_array_attrib(ctx, vao, VERT_ATTRIB_GENERIC(index));
115701e04c3fSmrg}
115801e04c3fSmrg
115901e04c3fSmrg
116001e04c3fSmrgvoid
116101e04c3fSmrg_mesa_disable_vertex_array_attrib(struct gl_context *ctx,
116201e04c3fSmrg                                  struct gl_vertex_array_object *vao,
116301e04c3fSmrg                                  gl_vert_attrib attrib)
116401e04c3fSmrg{
116501e04c3fSmrg   assert(attrib < ARRAY_SIZE(vao->VertexAttrib));
116601e04c3fSmrg   assert(!vao->SharedAndImmutable);
116701e04c3fSmrg
116801e04c3fSmrg   if (vao->VertexAttrib[attrib].Enabled) {
116901e04c3fSmrg      /* was enabled, now being disabled */
117001e04c3fSmrg      vao->VertexAttrib[attrib].Enabled = GL_FALSE;
117101e04c3fSmrg      const GLbitfield array_bit = VERT_BIT(attrib);
117201e04c3fSmrg      vao->_Enabled &= ~array_bit;
117301e04c3fSmrg      vao->NewArrays |= array_bit;
117401e04c3fSmrg
117501e04c3fSmrg      if (vao == ctx->Array.VAO)
117601e04c3fSmrg         ctx->NewState |= _NEW_ARRAY;
117701e04c3fSmrg
117801e04c3fSmrg      /* Update the map mode if needed */
117901e04c3fSmrg      if (array_bit & (VERT_BIT_POS|VERT_BIT_GENERIC0))
118001e04c3fSmrg         update_attribute_map_mode(ctx, vao);
118101e04c3fSmrg   }
118201e04c3fSmrg}
118301e04c3fSmrg
118401e04c3fSmrg
118501e04c3fSmrgvoid GLAPIENTRY
118601e04c3fSmrg_mesa_DisableVertexAttribArray(GLuint index)
118701e04c3fSmrg{
11883464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
11893464ebd5Sriastradh
1190af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
119101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexAttribArray(index)");
11923464ebd5Sriastradh      return;
11933464ebd5Sriastradh   }
11943464ebd5Sriastradh
119501e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
119601e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
119701e04c3fSmrg}
11983464ebd5Sriastradh
1199af69d88dSmrg
120001e04c3fSmrgvoid GLAPIENTRY
120101e04c3fSmrg_mesa_DisableVertexAttribArray_no_error(GLuint index)
120201e04c3fSmrg{
120301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
120401e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
120501e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
120601e04c3fSmrg}
120701e04c3fSmrg
120801e04c3fSmrg
120901e04c3fSmrgvoid GLAPIENTRY
121001e04c3fSmrg_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index)
121101e04c3fSmrg{
121201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
121301e04c3fSmrg   struct gl_vertex_array_object *vao;
121401e04c3fSmrg
121501e04c3fSmrg   /* The ARB_direct_state_access specification says:
121601e04c3fSmrg    *
121701e04c3fSmrg    *   "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
121801e04c3fSmrg    *    and DisableVertexArrayAttrib if <vaobj> is not
121901e04c3fSmrg    *    [compatibility profile: zero or] the name of an existing vertex
122001e04c3fSmrg    *    array object."
122101e04c3fSmrg    */
122201e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glDisableVertexArrayAttrib");
122301e04c3fSmrg   if (!vao)
122401e04c3fSmrg      return;
122501e04c3fSmrg
122601e04c3fSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
122701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexArrayAttrib(index)");
122801e04c3fSmrg      return;
1229af69d88dSmrg   }
123001e04c3fSmrg
123101e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
123201e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
123301e04c3fSmrg}
123401e04c3fSmrg
123501e04c3fSmrg
123601e04c3fSmrgvoid GLAPIENTRY
123701e04c3fSmrg_mesa_DisableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index)
123801e04c3fSmrg{
123901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
124001e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
124101e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
124201e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
12433464ebd5Sriastradh}
12443464ebd5Sriastradh
12453464ebd5Sriastradh
12463464ebd5Sriastradh/**
12473464ebd5Sriastradh * Return info for a vertex attribute array (no alias with legacy
12483464ebd5Sriastradh * vertex attributes (pos, normal, color, etc)).  This function does
12493464ebd5Sriastradh * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
12503464ebd5Sriastradh */
12513464ebd5Sriastradhstatic GLuint
125201e04c3fSmrgget_vertex_array_attrib(struct gl_context *ctx,
125301e04c3fSmrg                        const struct gl_vertex_array_object *vao,
125401e04c3fSmrg                        GLuint index, GLenum pname,
125501e04c3fSmrg                        const char *caller)
12563464ebd5Sriastradh{
125701e04c3fSmrg   const struct gl_array_attributes *array;
12583464ebd5Sriastradh
1259af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
12603464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
12613464ebd5Sriastradh      return 0;
12623464ebd5Sriastradh   }
12633464ebd5Sriastradh
126401e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
12653464ebd5Sriastradh
1266af69d88dSmrg   array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
12673464ebd5Sriastradh
12683464ebd5Sriastradh   switch (pname) {
12693464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
12703464ebd5Sriastradh      return array->Enabled;
12713464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
1272af69d88dSmrg      return (array->Format == GL_BGRA) ? GL_BGRA : array->Size;
12733464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
12743464ebd5Sriastradh      return array->Stride;
12753464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
12763464ebd5Sriastradh      return array->Type;
12773464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
12783464ebd5Sriastradh      return array->Normalized;
12793464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
128001e04c3fSmrg      return vao->BufferBinding[array->BufferBindingIndex].BufferObj->Name;
12813464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1282af69d88dSmrg      if ((_mesa_is_desktop_gl(ctx)
1283af69d88dSmrg           && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4))
1284af69d88dSmrg          || _mesa_is_gles3(ctx)) {
12853464ebd5Sriastradh         return array->Integer;
12864a49301eSmrg      }
12873464ebd5Sriastradh      goto error;
128801e04c3fSmrg   case GL_VERTEX_ATTRIB_ARRAY_LONG:
128901e04c3fSmrg      if (_mesa_is_desktop_gl(ctx)) {
129001e04c3fSmrg         return array->Doubles;
129101e04c3fSmrg      }
129201e04c3fSmrg      goto error;
12933464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
1294af69d88dSmrg      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
1295af69d88dSmrg          || _mesa_is_gles3(ctx)) {
129601e04c3fSmrg         return vao->BufferBinding[array->BufferBindingIndex].InstanceDivisor;
1297af69d88dSmrg      }
1298af69d88dSmrg      goto error;
1299af69d88dSmrg   case GL_VERTEX_ATTRIB_BINDING:
130001e04c3fSmrg      if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) {
130101e04c3fSmrg         return array->BufferBindingIndex - VERT_ATTRIB_GENERIC0;
1302af69d88dSmrg      }
1303af69d88dSmrg      goto error;
1304af69d88dSmrg   case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
130501e04c3fSmrg      if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) {
1306af69d88dSmrg         return array->RelativeOffset;
13074a49301eSmrg      }
13083464ebd5Sriastradh      goto error;
13093464ebd5Sriastradh   default:
13103464ebd5Sriastradh      ; /* fall-through */
13113464ebd5Sriastradh   }
13124a49301eSmrg
13133464ebd5Sriastradherror:
13143464ebd5Sriastradh   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname);
13153464ebd5Sriastradh   return 0;
13163464ebd5Sriastradh}
13173464ebd5Sriastradh
13183464ebd5Sriastradh
13193464ebd5Sriastradhstatic const GLfloat *
13203464ebd5Sriastradhget_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
13213464ebd5Sriastradh{
13223464ebd5Sriastradh   if (index == 0) {
1323af69d88dSmrg      if (_mesa_attr_zero_aliases_vertex(ctx)) {
13243464ebd5Sriastradh	 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
13253464ebd5Sriastradh	 return NULL;
13263464ebd5Sriastradh      }
13273464ebd5Sriastradh   }
1328af69d88dSmrg   else if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
13293464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE,
13303464ebd5Sriastradh		  "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function);
13313464ebd5Sriastradh      return NULL;
13323464ebd5Sriastradh   }
13333464ebd5Sriastradh
133401e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(index) <
133501e04c3fSmrg          ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
1336af69d88dSmrg
13373464ebd5Sriastradh   FLUSH_CURRENT(ctx, 0);
1338af69d88dSmrg   return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)];
13393464ebd5Sriastradh}
13403464ebd5Sriastradh
13413464ebd5Sriastradhvoid GLAPIENTRY
1342af69d88dSmrg_mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
13433464ebd5Sriastradh{
13443464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
13453464ebd5Sriastradh
13463464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
13473464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv");
13483464ebd5Sriastradh      if (v != NULL) {
13493464ebd5Sriastradh         COPY_4V(params, v);
13503464ebd5Sriastradh      }
13514a49301eSmrg   }
13524a49301eSmrg   else {
135301e04c3fSmrg      params[0] = (GLfloat) get_vertex_array_attrib(ctx, ctx->Array.VAO,
135401e04c3fSmrg                                                    index, pname,
13553464ebd5Sriastradh                                                    "glGetVertexAttribfv");
13564a49301eSmrg   }
13573464ebd5Sriastradh}
13584a49301eSmrg
13593464ebd5Sriastradh
13603464ebd5Sriastradhvoid GLAPIENTRY
1361af69d88dSmrg_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params)
13623464ebd5Sriastradh{
13633464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
13643464ebd5Sriastradh
13653464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
13663464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv");
13673464ebd5Sriastradh      if (v != NULL) {
13683464ebd5Sriastradh         params[0] = (GLdouble) v[0];
13693464ebd5Sriastradh         params[1] = (GLdouble) v[1];
13703464ebd5Sriastradh         params[2] = (GLdouble) v[2];
13713464ebd5Sriastradh         params[3] = (GLdouble) v[3];
13723464ebd5Sriastradh      }
13733464ebd5Sriastradh   }
13743464ebd5Sriastradh   else {
137501e04c3fSmrg      params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
137601e04c3fSmrg                                                     index, pname,
13773464ebd5Sriastradh                                                     "glGetVertexAttribdv");
13787117f1b4Smrg   }
13793464ebd5Sriastradh}
13807117f1b4Smrg
138101e04c3fSmrgvoid GLAPIENTRY
138201e04c3fSmrg_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params)
138301e04c3fSmrg{
138401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
138501e04c3fSmrg
138601e04c3fSmrg   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
138701e04c3fSmrg      const GLdouble *v =
138801e04c3fSmrg         (const GLdouble *)get_current_attrib(ctx, index,
138901e04c3fSmrg                                              "glGetVertexAttribLdv");
139001e04c3fSmrg      if (v != NULL) {
139101e04c3fSmrg         params[0] = v[0];
139201e04c3fSmrg         params[1] = v[1];
139301e04c3fSmrg         params[2] = v[2];
139401e04c3fSmrg         params[3] = v[3];
139501e04c3fSmrg      }
139601e04c3fSmrg   }
139701e04c3fSmrg   else {
139801e04c3fSmrg      params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
139901e04c3fSmrg                                                     index, pname,
140001e04c3fSmrg                                                     "glGetVertexAttribLdv");
140101e04c3fSmrg   }
140201e04c3fSmrg}
14033464ebd5Sriastradh
14043464ebd5Sriastradhvoid GLAPIENTRY
1405af69d88dSmrg_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
14063464ebd5Sriastradh{
14073464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
14083464ebd5Sriastradh
14093464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
14103464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv");
14113464ebd5Sriastradh      if (v != NULL) {
14123464ebd5Sriastradh         /* XXX should floats in[0,1] be scaled to full int range? */
14133464ebd5Sriastradh         params[0] = (GLint) v[0];
14143464ebd5Sriastradh         params[1] = (GLint) v[1];
14153464ebd5Sriastradh         params[2] = (GLint) v[2];
14163464ebd5Sriastradh         params[3] = (GLint) v[3];
14173464ebd5Sriastradh      }
14183464ebd5Sriastradh   }
14193464ebd5Sriastradh   else {
142001e04c3fSmrg      params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
142101e04c3fSmrg                                                  index, pname,
14223464ebd5Sriastradh                                                  "glGetVertexAttribiv");
14233464ebd5Sriastradh   }
14243464ebd5Sriastradh}
14253464ebd5Sriastradh
142601e04c3fSmrgvoid GLAPIENTRY
142701e04c3fSmrg_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params)
142801e04c3fSmrg{
142901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
143001e04c3fSmrg
143101e04c3fSmrg   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
143201e04c3fSmrg      const GLuint64 *v =
143301e04c3fSmrg         (const GLuint64 *)get_current_attrib(ctx, index,
143401e04c3fSmrg                                              "glGetVertexAttribLui64vARB");
143501e04c3fSmrg      if (v != NULL) {
143601e04c3fSmrg         params[0] = v[0];
143701e04c3fSmrg         params[1] = v[1];
143801e04c3fSmrg         params[2] = v[2];
143901e04c3fSmrg         params[3] = v[3];
144001e04c3fSmrg      }
144101e04c3fSmrg   }
144201e04c3fSmrg   else {
144301e04c3fSmrg      params[0] = (GLuint64) get_vertex_array_attrib(ctx, ctx->Array.VAO,
144401e04c3fSmrg                                                     index, pname,
144501e04c3fSmrg                                                     "glGetVertexAttribLui64vARB");
144601e04c3fSmrg   }
144701e04c3fSmrg}
144801e04c3fSmrg
14493464ebd5Sriastradh
14503464ebd5Sriastradh/** GL 3.0 */
14513464ebd5Sriastradhvoid GLAPIENTRY
14523464ebd5Sriastradh_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
14533464ebd5Sriastradh{
14543464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
14553464ebd5Sriastradh
14563464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
1457af69d88dSmrg      const GLint *v = (const GLint *)
14583464ebd5Sriastradh	 get_current_attrib(ctx, index, "glGetVertexAttribIiv");
14593464ebd5Sriastradh      if (v != NULL) {
1460af69d88dSmrg         COPY_4V(params, v);
14613464ebd5Sriastradh      }
14623464ebd5Sriastradh   }
14633464ebd5Sriastradh   else {
146401e04c3fSmrg      params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
146501e04c3fSmrg                                                  index, pname,
14663464ebd5Sriastradh                                                  "glGetVertexAttribIiv");
14673464ebd5Sriastradh   }
14683464ebd5Sriastradh}
14693464ebd5Sriastradh
14703464ebd5Sriastradh
14713464ebd5Sriastradh/** GL 3.0 */
14723464ebd5Sriastradhvoid GLAPIENTRY
14733464ebd5Sriastradh_mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
14743464ebd5Sriastradh{
14753464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
14763464ebd5Sriastradh
14773464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
1478af69d88dSmrg      const GLuint *v = (const GLuint *)
14793464ebd5Sriastradh	 get_current_attrib(ctx, index, "glGetVertexAttribIuiv");
14803464ebd5Sriastradh      if (v != NULL) {
1481af69d88dSmrg         COPY_4V(params, v);
14823464ebd5Sriastradh      }
14833464ebd5Sriastradh   }
14843464ebd5Sriastradh   else {
148501e04c3fSmrg      params[0] = get_vertex_array_attrib(ctx, ctx->Array.VAO,
148601e04c3fSmrg                                          index, pname,
14873464ebd5Sriastradh                                          "glGetVertexAttribIuiv");
14883464ebd5Sriastradh   }
14893464ebd5Sriastradh}
14903464ebd5Sriastradh
14913464ebd5Sriastradh
14923464ebd5Sriastradhvoid GLAPIENTRY
1493af69d88dSmrg_mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
14943464ebd5Sriastradh{
14953464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
14963464ebd5Sriastradh
1497af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
14983464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
14993464ebd5Sriastradh      return;
15003464ebd5Sriastradh   }
15013464ebd5Sriastradh
15023464ebd5Sriastradh   if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
15033464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
15043464ebd5Sriastradh      return;
15053464ebd5Sriastradh   }
15063464ebd5Sriastradh
150701e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(index) <
150801e04c3fSmrg          ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
150901e04c3fSmrg
151001e04c3fSmrg   *pointer = (GLvoid *)
151101e04c3fSmrg      ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
151201e04c3fSmrg}
151301e04c3fSmrg
151401e04c3fSmrg
151501e04c3fSmrg/** ARB_direct_state_access */
151601e04c3fSmrgvoid GLAPIENTRY
151701e04c3fSmrg_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index,
151801e04c3fSmrg                              GLenum pname, GLint *params)
151901e04c3fSmrg{
152001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
152101e04c3fSmrg   struct gl_vertex_array_object *vao;
152201e04c3fSmrg
152301e04c3fSmrg   /* The ARB_direct_state_access specification says:
152401e04c3fSmrg    *
152501e04c3fSmrg    *    "An INVALID_OPERATION error is generated if <vaobj> is not
152601e04c3fSmrg    *     [compatibility profile: zero or] the name of an existing
152701e04c3fSmrg    *     vertex array object."
152801e04c3fSmrg    */
152901e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexediv");
153001e04c3fSmrg   if (!vao)
153101e04c3fSmrg      return;
153201e04c3fSmrg
153301e04c3fSmrg   /* The ARB_direct_state_access specification says:
153401e04c3fSmrg    *
153501e04c3fSmrg    *    "For GetVertexArrayIndexediv, <pname> must be one of
153601e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_ENABLED, VERTEX_ATTRIB_ARRAY_SIZE,
153701e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_STRIDE, VERTEX_ATTRIB_ARRAY_TYPE,
153801e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_NORMALIZED, VERTEX_ATTRIB_ARRAY_INTEGER,
153901e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_LONG, VERTEX_ATTRIB_ARRAY_DIVISOR, or
154001e04c3fSmrg    *     VERTEX_ATTRIB_RELATIVE_OFFSET."
154101e04c3fSmrg    *
154201e04c3fSmrg    * and:
154301e04c3fSmrg    *
154401e04c3fSmrg    *    "Add GetVertexArrayIndexediv in 'Get Command' for
154501e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
154601e04c3fSmrg    *     VERTEX_ATTRIB_BINDING,
154701e04c3fSmrg    *     VERTEX_ATTRIB_RELATIVE_OFFSET,
154801e04c3fSmrg    *     VERTEX_BINDING_OFFSET, and
154901e04c3fSmrg    *     VERTEX_BINDING_STRIDE states"
155001e04c3fSmrg    *
155101e04c3fSmrg    * The only parameter name common to both lists is
155201e04c3fSmrg    * VERTEX_ATTRIB_RELATIVE_OFFSET.  Also note that VERTEX_BINDING_BUFFER
155301e04c3fSmrg    * and VERTEX_BINDING_DIVISOR are missing from both lists.  It seems
155401e04c3fSmrg    * pretty clear however that the intent is that it should be possible
155501e04c3fSmrg    * to query all vertex attrib and binding states that can be set with
155601e04c3fSmrg    * a DSA function.
155701e04c3fSmrg    */
155801e04c3fSmrg   switch (pname) {
155901e04c3fSmrg   case GL_VERTEX_BINDING_OFFSET:
156001e04c3fSmrg      params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Offset;
156101e04c3fSmrg      break;
156201e04c3fSmrg   case GL_VERTEX_BINDING_STRIDE:
156301e04c3fSmrg      params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Stride;
156401e04c3fSmrg      break;
156501e04c3fSmrg   case GL_VERTEX_BINDING_DIVISOR:
156601e04c3fSmrg      params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor;
156701e04c3fSmrg      break;
156801e04c3fSmrg   case GL_VERTEX_BINDING_BUFFER:
156901e04c3fSmrg      params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].BufferObj->Name;
157001e04c3fSmrg      break;
157101e04c3fSmrg   default:
157201e04c3fSmrg      params[0] = get_vertex_array_attrib(ctx, vao, index, pname,
157301e04c3fSmrg                                          "glGetVertexArrayIndexediv");
157401e04c3fSmrg      break;
157501e04c3fSmrg   }
157601e04c3fSmrg}
157701e04c3fSmrg
157801e04c3fSmrg
157901e04c3fSmrgvoid GLAPIENTRY
158001e04c3fSmrg_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index,
158101e04c3fSmrg                                GLenum pname, GLint64 *params)
158201e04c3fSmrg{
158301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
158401e04c3fSmrg   struct gl_vertex_array_object *vao;
158501e04c3fSmrg
158601e04c3fSmrg   /* The ARB_direct_state_access specification says:
158701e04c3fSmrg    *
158801e04c3fSmrg    *    "An INVALID_OPERATION error is generated if <vaobj> is not
158901e04c3fSmrg    *     [compatibility profile: zero or] the name of an existing
159001e04c3fSmrg    *     vertex array object."
159101e04c3fSmrg    */
159201e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayIndexed64iv");
159301e04c3fSmrg   if (!vao)
159401e04c3fSmrg      return;
159501e04c3fSmrg
159601e04c3fSmrg   /* The ARB_direct_state_access specification says:
159701e04c3fSmrg    *
159801e04c3fSmrg    *    "For GetVertexArrayIndexed64iv, <pname> must be
159901e04c3fSmrg    *     VERTEX_BINDING_OFFSET."
160001e04c3fSmrg    *
160101e04c3fSmrg    * and:
160201e04c3fSmrg    *
160301e04c3fSmrg    *    "An INVALID_ENUM error is generated if <pname> is not one of
160401e04c3fSmrg    *     the valid values listed above for the corresponding command."
160501e04c3fSmrg    */
160601e04c3fSmrg   if (pname != GL_VERTEX_BINDING_OFFSET) {
160701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIndexed64iv("
160801e04c3fSmrg                  "pname != GL_VERTEX_BINDING_OFFSET)");
160901e04c3fSmrg      return;
161001e04c3fSmrg   }
161101e04c3fSmrg
161201e04c3fSmrg   /* The ARB_direct_state_access specification says:
161301e04c3fSmrg    *
161401e04c3fSmrg    *    "An INVALID_VALUE error is generated if <index> is greater than
161501e04c3fSmrg    *     or equal to the value of MAX_VERTEX_ATTRIBS."
161601e04c3fSmrg    *
161701e04c3fSmrg    * Since the index refers to a buffer binding in this case, the intended
161801e04c3fSmrg    * limit must be MAX_VERTEX_ATTRIB_BINDINGS.  Both limits are currently
161901e04c3fSmrg    * required to be the same, so in practice this doesn't matter.
162001e04c3fSmrg    */
162101e04c3fSmrg   if (index >= ctx->Const.MaxVertexAttribBindings) {
162201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayIndexed64iv(index"
162301e04c3fSmrg                  "%d >= the value of GL_MAX_VERTEX_ATTRIB_BINDINGS (%d))",
162401e04c3fSmrg                  index, ctx->Const.MaxVertexAttribBindings);
162501e04c3fSmrg      return;
162601e04c3fSmrg   }
16273464ebd5Sriastradh
162801e04c3fSmrg   params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Offset;
16297117f1b4Smrg}
16307117f1b4Smrg
16317117f1b4Smrg
16327117f1b4Smrgvoid GLAPIENTRY
16337117f1b4Smrg_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
16347117f1b4Smrg                       GLsizei count, const GLvoid *ptr)
16357117f1b4Smrg{
16367117f1b4Smrg   (void) count;
16377117f1b4Smrg   _mesa_VertexPointer(size, type, stride, ptr);
16387117f1b4Smrg}
16397117f1b4Smrg
16407117f1b4Smrg
16417117f1b4Smrgvoid GLAPIENTRY
16427117f1b4Smrg_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
16437117f1b4Smrg                       const GLvoid *ptr)
16447117f1b4Smrg{
16457117f1b4Smrg   (void) count;
16467117f1b4Smrg   _mesa_NormalPointer(type, stride, ptr);
16477117f1b4Smrg}
16487117f1b4Smrg
16497117f1b4Smrg
16507117f1b4Smrgvoid GLAPIENTRY
16517117f1b4Smrg_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
16527117f1b4Smrg                      const GLvoid *ptr)
16537117f1b4Smrg{
16547117f1b4Smrg   (void) count;
16557117f1b4Smrg   _mesa_ColorPointer(size, type, stride, ptr);
16567117f1b4Smrg}
16577117f1b4Smrg
16587117f1b4Smrg
16597117f1b4Smrgvoid GLAPIENTRY
16607117f1b4Smrg_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
16617117f1b4Smrg                      const GLvoid *ptr)
16627117f1b4Smrg{
16637117f1b4Smrg   (void) count;
16647117f1b4Smrg   _mesa_IndexPointer(type, stride, ptr);
16657117f1b4Smrg}
16667117f1b4Smrg
16677117f1b4Smrg
16687117f1b4Smrgvoid GLAPIENTRY
16697117f1b4Smrg_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
16707117f1b4Smrg                         GLsizei count, const GLvoid *ptr)
16717117f1b4Smrg{
16727117f1b4Smrg   (void) count;
16737117f1b4Smrg   _mesa_TexCoordPointer(size, type, stride, ptr);
16747117f1b4Smrg}
16757117f1b4Smrg
16767117f1b4Smrg
16777117f1b4Smrgvoid GLAPIENTRY
16787117f1b4Smrg_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
16797117f1b4Smrg{
16807117f1b4Smrg   (void) count;
16817117f1b4Smrg   _mesa_EdgeFlagPointer(stride, ptr);
16827117f1b4Smrg}
16837117f1b4Smrg
16847117f1b4Smrg
16857117f1b4Smrgvoid GLAPIENTRY
16867117f1b4Smrg_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
16877117f1b4Smrg{
16887117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
16897117f1b4Smrg   GLboolean tflag, cflag, nflag;  /* enable/disable flags */
16907117f1b4Smrg   GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
16917117f1b4Smrg   GLenum ctype = 0;               /* color type */
16927117f1b4Smrg   GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
16937117f1b4Smrg   const GLint toffset = 0;        /* always zero */
16947117f1b4Smrg   GLint defstride;                /* default stride */
16957117f1b4Smrg   GLint c, f;
16967117f1b4Smrg
16977117f1b4Smrg   f = sizeof(GLfloat);
16987117f1b4Smrg   c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
16997117f1b4Smrg
17007117f1b4Smrg   if (stride < 0) {
17017117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
17027117f1b4Smrg      return;
17037117f1b4Smrg   }
17047117f1b4Smrg
17057117f1b4Smrg   switch (format) {
17067117f1b4Smrg      case GL_V2F:
17077117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
17087117f1b4Smrg         tcomps = 0;  ccomps = 0;  vcomps = 2;
17097117f1b4Smrg         voffset = 0;
17107117f1b4Smrg         defstride = 2*f;
17117117f1b4Smrg         break;
17127117f1b4Smrg      case GL_V3F:
17137117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
17147117f1b4Smrg         tcomps = 0;  ccomps = 0;  vcomps = 3;
17157117f1b4Smrg         voffset = 0;
17167117f1b4Smrg         defstride = 3*f;
17177117f1b4Smrg         break;
17187117f1b4Smrg      case GL_C4UB_V2F:
17197117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
17207117f1b4Smrg         tcomps = 0;  ccomps = 4;  vcomps = 2;
17217117f1b4Smrg         ctype = GL_UNSIGNED_BYTE;
17227117f1b4Smrg         coffset = 0;
17237117f1b4Smrg         voffset = c;
17247117f1b4Smrg         defstride = c + 2*f;
17257117f1b4Smrg         break;
17267117f1b4Smrg      case GL_C4UB_V3F:
17277117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
17287117f1b4Smrg         tcomps = 0;  ccomps = 4;  vcomps = 3;
17297117f1b4Smrg         ctype = GL_UNSIGNED_BYTE;
17307117f1b4Smrg         coffset = 0;
17317117f1b4Smrg         voffset = c;
17327117f1b4Smrg         defstride = c + 3*f;
17337117f1b4Smrg         break;
17347117f1b4Smrg      case GL_C3F_V3F:
17357117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
17367117f1b4Smrg         tcomps = 0;  ccomps = 3;  vcomps = 3;
17377117f1b4Smrg         ctype = GL_FLOAT;
17387117f1b4Smrg         coffset = 0;
17397117f1b4Smrg         voffset = 3*f;
17407117f1b4Smrg         defstride = 6*f;
17417117f1b4Smrg         break;
17427117f1b4Smrg      case GL_N3F_V3F:
17437117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
17447117f1b4Smrg         tcomps = 0;  ccomps = 0;  vcomps = 3;
17457117f1b4Smrg         noffset = 0;
17467117f1b4Smrg         voffset = 3*f;
17477117f1b4Smrg         defstride = 6*f;
17487117f1b4Smrg         break;
17497117f1b4Smrg      case GL_C4F_N3F_V3F:
17507117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
17517117f1b4Smrg         tcomps = 0;  ccomps = 4;  vcomps = 3;
17527117f1b4Smrg         ctype = GL_FLOAT;
17537117f1b4Smrg         coffset = 0;
17547117f1b4Smrg         noffset = 4*f;
17557117f1b4Smrg         voffset = 7*f;
17567117f1b4Smrg         defstride = 10*f;
17577117f1b4Smrg         break;
17587117f1b4Smrg      case GL_T2F_V3F:
17597117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
17607117f1b4Smrg         tcomps = 2;  ccomps = 0;  vcomps = 3;
17617117f1b4Smrg         voffset = 2*f;
17627117f1b4Smrg         defstride = 5*f;
17637117f1b4Smrg         break;
17647117f1b4Smrg      case GL_T4F_V4F:
17657117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
17667117f1b4Smrg         tcomps = 4;  ccomps = 0;  vcomps = 4;
17677117f1b4Smrg         voffset = 4*f;
17687117f1b4Smrg         defstride = 8*f;
17697117f1b4Smrg         break;
17707117f1b4Smrg      case GL_T2F_C4UB_V3F:
17717117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
17727117f1b4Smrg         tcomps = 2;  ccomps = 4;  vcomps = 3;
17737117f1b4Smrg         ctype = GL_UNSIGNED_BYTE;
17747117f1b4Smrg         coffset = 2*f;
17757117f1b4Smrg         voffset = c+2*f;
17767117f1b4Smrg         defstride = c+5*f;
17777117f1b4Smrg         break;
17787117f1b4Smrg      case GL_T2F_C3F_V3F:
17797117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
17807117f1b4Smrg         tcomps = 2;  ccomps = 3;  vcomps = 3;
17817117f1b4Smrg         ctype = GL_FLOAT;
17827117f1b4Smrg         coffset = 2*f;
17837117f1b4Smrg         voffset = 5*f;
17847117f1b4Smrg         defstride = 8*f;
17857117f1b4Smrg         break;
17867117f1b4Smrg      case GL_T2F_N3F_V3F:
17877117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
17887117f1b4Smrg         tcomps = 2;  ccomps = 0;  vcomps = 3;
17897117f1b4Smrg         noffset = 2*f;
17907117f1b4Smrg         voffset = 5*f;
17917117f1b4Smrg         defstride = 8*f;
17927117f1b4Smrg         break;
17937117f1b4Smrg      case GL_T2F_C4F_N3F_V3F:
17947117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
17957117f1b4Smrg         tcomps = 2;  ccomps = 4;  vcomps = 3;
17967117f1b4Smrg         ctype = GL_FLOAT;
17977117f1b4Smrg         coffset = 2*f;
17987117f1b4Smrg         noffset = 6*f;
17997117f1b4Smrg         voffset = 9*f;
18007117f1b4Smrg         defstride = 12*f;
18017117f1b4Smrg         break;
18027117f1b4Smrg      case GL_T4F_C4F_N3F_V4F:
18037117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
18047117f1b4Smrg         tcomps = 4;  ccomps = 4;  vcomps = 4;
18057117f1b4Smrg         ctype = GL_FLOAT;
18067117f1b4Smrg         coffset = 4*f;
18077117f1b4Smrg         noffset = 8*f;
18087117f1b4Smrg         voffset = 11*f;
18097117f1b4Smrg         defstride = 15*f;
18107117f1b4Smrg         break;
18117117f1b4Smrg      default:
18127117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
18137117f1b4Smrg         return;
18147117f1b4Smrg   }
18157117f1b4Smrg
18167117f1b4Smrg   if (stride==0) {
18177117f1b4Smrg      stride = defstride;
18187117f1b4Smrg   }
18197117f1b4Smrg
18207117f1b4Smrg   _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
18217117f1b4Smrg   _mesa_DisableClientState( GL_INDEX_ARRAY );
18227117f1b4Smrg   /* XXX also disable secondary color and generic arrays? */
18237117f1b4Smrg
18247117f1b4Smrg   /* Texcoords */
18257117f1b4Smrg   if (tflag) {
18267117f1b4Smrg      _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
18277117f1b4Smrg      _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
18287117f1b4Smrg                             (GLubyte *) pointer + toffset );
18297117f1b4Smrg   }
18307117f1b4Smrg   else {
18317117f1b4Smrg      _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
18327117f1b4Smrg   }
18337117f1b4Smrg
18347117f1b4Smrg   /* Color */
18357117f1b4Smrg   if (cflag) {
18367117f1b4Smrg      _mesa_EnableClientState( GL_COLOR_ARRAY );
18377117f1b4Smrg      _mesa_ColorPointer( ccomps, ctype, stride,
18387117f1b4Smrg			  (GLubyte *) pointer + coffset );
18397117f1b4Smrg   }
18407117f1b4Smrg   else {
18417117f1b4Smrg      _mesa_DisableClientState( GL_COLOR_ARRAY );
18427117f1b4Smrg   }
18437117f1b4Smrg
18447117f1b4Smrg
18457117f1b4Smrg   /* Normals */
18467117f1b4Smrg   if (nflag) {
18477117f1b4Smrg      _mesa_EnableClientState( GL_NORMAL_ARRAY );
18487117f1b4Smrg      _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
18497117f1b4Smrg   }
18507117f1b4Smrg   else {
18517117f1b4Smrg      _mesa_DisableClientState( GL_NORMAL_ARRAY );
18527117f1b4Smrg   }
18537117f1b4Smrg
18547117f1b4Smrg   /* Vertices */
18557117f1b4Smrg   _mesa_EnableClientState( GL_VERTEX_ARRAY );
18567117f1b4Smrg   _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
18577117f1b4Smrg			(GLubyte *) pointer + voffset );
18587117f1b4Smrg}
18597117f1b4Smrg
18607117f1b4Smrg
18617117f1b4Smrgvoid GLAPIENTRY
18627117f1b4Smrg_mesa_LockArraysEXT(GLint first, GLsizei count)
18637117f1b4Smrg{
18647117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1865af69d88dSmrg
18667117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
18677117f1b4Smrg      _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
18687117f1b4Smrg
1869c1f859d4Smrg   if (first < 0) {
1870c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
1871c1f859d4Smrg      return;
18727117f1b4Smrg   }
1873c1f859d4Smrg   if (count <= 0) {
1874c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
1875c1f859d4Smrg      return;
1876c1f859d4Smrg   }
1877c1f859d4Smrg   if (ctx->Array.LockCount != 0) {
1878c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
1879c1f859d4Smrg      return;
18807117f1b4Smrg   }
18817117f1b4Smrg
1882c1f859d4Smrg   ctx->Array.LockFirst = first;
1883c1f859d4Smrg   ctx->Array.LockCount = count;
1884c1f859d4Smrg
18857117f1b4Smrg   ctx->NewState |= _NEW_ARRAY;
18867117f1b4Smrg}
18877117f1b4Smrg
18887117f1b4Smrg
18897117f1b4Smrgvoid GLAPIENTRY
18907117f1b4Smrg_mesa_UnlockArraysEXT( void )
18917117f1b4Smrg{
18927117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1893af69d88dSmrg
18947117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
18957117f1b4Smrg      _mesa_debug(ctx, "glUnlockArrays\n");
18967117f1b4Smrg
1897c1f859d4Smrg   if (ctx->Array.LockCount == 0) {
1898c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
1899c1f859d4Smrg      return;
1900c1f859d4Smrg   }
1901c1f859d4Smrg
19027117f1b4Smrg   ctx->Array.LockFirst = 0;
19037117f1b4Smrg   ctx->Array.LockCount = 0;
19047117f1b4Smrg   ctx->NewState |= _NEW_ARRAY;
19057117f1b4Smrg}
19067117f1b4Smrg
19077117f1b4Smrg
190801e04c3fSmrgstatic void
190901e04c3fSmrgprimitive_restart_index(struct gl_context *ctx, GLuint index)
19107117f1b4Smrg{
191101e04c3fSmrg   ctx->Array.RestartIndex = index;
19127117f1b4Smrg}
19137117f1b4Smrg
19147117f1b4Smrg
191501e04c3fSmrg/**
191601e04c3fSmrg * GL_NV_primitive_restart and GL 3.1
191701e04c3fSmrg */
19187117f1b4Smrgvoid GLAPIENTRY
191901e04c3fSmrg_mesa_PrimitiveRestartIndex_no_error(GLuint index)
19207117f1b4Smrg{
19217117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
192201e04c3fSmrg   primitive_restart_index(ctx, index);
19237117f1b4Smrg}
19247117f1b4Smrg
19257117f1b4Smrg
19267117f1b4Smrgvoid GLAPIENTRY
192701e04c3fSmrg_mesa_PrimitiveRestartIndex(GLuint index)
19287117f1b4Smrg{
19297117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
19307117f1b4Smrg
193101e04c3fSmrg   if (!ctx->Extensions.NV_primitive_restart && ctx->Version < 31) {
193201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()");
193301e04c3fSmrg      return;
19347117f1b4Smrg   }
193501e04c3fSmrg
193601e04c3fSmrg   primitive_restart_index(ctx, index);
19377117f1b4Smrg}
19387117f1b4Smrg
19397117f1b4Smrg
19403464ebd5Sriastradhvoid GLAPIENTRY
194101e04c3fSmrg_mesa_VertexAttribDivisor_no_error(GLuint index, GLuint divisor)
19423464ebd5Sriastradh{
19433464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
19443464ebd5Sriastradh
194501e04c3fSmrg   const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index);
194601e04c3fSmrg   struct gl_vertex_array_object * const vao = ctx->Array.VAO;
19473464ebd5Sriastradh
194801e04c3fSmrg   assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
194901e04c3fSmrg
195001e04c3fSmrg   /* The ARB_vertex_attrib_binding spec says:
195101e04c3fSmrg    *
195201e04c3fSmrg    *    "The command
195301e04c3fSmrg    *
195401e04c3fSmrg    *       void VertexAttribDivisor(uint index, uint divisor);
195501e04c3fSmrg    *
195601e04c3fSmrg    *     is equivalent to (assuming no errors are generated):
195701e04c3fSmrg    *
195801e04c3fSmrg    *       VertexAttribBinding(index, index);
195901e04c3fSmrg    *       VertexBindingDivisor(index, divisor);"
196001e04c3fSmrg    */
196101e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
196201e04c3fSmrg   vertex_binding_divisor(ctx, vao, genericIndex, divisor);
19633464ebd5Sriastradh}
19643464ebd5Sriastradh
19653464ebd5Sriastradh
19663464ebd5Sriastradh/**
19673464ebd5Sriastradh * See GL_ARB_instanced_arrays.
19683464ebd5Sriastradh * Note that the instance divisor only applies to generic arrays, not
19693464ebd5Sriastradh * the legacy vertex arrays.
19703464ebd5Sriastradh */
19713464ebd5Sriastradhvoid GLAPIENTRY
19723464ebd5Sriastradh_mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
19733464ebd5Sriastradh{
19743464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
1975af69d88dSmrg
197601e04c3fSmrg   const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index);
197701e04c3fSmrg   struct gl_vertex_array_object * const vao = ctx->Array.VAO;
19783464ebd5Sriastradh
19793464ebd5Sriastradh   if (!ctx->Extensions.ARB_instanced_arrays) {
19803464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
19813464ebd5Sriastradh      return;
19823464ebd5Sriastradh   }
19833464ebd5Sriastradh
1984af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
198501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
198601e04c3fSmrg                  "glVertexAttribDivisor(index = %u)", index);
19873464ebd5Sriastradh      return;
19883464ebd5Sriastradh   }
19893464ebd5Sriastradh
199001e04c3fSmrg   assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
1991af69d88dSmrg
1992af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1993af69d88dSmrg    *
1994af69d88dSmrg    *    "The command
1995af69d88dSmrg    *
1996af69d88dSmrg    *       void VertexAttribDivisor(uint index, uint divisor);
1997af69d88dSmrg    *
1998af69d88dSmrg    *     is equivalent to (assuming no errors are generated):
1999af69d88dSmrg    *
2000af69d88dSmrg    *       VertexAttribBinding(index, index);
2001af69d88dSmrg    *       VertexBindingDivisor(index, divisor);"
2002af69d88dSmrg    */
200301e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
200401e04c3fSmrg   vertex_binding_divisor(ctx, vao, genericIndex, divisor);
2005af69d88dSmrg}
2006af69d88dSmrg
2007af69d88dSmrg
200801e04c3fSmrgstatic ALWAYS_INLINE void
200901e04c3fSmrgvertex_array_vertex_buffer(struct gl_context *ctx,
201001e04c3fSmrg                           struct gl_vertex_array_object *vao,
201101e04c3fSmrg                           GLuint bindingIndex, GLuint buffer, GLintptr offset,
201201e04c3fSmrg                           GLsizei stride, bool no_error, const char *func)
2013af69d88dSmrg{
2014af69d88dSmrg   struct gl_buffer_object *vbo;
201501e04c3fSmrg   if (buffer ==
201601e04c3fSmrg       vao->BufferBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) {
201701e04c3fSmrg      vbo = vao->BufferBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj;
201801e04c3fSmrg   } else if (buffer != 0) {
201901e04c3fSmrg      vbo = _mesa_lookup_bufferobj(ctx, buffer);
2020af69d88dSmrg
202101e04c3fSmrg      if (!no_error && !vbo && _mesa_is_gles31(ctx)) {
202201e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", func);
202301e04c3fSmrg         return;
202401e04c3fSmrg      }
202501e04c3fSmrg      /* From the GL_ARB_vertex_attrib_array spec:
202601e04c3fSmrg       *
202701e04c3fSmrg       *   "[Core profile only:]
202801e04c3fSmrg       *    An INVALID_OPERATION error is generated if buffer is not zero or a
202901e04c3fSmrg       *    name returned from a previous call to GenBuffers, or if such a name
203001e04c3fSmrg       *    has since been deleted with DeleteBuffers.
203101e04c3fSmrg       *
203201e04c3fSmrg       * Otherwise, we fall back to the same compat profile behavior as other
203301e04c3fSmrg       * object references (automatically gen it).
203401e04c3fSmrg       */
203501e04c3fSmrg      if (!_mesa_handle_bind_buffer_gen(ctx, buffer, &vbo, func))
203601e04c3fSmrg         return;
203701e04c3fSmrg   } else {
203801e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
203901e04c3fSmrg       *
204001e04c3fSmrg       *    "If <buffer> is zero, any buffer object attached to this
204101e04c3fSmrg       *     bindpoint is detached."
204201e04c3fSmrg       */
204301e04c3fSmrg      vbo = ctx->Shared->NullBufferObj;
2044af69d88dSmrg   }
2045af69d88dSmrg
204601e04c3fSmrg   _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex),
204701e04c3fSmrg                            vbo, offset, stride);
204801e04c3fSmrg}
204901e04c3fSmrg
205001e04c3fSmrg
205101e04c3fSmrg/**
205201e04c3fSmrg * GL_ARB_vertex_attrib_binding
205301e04c3fSmrg */
205401e04c3fSmrgstatic void
205501e04c3fSmrgvertex_array_vertex_buffer_err(struct gl_context *ctx,
205601e04c3fSmrg                               struct gl_vertex_array_object *vao,
205701e04c3fSmrg                               GLuint bindingIndex, GLuint buffer,
205801e04c3fSmrg                               GLintptr offset, GLsizei stride,
205901e04c3fSmrg                               const char *func)
206001e04c3fSmrg{
206101e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
206201e04c3fSmrg
2063af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2064af69d88dSmrg    *
2065af69d88dSmrg    *    "An INVALID_VALUE error is generated if <bindingindex> is greater than
2066af69d88dSmrg    *     the value of MAX_VERTEX_ATTRIB_BINDINGS."
2067af69d88dSmrg    */
2068af69d88dSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
2069af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
207001e04c3fSmrg                  "%s(bindingindex=%u > "
2071af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
207201e04c3fSmrg                  func, bindingIndex);
2073af69d88dSmrg      return;
2074af69d88dSmrg   }
2075af69d88dSmrg
2076af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2077af69d88dSmrg    *
2078af69d88dSmrg    *    "The error INVALID_VALUE is generated if <stride> or <offset>
2079af69d88dSmrg    *     are negative."
2080af69d88dSmrg    */
2081af69d88dSmrg   if (offset < 0) {
2082af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
208301e04c3fSmrg                  "%s(offset=%" PRId64 " < 0)",
208401e04c3fSmrg                  func, (int64_t) offset);
2085af69d88dSmrg      return;
2086af69d88dSmrg   }
2087af69d88dSmrg
2088af69d88dSmrg   if (stride < 0) {
2089af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
209001e04c3fSmrg                  "%s(stride=%d < 0)", func, stride);
2091af69d88dSmrg      return;
2092af69d88dSmrg   }
2093af69d88dSmrg
209401e04c3fSmrg   if (((_mesa_is_desktop_gl(ctx) && ctx->Version >= 44) || _mesa_is_gles31(ctx)) &&
209501e04c3fSmrg       stride > ctx->Const.MaxVertexAttribStride) {
209601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
209701e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
209801e04c3fSmrg      return;
2099af69d88dSmrg   }
2100af69d88dSmrg
210101e04c3fSmrg   vertex_array_vertex_buffer(ctx, vao, bindingIndex, buffer, offset,
210201e04c3fSmrg                              stride, false, func);
2103af69d88dSmrg}
2104af69d88dSmrg
2105af69d88dSmrg
2106af69d88dSmrgvoid GLAPIENTRY
210701e04c3fSmrg_mesa_BindVertexBuffer_no_error(GLuint bindingIndex, GLuint buffer,
210801e04c3fSmrg                                GLintptr offset, GLsizei stride)
2109af69d88dSmrg{
2110af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
211101e04c3fSmrg   vertex_array_vertex_buffer(ctx, ctx->Array.VAO, bindingIndex,
211201e04c3fSmrg                              buffer, offset, stride, true,
211301e04c3fSmrg                              "glBindVertexBuffer");
211401e04c3fSmrg}
2115af69d88dSmrg
211601e04c3fSmrg
211701e04c3fSmrgvoid GLAPIENTRY
211801e04c3fSmrg_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
211901e04c3fSmrg                       GLsizei stride)
212001e04c3fSmrg{
212101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
2122af69d88dSmrg
2123af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2124af69d88dSmrg    *
212501e04c3fSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
212601e04c3fSmrg    *     is bound."
2127af69d88dSmrg    */
212801e04c3fSmrg   if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
2129af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
2130af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
213101e04c3fSmrg                  "glBindVertexBuffer(No array object bound)");
2132af69d88dSmrg      return;
2133af69d88dSmrg   }
2134af69d88dSmrg
213501e04c3fSmrg   vertex_array_vertex_buffer_err(ctx, ctx->Array.VAO, bindingIndex,
213601e04c3fSmrg                                  buffer, offset, stride,
213701e04c3fSmrg                                  "glBindVertexBuffer");
213801e04c3fSmrg}
213901e04c3fSmrg
214001e04c3fSmrg
214101e04c3fSmrgvoid GLAPIENTRY
214201e04c3fSmrg_mesa_VertexArrayVertexBuffer_no_error(GLuint vaobj, GLuint bindingIndex,
214301e04c3fSmrg                                       GLuint buffer, GLintptr offset,
214401e04c3fSmrg                                       GLsizei stride)
214501e04c3fSmrg{
214601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
214701e04c3fSmrg
214801e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
214901e04c3fSmrg   vertex_array_vertex_buffer(ctx, vao, bindingIndex, buffer, offset,
215001e04c3fSmrg                              stride, true, "glVertexArrayVertexBuffer");
215101e04c3fSmrg}
215201e04c3fSmrg
215301e04c3fSmrg
215401e04c3fSmrgvoid GLAPIENTRY
215501e04c3fSmrg_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer,
215601e04c3fSmrg                              GLintptr offset, GLsizei stride)
215701e04c3fSmrg{
215801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
215901e04c3fSmrg   struct gl_vertex_array_object *vao;
216001e04c3fSmrg
216101e04c3fSmrg   /* The ARB_direct_state_access specification says:
2162af69d88dSmrg    *
216301e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
216401e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
216501e04c3fSmrg    *    existing vertex array object."
2166af69d88dSmrg    */
216701e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffer");
216801e04c3fSmrg   if (!vao)
2169af69d88dSmrg      return;
217001e04c3fSmrg
217101e04c3fSmrg   vertex_array_vertex_buffer_err(ctx, vao, bindingIndex, buffer, offset,
217201e04c3fSmrg                                  stride, "glVertexArrayVertexBuffer");
217301e04c3fSmrg}
217401e04c3fSmrg
217501e04c3fSmrg
217601e04c3fSmrgstatic ALWAYS_INLINE void
217701e04c3fSmrgvertex_array_vertex_buffers(struct gl_context *ctx,
217801e04c3fSmrg                            struct gl_vertex_array_object *vao,
217901e04c3fSmrg                            GLuint first, GLsizei count, const GLuint *buffers,
218001e04c3fSmrg                            const GLintptr *offsets, const GLsizei *strides,
218101e04c3fSmrg                            bool no_error, const char *func)
218201e04c3fSmrg{
218301e04c3fSmrg   GLint i;
2184af69d88dSmrg
2185af69d88dSmrg   if (!buffers) {
2186af69d88dSmrg      /**
2187af69d88dSmrg       * The ARB_multi_bind spec says:
2188af69d88dSmrg       *
2189af69d88dSmrg       *    "If <buffers> is NULL, each affected vertex buffer binding point
2190af69d88dSmrg       *     from <first> through <first>+<count>-1 will be reset to have no
2191af69d88dSmrg       *     bound buffer object.  In this case, the offsets and strides
2192af69d88dSmrg       *     associated with the binding points are set to default values,
2193af69d88dSmrg       *     ignoring <offsets> and <strides>."
2194af69d88dSmrg       */
2195af69d88dSmrg      struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj;
2196af69d88dSmrg
2197af69d88dSmrg      for (i = 0; i < count; i++)
219801e04c3fSmrg         _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
219901e04c3fSmrg                                  vbo, 0, 16);
2200af69d88dSmrg
2201af69d88dSmrg      return;
2202af69d88dSmrg   }
2203af69d88dSmrg
2204af69d88dSmrg   /* Note that the error semantics for multi-bind commands differ from
2205af69d88dSmrg    * those of other GL commands.
2206af69d88dSmrg    *
2207af69d88dSmrg    * The Issues section in the ARB_multi_bind spec says:
2208af69d88dSmrg    *
2209af69d88dSmrg    *    "(11) Typically, OpenGL specifies that if an error is generated by
2210af69d88dSmrg    *          a command, that command has no effect.  This is somewhat
2211af69d88dSmrg    *          unfortunate for multi-bind commands, because it would require
2212af69d88dSmrg    *          a first pass to scan the entire list of bound objects for
2213af69d88dSmrg    *          errors and then a second pass to actually perform the
2214af69d88dSmrg    *          bindings.  Should we have different error semantics?
2215af69d88dSmrg    *
2216af69d88dSmrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
2217af69d88dSmrg    *       one of the <count> binding points are invalid, that binding
2218af69d88dSmrg    *       point is not updated and an error will be generated.  However,
2219af69d88dSmrg    *       other binding points in the same command will be updated if
2220af69d88dSmrg    *       their parameters are valid and no other error occurs."
2221af69d88dSmrg    */
2222af69d88dSmrg
222301e04c3fSmrg   _mesa_HashLockMutex(ctx->Shared->BufferObjects);
2224af69d88dSmrg
2225af69d88dSmrg   for (i = 0; i < count; i++) {
2226af69d88dSmrg      struct gl_buffer_object *vbo;
2227af69d88dSmrg
222801e04c3fSmrg      if (!no_error) {
222901e04c3fSmrg         /* The ARB_multi_bind spec says:
223001e04c3fSmrg          *
223101e04c3fSmrg          *    "An INVALID_VALUE error is generated if any value in
223201e04c3fSmrg          *     <offsets> or <strides> is negative (per binding)."
223301e04c3fSmrg          */
223401e04c3fSmrg         if (offsets[i] < 0) {
223501e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
223601e04c3fSmrg                        "%s(offsets[%u]=%" PRId64 " < 0)",
223701e04c3fSmrg                        func, i, (int64_t) offsets[i]);
223801e04c3fSmrg            continue;
223901e04c3fSmrg         }
2240af69d88dSmrg
224101e04c3fSmrg         if (strides[i] < 0) {
224201e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
224301e04c3fSmrg                        "%s(strides[%u]=%d < 0)",
224401e04c3fSmrg                        func, i, strides[i]);
224501e04c3fSmrg            continue;
224601e04c3fSmrg         }
224701e04c3fSmrg
224801e04c3fSmrg         if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 &&
224901e04c3fSmrg             strides[i] > ctx->Const.MaxVertexAttribStride) {
225001e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
225101e04c3fSmrg                        "%s(strides[%u]=%d > "
225201e04c3fSmrg                        "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, i, strides[i]);
225301e04c3fSmrg            continue;
225401e04c3fSmrg         }
2255af69d88dSmrg      }
2256af69d88dSmrg
2257af69d88dSmrg      if (buffers[i]) {
2258af69d88dSmrg         struct gl_vertex_buffer_binding *binding =
225901e04c3fSmrg            &vao->BufferBinding[VERT_ATTRIB_GENERIC(first + i)];
2260af69d88dSmrg
2261af69d88dSmrg         if (buffers[i] == binding->BufferObj->Name)
2262af69d88dSmrg            vbo = binding->BufferObj;
2263af69d88dSmrg         else
226401e04c3fSmrg            vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, func);
2265af69d88dSmrg
2266af69d88dSmrg         if (!vbo)
2267af69d88dSmrg            continue;
2268af69d88dSmrg      } else {
2269af69d88dSmrg         vbo = ctx->Shared->NullBufferObj;
2270af69d88dSmrg      }
2271af69d88dSmrg
227201e04c3fSmrg      _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
227301e04c3fSmrg                               vbo, offsets[i], strides[i]);
2274af69d88dSmrg   }
2275af69d88dSmrg
227601e04c3fSmrg   _mesa_HashUnlockMutex(ctx->Shared->BufferObjects);
2277af69d88dSmrg}
2278af69d88dSmrg
2279af69d88dSmrg
228001e04c3fSmrgstatic void
228101e04c3fSmrgvertex_array_vertex_buffers_err(struct gl_context *ctx,
228201e04c3fSmrg                                struct gl_vertex_array_object *vao,
228301e04c3fSmrg                                GLuint first, GLsizei count,
228401e04c3fSmrg                                const GLuint *buffers, const GLintptr *offsets,
228501e04c3fSmrg                                const GLsizei *strides, const char *func)
2286af69d88dSmrg{
2287af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
2288af69d88dSmrg
228901e04c3fSmrg   /* The ARB_multi_bind spec says:
2290af69d88dSmrg    *
229101e04c3fSmrg    *    "An INVALID_OPERATION error is generated if <first> + <count>
229201e04c3fSmrg    *     is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS."
2293af69d88dSmrg    */
229401e04c3fSmrg   if (first + count > ctx->Const.MaxVertexAttribBindings) {
2295af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
229601e04c3fSmrg                  "%s(first=%u + count=%d > the value of "
229701e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)",
229801e04c3fSmrg                  func, first, count, ctx->Const.MaxVertexAttribBindings);
2299af69d88dSmrg      return;
2300af69d88dSmrg   }
2301af69d88dSmrg
230201e04c3fSmrg   vertex_array_vertex_buffers(ctx, vao, first, count, buffers, offsets,
230301e04c3fSmrg                               strides, false, func);
230401e04c3fSmrg}
230501e04c3fSmrg
2306af69d88dSmrg
230701e04c3fSmrgvoid GLAPIENTRY
230801e04c3fSmrg_mesa_BindVertexBuffers_no_error(GLuint first, GLsizei count,
230901e04c3fSmrg                                 const GLuint *buffers, const GLintptr *offsets,
231001e04c3fSmrg                                 const GLsizei *strides)
231101e04c3fSmrg{
231201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
2313af69d88dSmrg
231401e04c3fSmrg   vertex_array_vertex_buffers(ctx, ctx->Array.VAO, first, count,
231501e04c3fSmrg                               buffers, offsets, strides, true,
231601e04c3fSmrg                               "glBindVertexBuffers");
2317af69d88dSmrg}
2318af69d88dSmrg
2319af69d88dSmrg
2320af69d88dSmrgvoid GLAPIENTRY
232101e04c3fSmrg_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
232201e04c3fSmrg                        const GLintptr *offsets, const GLsizei *strides)
2323af69d88dSmrg{
2324af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
2325af69d88dSmrg
2326af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2327af69d88dSmrg    *
232801e04c3fSmrg    *    "An INVALID_OPERATION error is generated if no
232901e04c3fSmrg    *     vertex array object is bound."
2330af69d88dSmrg    */
2331af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
2332af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
2333af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
233401e04c3fSmrg                  "glBindVertexBuffers(No array object bound)");
2335af69d88dSmrg      return;
2336af69d88dSmrg   }
2337af69d88dSmrg
233801e04c3fSmrg   vertex_array_vertex_buffers_err(ctx, ctx->Array.VAO, first, count,
233901e04c3fSmrg                                   buffers, offsets, strides,
234001e04c3fSmrg                                   "glBindVertexBuffers");
234101e04c3fSmrg}
234201e04c3fSmrg
234301e04c3fSmrg
234401e04c3fSmrgvoid GLAPIENTRY
234501e04c3fSmrg_mesa_VertexArrayVertexBuffers_no_error(GLuint vaobj, GLuint first,
234601e04c3fSmrg                                        GLsizei count, const GLuint *buffers,
234701e04c3fSmrg                                        const GLintptr *offsets,
234801e04c3fSmrg                                        const GLsizei *strides)
234901e04c3fSmrg{
235001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
235101e04c3fSmrg
235201e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
235301e04c3fSmrg   vertex_array_vertex_buffers(ctx, vao, first, count,
235401e04c3fSmrg                               buffers, offsets, strides, true,
235501e04c3fSmrg                               "glVertexArrayVertexBuffers");
235601e04c3fSmrg}
235701e04c3fSmrg
235801e04c3fSmrg
235901e04c3fSmrgvoid GLAPIENTRY
236001e04c3fSmrg_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count,
236101e04c3fSmrg                               const GLuint *buffers,
236201e04c3fSmrg                               const GLintptr *offsets, const GLsizei *strides)
236301e04c3fSmrg{
236401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
236501e04c3fSmrg   struct gl_vertex_array_object *vao;
236601e04c3fSmrg
236701e04c3fSmrg   /* The ARB_direct_state_access specification says:
2368af69d88dSmrg    *
236901e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
237001e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
237101e04c3fSmrg    *    existing vertex array object."
2372af69d88dSmrg    */
237301e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayVertexBuffers");
237401e04c3fSmrg   if (!vao)
2375af69d88dSmrg      return;
237601e04c3fSmrg
237701e04c3fSmrg   vertex_array_vertex_buffers_err(ctx, vao, first, count,
237801e04c3fSmrg                                   buffers, offsets, strides,
237901e04c3fSmrg                                   "glVertexArrayVertexBuffers");
238001e04c3fSmrg}
238101e04c3fSmrg
238201e04c3fSmrg
238301e04c3fSmrgstatic void
238401e04c3fSmrgvertex_attrib_format(GLuint attribIndex, GLint size, GLenum type,
238501e04c3fSmrg                     GLboolean normalized, GLboolean integer,
238601e04c3fSmrg                     GLboolean doubles, GLbitfield legalTypes,
238701e04c3fSmrg                     GLsizei sizeMax, GLuint relativeOffset,
238801e04c3fSmrg                     const char *func)
238901e04c3fSmrg{
239001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
239101e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
239201e04c3fSmrg
239301e04c3fSmrg   GLenum format = get_array_format(ctx, sizeMax, &size);
239401e04c3fSmrg
239501e04c3fSmrg   if (!_mesa_is_no_error_enabled(ctx)) {
239601e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
239701e04c3fSmrg       *
239801e04c3fSmrg       *    "An INVALID_OPERATION error is generated under any of the
239901e04c3fSmrg       *    following conditions:
240001e04c3fSmrg       *     - if no vertex array object is currently bound (see section
240101e04c3fSmrg       *       2.10);
240201e04c3fSmrg       *     - ..."
240301e04c3fSmrg       *
240401e04c3fSmrg       * This error condition only applies to VertexAttribFormat and
240501e04c3fSmrg       * VertexAttribIFormat in the extension spec, but we assume that this
240601e04c3fSmrg       * is an oversight.  In the OpenGL 4.3 (Core Profile) spec, it applies
240701e04c3fSmrg       * to all three functions.
240801e04c3fSmrg       */
240901e04c3fSmrg      if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
241001e04c3fSmrg          ctx->Array.VAO == ctx->Array.DefaultVAO) {
241101e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
241201e04c3fSmrg                     "%s(No array object bound)", func);
241301e04c3fSmrg         return;
241401e04c3fSmrg      }
241501e04c3fSmrg
241601e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
241701e04c3fSmrg       *
241801e04c3fSmrg       *   "The error INVALID_VALUE is generated if index is greater than or
241901e04c3fSmrg       *   equal to the value of MAX_VERTEX_ATTRIBS."
242001e04c3fSmrg       */
242101e04c3fSmrg      if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
242201e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
242301e04c3fSmrg                     "%s(attribindex=%u > "
242401e04c3fSmrg                     "GL_MAX_VERTEX_ATTRIBS)",
242501e04c3fSmrg                     func, attribIndex);
242601e04c3fSmrg         return;
242701e04c3fSmrg      }
242801e04c3fSmrg
242901e04c3fSmrg      if (!validate_array_format(ctx, func, ctx->Array.VAO,
243001e04c3fSmrg                                 VERT_ATTRIB_GENERIC(attribIndex),
243101e04c3fSmrg                                 legalTypes, 1, sizeMax, size, type,
243201e04c3fSmrg                                 normalized, integer, doubles, relativeOffset,
243301e04c3fSmrg                                 format)) {
243401e04c3fSmrg         return;
243501e04c3fSmrg      }
2436af69d88dSmrg   }
2437af69d88dSmrg
243801e04c3fSmrg   _mesa_update_array_format(ctx, ctx->Array.VAO,
243901e04c3fSmrg                             VERT_ATTRIB_GENERIC(attribIndex), size, type,
244001e04c3fSmrg                             format, normalized, integer, doubles,
244101e04c3fSmrg                             relativeOffset);
244201e04c3fSmrg}
244301e04c3fSmrg
244401e04c3fSmrg
244501e04c3fSmrgvoid GLAPIENTRY
244601e04c3fSmrg_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
244701e04c3fSmrg                         GLboolean normalized, GLuint relativeOffset)
244801e04c3fSmrg{
244901e04c3fSmrg   vertex_attrib_format(attribIndex, size, type, normalized,
245001e04c3fSmrg                        GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
245101e04c3fSmrg                        BGRA_OR_4, relativeOffset,
245201e04c3fSmrg                        "glVertexAttribFormat");
245301e04c3fSmrg}
245401e04c3fSmrg
2455af69d88dSmrg
245601e04c3fSmrgvoid GLAPIENTRY
245701e04c3fSmrg_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
245801e04c3fSmrg                          GLuint relativeOffset)
245901e04c3fSmrg{
246001e04c3fSmrg   vertex_attrib_format(attribIndex, size, type, GL_FALSE,
246101e04c3fSmrg                        GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 4,
246201e04c3fSmrg                        relativeOffset, "glVertexAttribIFormat");
2463af69d88dSmrg}
2464af69d88dSmrg
2465af69d88dSmrg
2466af69d88dSmrgvoid GLAPIENTRY
2467af69d88dSmrg_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
2468af69d88dSmrg                          GLuint relativeOffset)
2469af69d88dSmrg{
247001e04c3fSmrg   vertex_attrib_format(attribIndex, size, type, GL_FALSE, GL_FALSE,
247101e04c3fSmrg                        GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 4,
247201e04c3fSmrg                        relativeOffset, "glVertexAttribLFormat");
247301e04c3fSmrg}
247401e04c3fSmrg
2475af69d88dSmrg
247601e04c3fSmrgstatic void
247701e04c3fSmrgvertex_array_attrib_format(GLuint vaobj, GLuint attribIndex, GLint size,
247801e04c3fSmrg                           GLenum type, GLboolean normalized,
247901e04c3fSmrg                           GLboolean integer, GLboolean doubles,
248001e04c3fSmrg                           GLbitfield legalTypes, GLsizei sizeMax,
248101e04c3fSmrg                           GLuint relativeOffset, const char *func)
248201e04c3fSmrg{
2483af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
248401e04c3fSmrg   struct gl_vertex_array_object *vao;
248501e04c3fSmrg
2486af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
2487af69d88dSmrg
248801e04c3fSmrg   GLenum format = get_array_format(ctx, sizeMax, &size);
248901e04c3fSmrg
249001e04c3fSmrg   if (_mesa_is_no_error_enabled(ctx)) {
249101e04c3fSmrg      vao = _mesa_lookup_vao(ctx, vaobj);
249201e04c3fSmrg      if (!vao)
249301e04c3fSmrg         return;
249401e04c3fSmrg   } else {
249501e04c3fSmrg      /* The ARB_direct_state_access spec says:
249601e04c3fSmrg       *
249701e04c3fSmrg       *   "An INVALID_OPERATION error is generated by
249801e04c3fSmrg       *   VertexArrayAttrib*Format if <vaobj> is not [compatibility profile:
249901e04c3fSmrg       *   zero or] the name of an existing vertex array object."
250001e04c3fSmrg       */
250101e04c3fSmrg      vao = _mesa_lookup_vao_err(ctx, vaobj, func);
250201e04c3fSmrg      if (!vao)
250301e04c3fSmrg         return;
250401e04c3fSmrg
250501e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
250601e04c3fSmrg       *
250701e04c3fSmrg       *   "The error INVALID_VALUE is generated if index is greater than or
250801e04c3fSmrg       *   equal to the value of MAX_VERTEX_ATTRIBS."
250901e04c3fSmrg       */
251001e04c3fSmrg      if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
251101e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
251201e04c3fSmrg                     "%s(attribindex=%u > GL_MAX_VERTEX_ATTRIBS)",
251301e04c3fSmrg                     func, attribIndex);
251401e04c3fSmrg         return;
251501e04c3fSmrg      }
251601e04c3fSmrg
251701e04c3fSmrg      if (!validate_array_format(ctx, func, vao,
251801e04c3fSmrg                                 VERT_ATTRIB_GENERIC(attribIndex),
251901e04c3fSmrg                                 legalTypes, 1, sizeMax, size, type,
252001e04c3fSmrg                                 normalized, integer, doubles, relativeOffset,
252101e04c3fSmrg                                 format)) {
252201e04c3fSmrg         return;
252301e04c3fSmrg      }
2524af69d88dSmrg   }
2525af69d88dSmrg
252601e04c3fSmrg   _mesa_update_array_format(ctx, vao, VERT_ATTRIB_GENERIC(attribIndex), size,
252701e04c3fSmrg                             type, format, normalized, integer, doubles,
252801e04c3fSmrg                             relativeOffset);
252901e04c3fSmrg}
253001e04c3fSmrg
253101e04c3fSmrg
253201e04c3fSmrgvoid GLAPIENTRY
253301e04c3fSmrg_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size,
253401e04c3fSmrg                              GLenum type, GLboolean normalized,
253501e04c3fSmrg                              GLuint relativeOffset)
253601e04c3fSmrg{
253701e04c3fSmrg   vertex_array_attrib_format(vaobj, attribIndex, size, type, normalized,
253801e04c3fSmrg                              GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
253901e04c3fSmrg                              BGRA_OR_4, relativeOffset,
254001e04c3fSmrg                              "glVertexArrayAttribFormat");
254101e04c3fSmrg}
254201e04c3fSmrg
254301e04c3fSmrg
254401e04c3fSmrgvoid GLAPIENTRY
254501e04c3fSmrg_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex,
254601e04c3fSmrg                               GLint size, GLenum type,
254701e04c3fSmrg                               GLuint relativeOffset)
254801e04c3fSmrg{
254901e04c3fSmrg   vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE,
255001e04c3fSmrg                              GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK,
255101e04c3fSmrg                              4, relativeOffset,
255201e04c3fSmrg                              "glVertexArrayAttribIFormat");
255301e04c3fSmrg}
255401e04c3fSmrg
255501e04c3fSmrg
255601e04c3fSmrgvoid GLAPIENTRY
255701e04c3fSmrg_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex,
255801e04c3fSmrg                               GLint size, GLenum type,
255901e04c3fSmrg                               GLuint relativeOffset)
256001e04c3fSmrg{
256101e04c3fSmrg   vertex_array_attrib_format(vaobj, attribIndex, size, type, GL_FALSE,
256201e04c3fSmrg                              GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK,
256301e04c3fSmrg                              4, relativeOffset,
256401e04c3fSmrg                              "glVertexArrayAttribLFormat");
256501e04c3fSmrg}
256601e04c3fSmrg
256701e04c3fSmrg
256801e04c3fSmrgstatic void
256901e04c3fSmrgvertex_array_attrib_binding(struct gl_context *ctx,
257001e04c3fSmrg                            struct gl_vertex_array_object *vao,
257101e04c3fSmrg                            GLuint attribIndex, GLuint bindingIndex,
257201e04c3fSmrg                            const char *func)
257301e04c3fSmrg{
257401e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
257501e04c3fSmrg
2576af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2577af69d88dSmrg    *
257801e04c3fSmrg    *    "<attribindex> must be less than the value of MAX_VERTEX_ATTRIBS and
257901e04c3fSmrg    *     <bindingindex> must be less than the value of
258001e04c3fSmrg    *     MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE
258101e04c3fSmrg    *     is generated."
2582af69d88dSmrg    */
2583af69d88dSmrg   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
2584af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
258501e04c3fSmrg                  "%s(attribindex=%u >= "
2586af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIBS)",
258701e04c3fSmrg                  func, attribIndex);
258801e04c3fSmrg      return;
258901e04c3fSmrg   }
259001e04c3fSmrg
259101e04c3fSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
259201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
259301e04c3fSmrg                  "%s(bindingindex=%u >= "
259401e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
259501e04c3fSmrg                  func, bindingIndex);
2596af69d88dSmrg      return;
2597af69d88dSmrg   }
2598af69d88dSmrg
259901e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(attribIndex) < ARRAY_SIZE(vao->VertexAttrib));
260001e04c3fSmrg
260101e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao,
260201e04c3fSmrg                               VERT_ATTRIB_GENERIC(attribIndex),
260301e04c3fSmrg                               VERT_ATTRIB_GENERIC(bindingIndex));
260401e04c3fSmrg}
260501e04c3fSmrg
2606af69d88dSmrg
260701e04c3fSmrgvoid GLAPIENTRY
260801e04c3fSmrg_mesa_VertexAttribBinding_no_error(GLuint attribIndex, GLuint bindingIndex)
260901e04c3fSmrg{
261001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
261101e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, ctx->Array.VAO,
261201e04c3fSmrg                               VERT_ATTRIB_GENERIC(attribIndex),
261301e04c3fSmrg                               VERT_ATTRIB_GENERIC(bindingIndex));
2614af69d88dSmrg}
2615af69d88dSmrg
2616af69d88dSmrg
2617af69d88dSmrgvoid GLAPIENTRY
2618af69d88dSmrg_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
2619af69d88dSmrg{
2620af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
2621af69d88dSmrg
2622af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2623af69d88dSmrg    *
2624af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
2625af69d88dSmrg    *     is bound."
2626af69d88dSmrg    */
262701e04c3fSmrg   if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
2628af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
2629af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2630af69d88dSmrg                  "glVertexAttribBinding(No array object bound)");
2631af69d88dSmrg      return;
2632af69d88dSmrg   }
2633af69d88dSmrg
263401e04c3fSmrg   vertex_array_attrib_binding(ctx, ctx->Array.VAO,
263501e04c3fSmrg                               attribIndex, bindingIndex,
263601e04c3fSmrg                               "glVertexAttribBinding");
263701e04c3fSmrg}
263801e04c3fSmrg
263901e04c3fSmrg
264001e04c3fSmrgvoid GLAPIENTRY
264101e04c3fSmrg_mesa_VertexArrayAttribBinding_no_error(GLuint vaobj, GLuint attribIndex,
264201e04c3fSmrg                                        GLuint bindingIndex)
264301e04c3fSmrg{
264401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
264501e04c3fSmrg
264601e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
264701e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao,
264801e04c3fSmrg                               VERT_ATTRIB_GENERIC(attribIndex),
264901e04c3fSmrg                               VERT_ATTRIB_GENERIC(bindingIndex));
265001e04c3fSmrg}
265101e04c3fSmrg
265201e04c3fSmrg
265301e04c3fSmrgvoid GLAPIENTRY
265401e04c3fSmrg_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex)
265501e04c3fSmrg{
265601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
265701e04c3fSmrg   struct gl_vertex_array_object *vao;
265801e04c3fSmrg
265901e04c3fSmrg   /* The ARB_direct_state_access specification says:
2660af69d88dSmrg    *
266101e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayAttribBinding
266201e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
266301e04c3fSmrg    *    existing vertex array object."
2664af69d88dSmrg    */
266501e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayAttribBinding");
266601e04c3fSmrg   if (!vao)
266701e04c3fSmrg      return;
266801e04c3fSmrg
266901e04c3fSmrg   vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex,
267001e04c3fSmrg                               "glVertexArrayAttribBinding");
267101e04c3fSmrg}
267201e04c3fSmrg
267301e04c3fSmrg
267401e04c3fSmrgstatic void
267501e04c3fSmrgvertex_array_binding_divisor(struct gl_context *ctx,
267601e04c3fSmrg                             struct gl_vertex_array_object *vao,
267701e04c3fSmrg                             GLuint bindingIndex, GLuint divisor,
267801e04c3fSmrg                             const char *func)
267901e04c3fSmrg{
268001e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
268101e04c3fSmrg
268201e04c3fSmrg   if (!ctx->Extensions.ARB_instanced_arrays) {
268301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", func);
2684af69d88dSmrg      return;
2685af69d88dSmrg   }
2686af69d88dSmrg
268701e04c3fSmrg   /* The ARB_vertex_attrib_binding spec says:
268801e04c3fSmrg    *
268901e04c3fSmrg    *    "An INVALID_VALUE error is generated if <bindingindex> is greater
269001e04c3fSmrg    *     than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS."
269101e04c3fSmrg    */
2692af69d88dSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
2693af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
269401e04c3fSmrg                  "%s(bindingindex=%u > "
2695af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
269601e04c3fSmrg                  func, bindingIndex);
2697af69d88dSmrg      return;
2698af69d88dSmrg   }
2699af69d88dSmrg
270001e04c3fSmrg   vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
270101e04c3fSmrg}
270201e04c3fSmrg
2703af69d88dSmrg
270401e04c3fSmrgvoid GLAPIENTRY
270501e04c3fSmrg_mesa_VertexBindingDivisor_no_error(GLuint bindingIndex, GLuint divisor)
270601e04c3fSmrg{
270701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
270801e04c3fSmrg   vertex_binding_divisor(ctx, ctx->Array.VAO,
270901e04c3fSmrg                          VERT_ATTRIB_GENERIC(bindingIndex), divisor);
2710af69d88dSmrg}
2711af69d88dSmrg
2712af69d88dSmrg
2713af69d88dSmrgvoid GLAPIENTRY
2714af69d88dSmrg_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
2715af69d88dSmrg{
2716af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
2717af69d88dSmrg
2718af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2719af69d88dSmrg    *
2720af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
2721af69d88dSmrg    *     is bound."
2722af69d88dSmrg    */
272301e04c3fSmrg   if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
2724af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
2725af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
2726af69d88dSmrg                  "glVertexBindingDivisor(No array object bound)");
2727af69d88dSmrg      return;
2728af69d88dSmrg   }
2729af69d88dSmrg
273001e04c3fSmrg   vertex_array_binding_divisor(ctx, ctx->Array.VAO,
273101e04c3fSmrg                                bindingIndex, divisor,
273201e04c3fSmrg                                "glVertexBindingDivisor");
273301e04c3fSmrg}
273401e04c3fSmrg
273501e04c3fSmrg
273601e04c3fSmrgvoid GLAPIENTRY
273701e04c3fSmrg_mesa_VertexArrayBindingDivisor_no_error(GLuint vaobj, GLuint bindingIndex,
273801e04c3fSmrg                                         GLuint divisor)
273901e04c3fSmrg{
274001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
2741af69d88dSmrg
274201e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
274301e04c3fSmrg   vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
2744af69d88dSmrg}
2745af69d88dSmrg
27463464ebd5Sriastradh
274701e04c3fSmrgvoid GLAPIENTRY
274801e04c3fSmrg_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex,
274901e04c3fSmrg                                GLuint divisor)
275001e04c3fSmrg{
275101e04c3fSmrg   struct gl_vertex_array_object *vao;
275201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
275301e04c3fSmrg
275401e04c3fSmrg   /* The ARB_direct_state_access specification says:
275501e04c3fSmrg    *
275601e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor
275701e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
275801e04c3fSmrg    *    existing vertex array object."
275901e04c3fSmrg    */
276001e04c3fSmrg   vao = _mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayBindingDivisor");
276101e04c3fSmrg   if (!vao)
276201e04c3fSmrg       return;
276301e04c3fSmrg
276401e04c3fSmrg   vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor,
276501e04c3fSmrg                                "glVertexArrayBindingDivisor");
27664a49301eSmrg}
27674a49301eSmrg
276801e04c3fSmrg
2769af69d88dSmrgvoid
2770af69d88dSmrg_mesa_copy_vertex_attrib_array(struct gl_context *ctx,
277101e04c3fSmrg                               struct gl_array_attributes *dst,
277201e04c3fSmrg                               const struct gl_array_attributes *src)
2773af69d88dSmrg{
2774af69d88dSmrg   dst->Size           = src->Size;
2775af69d88dSmrg   dst->Type           = src->Type;
2776af69d88dSmrg   dst->Format         = src->Format;
277701e04c3fSmrg   dst->BufferBindingIndex = src->BufferBindingIndex;
2778af69d88dSmrg   dst->RelativeOffset = src->RelativeOffset;
2779af69d88dSmrg   dst->Format         = src->Format;
2780af69d88dSmrg   dst->Integer        = src->Integer;
278101e04c3fSmrg   dst->Doubles        = src->Doubles;
2782af69d88dSmrg   dst->Normalized     = src->Normalized;
2783af69d88dSmrg   dst->Ptr            = src->Ptr;
2784af69d88dSmrg   dst->Enabled        = src->Enabled;
2785af69d88dSmrg   dst->_ElementSize   = src->_ElementSize;
278601e04c3fSmrg   dst->_EffBufferBindingIndex = src->_EffBufferBindingIndex;
278701e04c3fSmrg   dst->_EffRelativeOffset = src->_EffRelativeOffset;
2788af69d88dSmrg}
2789af69d88dSmrg
2790af69d88dSmrgvoid
2791af69d88dSmrg_mesa_copy_vertex_buffer_binding(struct gl_context *ctx,
2792af69d88dSmrg                                 struct gl_vertex_buffer_binding *dst,
2793af69d88dSmrg                                 const struct gl_vertex_buffer_binding *src)
2794af69d88dSmrg{
2795af69d88dSmrg   dst->Offset          = src->Offset;
2796af69d88dSmrg   dst->Stride          = src->Stride;
2797af69d88dSmrg   dst->InstanceDivisor = src->InstanceDivisor;
2798af69d88dSmrg   dst->_BoundArrays    = src->_BoundArrays;
279901e04c3fSmrg   dst->_EffBoundArrays = src->_EffBoundArrays;
280001e04c3fSmrg   dst->_EffOffset      = src->_EffOffset;
28014a49301eSmrg
2802af69d88dSmrg   _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
2803af69d88dSmrg}
28044a49301eSmrg
28054a49301eSmrg/**
28064a49301eSmrg * Print current vertex object/array info.  For debug.
28074a49301eSmrg */
28084a49301eSmrgvoid
28093464ebd5Sriastradh_mesa_print_arrays(struct gl_context *ctx)
28104a49301eSmrg{
281101e04c3fSmrg   const struct gl_vertex_array_object *vao = ctx->Array.VAO;
28124a49301eSmrg
281301e04c3fSmrg   fprintf(stderr, "Array Object %u\n", vao->Name);
2814af69d88dSmrg
281501e04c3fSmrg   gl_vert_attrib i;
281601e04c3fSmrg   for (i = 0; i < VERT_ATTRIB_MAX; ++i) {
281701e04c3fSmrg      const struct gl_array_attributes *array = &vao->VertexAttrib[i];
281801e04c3fSmrg      if (!array->Enabled)
281901e04c3fSmrg         continue;
282001e04c3fSmrg
282101e04c3fSmrg      const struct gl_vertex_buffer_binding *binding =
282201e04c3fSmrg         &vao->BufferBinding[array->BufferBindingIndex];
282301e04c3fSmrg      const struct gl_buffer_object *bo = binding->BufferObj;
282401e04c3fSmrg
282501e04c3fSmrg      fprintf(stderr, "  %s: Ptr=%p, Type=%s, Size=%d, ElemSize=%u, "
282601e04c3fSmrg              "Stride=%d, Buffer=%u(Size %lu)\n",
282701e04c3fSmrg              gl_vert_attrib_name((gl_vert_attrib)i),
282801e04c3fSmrg              array->Ptr, _mesa_enum_to_string(array->Type), array->Size,
282901e04c3fSmrg              array->_ElementSize, binding->Stride, bo->Name,
283001e04c3fSmrg              (unsigned long) bo->Size);
283101e04c3fSmrg   }
28324a49301eSmrg}
28334a49301eSmrg
28344a49301eSmrg
28357117f1b4Smrg/**
28367117f1b4Smrg * Initialize vertex array state for given context.
28377117f1b4Smrg */
283801e04c3fSmrgvoid
28393464ebd5Sriastradh_mesa_init_varray(struct gl_context *ctx)
28407117f1b4Smrg{
284101e04c3fSmrg   ctx->Array.DefaultVAO = _mesa_new_vao(ctx, 0);
2842af69d88dSmrg   _mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO);
284301e04c3fSmrg   ctx->Array._EmptyVAO = _mesa_new_vao(ctx, ~0u);
284401e04c3fSmrg   _mesa_reference_vao(ctx, &ctx->Array._DrawVAO, ctx->Array._EmptyVAO);
28457117f1b4Smrg   ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
28464a49301eSmrg
28474a49301eSmrg   ctx->Array.Objects = _mesa_NewHashTable();
28484a49301eSmrg}
28494a49301eSmrg
28504a49301eSmrg
28514a49301eSmrg/**
28524a49301eSmrg * Callback for deleting an array object.  Called by _mesa_HashDeleteAll().
28534a49301eSmrg */
28544a49301eSmrgstatic void
28554a49301eSmrgdelete_arrayobj_cb(GLuint id, void *data, void *userData)
28564a49301eSmrg{
2857af69d88dSmrg   struct gl_vertex_array_object *vao = (struct gl_vertex_array_object *) data;
28583464ebd5Sriastradh   struct gl_context *ctx = (struct gl_context *) userData;
2859af69d88dSmrg   _mesa_delete_vao(ctx, vao);
28604a49301eSmrg}
28614a49301eSmrg
28624a49301eSmrg
28634a49301eSmrg/**
28644a49301eSmrg * Free vertex array state for given context.
28654a49301eSmrg */
286601e04c3fSmrgvoid
28673464ebd5Sriastradh_mesa_free_varray_data(struct gl_context *ctx)
28684a49301eSmrg{
28694a49301eSmrg   _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
28704a49301eSmrg   _mesa_DeleteHashTable(ctx->Array.Objects);
28717117f1b4Smrg}
2872