varray.c revision 7ec681f3
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"
317ec681f3Smrg
327117f1b4Smrg#include "bufferobj.h"
337117f1b4Smrg#include "context.h"
347117f1b4Smrg#include "enable.h"
357117f1b4Smrg#include "enums.h"
36b9abf16eSmaya#include "glformats.h"
374a49301eSmrg#include "hash.h"
383464ebd5Sriastradh#include "image.h"
393464ebd5Sriastradh#include "macros.h"
407117f1b4Smrg#include "mtypes.h"
417117f1b4Smrg#include "varray.h"
427117f1b4Smrg#include "arrayobj.h"
437ec681f3Smrg#include "get.h"
44cdc920a0Smrg#include "main/dispatch.h"
457117f1b4Smrg
467117f1b4Smrg
473464ebd5Sriastradh/** Used to do error checking for GL_EXT_vertex_array_bgra */
483464ebd5Sriastradh#define BGRA_OR_4  5
493464ebd5Sriastradh
503464ebd5Sriastradh
513464ebd5Sriastradh/** Used to indicate which GL datatypes are accepted by each of the
523464ebd5Sriastradh * glVertex/Color/Attrib/EtcPointer() functions.
533464ebd5Sriastradh */
54af69d88dSmrg#define BOOL_BIT                          (1 << 0)
55af69d88dSmrg#define BYTE_BIT                          (1 << 1)
56af69d88dSmrg#define UNSIGNED_BYTE_BIT                 (1 << 2)
57af69d88dSmrg#define SHORT_BIT                         (1 << 3)
58af69d88dSmrg#define UNSIGNED_SHORT_BIT                (1 << 4)
59af69d88dSmrg#define INT_BIT                           (1 << 5)
60af69d88dSmrg#define UNSIGNED_INT_BIT                  (1 << 6)
61af69d88dSmrg#define HALF_BIT                          (1 << 7)
62af69d88dSmrg#define FLOAT_BIT                         (1 << 8)
63af69d88dSmrg#define DOUBLE_BIT                        (1 << 9)
64af69d88dSmrg#define FIXED_ES_BIT                      (1 << 10)
65af69d88dSmrg#define FIXED_GL_BIT                      (1 << 11)
66af69d88dSmrg#define UNSIGNED_INT_2_10_10_10_REV_BIT   (1 << 12)
67af69d88dSmrg#define INT_2_10_10_10_REV_BIT            (1 << 13)
68af69d88dSmrg#define UNSIGNED_INT_10F_11F_11F_REV_BIT  (1 << 14)
69af69d88dSmrg#define ALL_TYPE_BITS                    ((1 << 15) - 1)
703464ebd5Sriastradh
7101e04c3fSmrg#define ATTRIB_FORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
7201e04c3fSmrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT | \
7301e04c3fSmrg                                  INT_BIT | UNSIGNED_INT_BIT | \
7401e04c3fSmrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT | \
7501e04c3fSmrg                                  FIXED_GL_BIT | \
7601e04c3fSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT | \
7701e04c3fSmrg                                  INT_2_10_10_10_REV_BIT | \
7801e04c3fSmrg                                  UNSIGNED_INT_10F_11F_11F_REV_BIT)
7901e04c3fSmrg
8001e04c3fSmrg#define ATTRIB_IFORMAT_TYPES_MASK (BYTE_BIT | UNSIGNED_BYTE_BIT | \
8101e04c3fSmrg                                   SHORT_BIT | UNSIGNED_SHORT_BIT | \
8201e04c3fSmrg                                   INT_BIT | UNSIGNED_INT_BIT)
8301e04c3fSmrg
8401e04c3fSmrg#define ATTRIB_LFORMAT_TYPES_MASK DOUBLE_BIT
8501e04c3fSmrg
863464ebd5Sriastradh
873464ebd5Sriastradh/** Convert GL datatype enum into a <type>_BIT value seen above */
883464ebd5Sriastradhstatic GLbitfield
893464ebd5Sriastradhtype_to_bit(const struct gl_context *ctx, GLenum type)
903464ebd5Sriastradh{
913464ebd5Sriastradh   switch (type) {
923464ebd5Sriastradh   case GL_BOOL:
933464ebd5Sriastradh      return BOOL_BIT;
943464ebd5Sriastradh   case GL_BYTE:
953464ebd5Sriastradh      return BYTE_BIT;
963464ebd5Sriastradh   case GL_UNSIGNED_BYTE:
973464ebd5Sriastradh      return UNSIGNED_BYTE_BIT;
983464ebd5Sriastradh   case GL_SHORT:
993464ebd5Sriastradh      return SHORT_BIT;
1003464ebd5Sriastradh   case GL_UNSIGNED_SHORT:
1013464ebd5Sriastradh      return UNSIGNED_SHORT_BIT;
1023464ebd5Sriastradh   case GL_INT:
1033464ebd5Sriastradh      return INT_BIT;
1043464ebd5Sriastradh   case GL_UNSIGNED_INT:
1053464ebd5Sriastradh      return UNSIGNED_INT_BIT;
1063464ebd5Sriastradh   case GL_HALF_FLOAT:
10701e04c3fSmrg   case GL_HALF_FLOAT_OES:
1083464ebd5Sriastradh      if (ctx->Extensions.ARB_half_float_vertex)
1093464ebd5Sriastradh         return HALF_BIT;
1103464ebd5Sriastradh      else
1113464ebd5Sriastradh         return 0x0;
1123464ebd5Sriastradh   case GL_FLOAT:
1133464ebd5Sriastradh      return FLOAT_BIT;
1143464ebd5Sriastradh   case GL_DOUBLE:
1153464ebd5Sriastradh      return DOUBLE_BIT;
1163464ebd5Sriastradh   case GL_FIXED:
117af69d88dSmrg      return _mesa_is_desktop_gl(ctx) ? FIXED_GL_BIT : FIXED_ES_BIT;
118af69d88dSmrg   case GL_UNSIGNED_INT_2_10_10_10_REV:
119af69d88dSmrg      return UNSIGNED_INT_2_10_10_10_REV_BIT;
120af69d88dSmrg   case GL_INT_2_10_10_10_REV:
121af69d88dSmrg      return INT_2_10_10_10_REV_BIT;
122af69d88dSmrg   case GL_UNSIGNED_INT_10F_11F_11F_REV:
123af69d88dSmrg      return UNSIGNED_INT_10F_11F_11F_REV_BIT;
1243464ebd5Sriastradh   default:
1253464ebd5Sriastradh      return 0;
1263464ebd5Sriastradh   }
1273464ebd5Sriastradh}
1283464ebd5Sriastradh
1293464ebd5Sriastradh
1307117f1b4Smrg/**
13101e04c3fSmrg * Depending on the position and generic0 attributes enable flags select
13201e04c3fSmrg * the one that is used for both attributes.
13301e04c3fSmrg * The generic0 attribute takes precedence.
1347117f1b4Smrg */
13501e04c3fSmrgstatic inline void
13601e04c3fSmrgupdate_attribute_map_mode(const struct gl_context *ctx,
13701e04c3fSmrg                          struct gl_vertex_array_object *vao)
138af69d88dSmrg{
13901e04c3fSmrg   /*
14001e04c3fSmrg    * There is no need to change the mapping away from the
14101e04c3fSmrg    * identity mapping if we are not in compat mode.
14201e04c3fSmrg    */
14301e04c3fSmrg   if (ctx->API != API_OPENGL_COMPAT)
14401e04c3fSmrg      return;
14501e04c3fSmrg   /* The generic0 attribute superseeds the position attribute */
146b9abf16eSmaya   const GLbitfield enabled = vao->Enabled;
14701e04c3fSmrg   if (enabled & VERT_BIT_GENERIC0)
14801e04c3fSmrg      vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_GENERIC0;
14901e04c3fSmrg   else if (enabled & VERT_BIT_POS)
15001e04c3fSmrg      vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_POSITION;
15101e04c3fSmrg   else
15201e04c3fSmrg      vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY;
15301e04c3fSmrg}
15401e04c3fSmrg
155af69d88dSmrg
15601e04c3fSmrg/**
15701e04c3fSmrg * Sets the BufferBindingIndex field for the vertex attribute given by
15801e04c3fSmrg * attribIndex.
15901e04c3fSmrg */
16001e04c3fSmrgvoid
16101e04c3fSmrg_mesa_vertex_attrib_binding(struct gl_context *ctx,
16201e04c3fSmrg                            struct gl_vertex_array_object *vao,
16301e04c3fSmrg                            gl_vert_attrib attribIndex,
16401e04c3fSmrg                            GLuint bindingIndex)
16501e04c3fSmrg{
16601e04c3fSmrg   struct gl_array_attributes *array = &vao->VertexAttrib[attribIndex];
16701e04c3fSmrg   assert(!vao->SharedAndImmutable);
168af69d88dSmrg
16901e04c3fSmrg   if (array->BufferBindingIndex != bindingIndex) {
17001e04c3fSmrg      const GLbitfield array_bit = VERT_BIT(attribIndex);
171af69d88dSmrg
1727ec681f3Smrg      if (vao->BufferBinding[bindingIndex].BufferObj)
17301e04c3fSmrg         vao->VertexAttribBufferMask |= array_bit;
17401e04c3fSmrg      else
17501e04c3fSmrg         vao->VertexAttribBufferMask &= ~array_bit;
176af69d88dSmrg
1777ec681f3Smrg      if (vao->BufferBinding[bindingIndex].InstanceDivisor)
1787ec681f3Smrg         vao->NonZeroDivisorMask |= array_bit;
1797ec681f3Smrg      else
1807ec681f3Smrg         vao->NonZeroDivisorMask &= ~array_bit;
1817ec681f3Smrg
18201e04c3fSmrg      vao->BufferBinding[array->BufferBindingIndex]._BoundArrays &= ~array_bit;
18301e04c3fSmrg      vao->BufferBinding[bindingIndex]._BoundArrays |= array_bit;
184af69d88dSmrg
18501e04c3fSmrg      array->BufferBindingIndex = bindingIndex;
18601e04c3fSmrg
187b9abf16eSmaya      vao->NewArrays |= vao->Enabled & array_bit;
1887ec681f3Smrg      vao->NonDefaultStateMask |= array_bit | BITFIELD_BIT(bindingIndex);
189af69d88dSmrg   }
190af69d88dSmrg}
191af69d88dSmrg
192af69d88dSmrg
193af69d88dSmrg/**
194af69d88dSmrg * Binds a buffer object to the vertex buffer binding point given by index,
195af69d88dSmrg * and sets the Offset and Stride fields.
196af69d88dSmrg */
19701e04c3fSmrgvoid
19801e04c3fSmrg_mesa_bind_vertex_buffer(struct gl_context *ctx,
19901e04c3fSmrg                         struct gl_vertex_array_object *vao,
20001e04c3fSmrg                         GLuint index,
20101e04c3fSmrg                         struct gl_buffer_object *vbo,
2027ec681f3Smrg                         GLintptr offset, GLsizei stride,
2037ec681f3Smrg                         bool offset_is_int32, bool take_vbo_ownership)
204af69d88dSmrg{
20501e04c3fSmrg   assert(index < ARRAY_SIZE(vao->BufferBinding));
20601e04c3fSmrg   assert(!vao->SharedAndImmutable);
20701e04c3fSmrg   struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
208af69d88dSmrg
2097ec681f3Smrg   if (ctx->Const.VertexBufferOffsetIsInt32 && (int)offset < 0 &&
2107ec681f3Smrg       !offset_is_int32 && vbo) {
2117ec681f3Smrg      /* The offset will be interpreted as a signed int, so make sure
2127ec681f3Smrg       * the user supplied offset is not negative (driver limitation).
2137ec681f3Smrg       */
2147ec681f3Smrg      _mesa_warning(ctx, "Received negative int32 vertex buffer offset. "
2157ec681f3Smrg			 "(driver limitation)\n");
2167ec681f3Smrg
2177ec681f3Smrg      /* We can't disable this binding, so use a non-negative offset value
2187ec681f3Smrg       * instead.
2197ec681f3Smrg       */
2207ec681f3Smrg      offset = 0;
2217ec681f3Smrg   }
2227ec681f3Smrg
223af69d88dSmrg   if (binding->BufferObj != vbo ||
224af69d88dSmrg       binding->Offset != offset ||
225af69d88dSmrg       binding->Stride != stride) {
226af69d88dSmrg
2277ec681f3Smrg      if (take_vbo_ownership) {
2287ec681f3Smrg         _mesa_reference_buffer_object(ctx, &binding->BufferObj, NULL);
2297ec681f3Smrg         binding->BufferObj = vbo;
2307ec681f3Smrg      } else {
2317ec681f3Smrg         _mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo);
2327ec681f3Smrg      }
233af69d88dSmrg
234af69d88dSmrg      binding->Offset = offset;
235af69d88dSmrg      binding->Stride = stride;
236af69d88dSmrg
2377ec681f3Smrg      if (!vbo) {
23801e04c3fSmrg         vao->VertexAttribBufferMask &= ~binding->_BoundArrays;
239b9abf16eSmaya      } else {
24001e04c3fSmrg         vao->VertexAttribBufferMask |= binding->_BoundArrays;
241b9abf16eSmaya         vbo->UsageHistory |= USAGE_ARRAY_BUFFER;
242b9abf16eSmaya      }
24301e04c3fSmrg
244b9abf16eSmaya      vao->NewArrays |= vao->Enabled & binding->_BoundArrays;
2457ec681f3Smrg      vao->NonDefaultStateMask |= BITFIELD_BIT(index);
246af69d88dSmrg   }
247af69d88dSmrg}
248af69d88dSmrg
249af69d88dSmrg
250af69d88dSmrg/**
251af69d88dSmrg * Sets the InstanceDivisor field in the vertex buffer binding point
252af69d88dSmrg * given by bindingIndex.
253af69d88dSmrg */
254af69d88dSmrgstatic void
25501e04c3fSmrgvertex_binding_divisor(struct gl_context *ctx,
25601e04c3fSmrg                       struct gl_vertex_array_object *vao,
25701e04c3fSmrg                       GLuint bindingIndex,
258af69d88dSmrg                       GLuint divisor)
259af69d88dSmrg{
260af69d88dSmrg   struct gl_vertex_buffer_binding *binding =
26101e04c3fSmrg      &vao->BufferBinding[bindingIndex];
26201e04c3fSmrg   assert(!vao->SharedAndImmutable);
263af69d88dSmrg
264af69d88dSmrg   if (binding->InstanceDivisor != divisor) {
265af69d88dSmrg      binding->InstanceDivisor = divisor;
2667ec681f3Smrg
2677ec681f3Smrg      if (divisor)
2687ec681f3Smrg         vao->NonZeroDivisorMask |= binding->_BoundArrays;
2697ec681f3Smrg      else
2707ec681f3Smrg         vao->NonZeroDivisorMask &= ~binding->_BoundArrays;
2717ec681f3Smrg
272b9abf16eSmaya      vao->NewArrays |= vao->Enabled & binding->_BoundArrays;
2737ec681f3Smrg      vao->NonDefaultStateMask |= BITFIELD_BIT(bindingIndex);
274af69d88dSmrg   }
275af69d88dSmrg}
276af69d88dSmrg
2777ec681f3Smrg/* vertex_formats[gltype - GL_BYTE][integer*2 + normalized][size - 1] */
2787ec681f3Smrgstatic const uint16_t vertex_formats[][4][4] = {
2797ec681f3Smrg   { /* GL_BYTE */
2807ec681f3Smrg      {
2817ec681f3Smrg         PIPE_FORMAT_R8_SSCALED,
2827ec681f3Smrg         PIPE_FORMAT_R8G8_SSCALED,
2837ec681f3Smrg         PIPE_FORMAT_R8G8B8_SSCALED,
2847ec681f3Smrg         PIPE_FORMAT_R8G8B8A8_SSCALED
2857ec681f3Smrg      },
2867ec681f3Smrg      {
2877ec681f3Smrg         PIPE_FORMAT_R8_SNORM,
2887ec681f3Smrg         PIPE_FORMAT_R8G8_SNORM,
2897ec681f3Smrg         PIPE_FORMAT_R8G8B8_SNORM,
2907ec681f3Smrg         PIPE_FORMAT_R8G8B8A8_SNORM
2917ec681f3Smrg      },
2927ec681f3Smrg      {
2937ec681f3Smrg         PIPE_FORMAT_R8_SINT,
2947ec681f3Smrg         PIPE_FORMAT_R8G8_SINT,
2957ec681f3Smrg         PIPE_FORMAT_R8G8B8_SINT,
2967ec681f3Smrg         PIPE_FORMAT_R8G8B8A8_SINT
2977ec681f3Smrg      },
2987ec681f3Smrg   },
2997ec681f3Smrg   { /* GL_UNSIGNED_BYTE */
3007ec681f3Smrg      {
3017ec681f3Smrg         PIPE_FORMAT_R8_USCALED,
3027ec681f3Smrg         PIPE_FORMAT_R8G8_USCALED,
3037ec681f3Smrg         PIPE_FORMAT_R8G8B8_USCALED,
3047ec681f3Smrg         PIPE_FORMAT_R8G8B8A8_USCALED
3057ec681f3Smrg      },
3067ec681f3Smrg      {
3077ec681f3Smrg         PIPE_FORMAT_R8_UNORM,
3087ec681f3Smrg         PIPE_FORMAT_R8G8_UNORM,
3097ec681f3Smrg         PIPE_FORMAT_R8G8B8_UNORM,
3107ec681f3Smrg         PIPE_FORMAT_R8G8B8A8_UNORM
3117ec681f3Smrg      },
3127ec681f3Smrg      {
3137ec681f3Smrg         PIPE_FORMAT_R8_UINT,
3147ec681f3Smrg         PIPE_FORMAT_R8G8_UINT,
3157ec681f3Smrg         PIPE_FORMAT_R8G8B8_UINT,
3167ec681f3Smrg         PIPE_FORMAT_R8G8B8A8_UINT
3177ec681f3Smrg      },
3187ec681f3Smrg   },
3197ec681f3Smrg   { /* GL_SHORT */
3207ec681f3Smrg      {
3217ec681f3Smrg         PIPE_FORMAT_R16_SSCALED,
3227ec681f3Smrg         PIPE_FORMAT_R16G16_SSCALED,
3237ec681f3Smrg         PIPE_FORMAT_R16G16B16_SSCALED,
3247ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_SSCALED
3257ec681f3Smrg      },
3267ec681f3Smrg      {
3277ec681f3Smrg         PIPE_FORMAT_R16_SNORM,
3287ec681f3Smrg         PIPE_FORMAT_R16G16_SNORM,
3297ec681f3Smrg         PIPE_FORMAT_R16G16B16_SNORM,
3307ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_SNORM
3317ec681f3Smrg      },
3327ec681f3Smrg      {
3337ec681f3Smrg         PIPE_FORMAT_R16_SINT,
3347ec681f3Smrg         PIPE_FORMAT_R16G16_SINT,
3357ec681f3Smrg         PIPE_FORMAT_R16G16B16_SINT,
3367ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_SINT
3377ec681f3Smrg      },
3387ec681f3Smrg   },
3397ec681f3Smrg   { /* GL_UNSIGNED_SHORT */
3407ec681f3Smrg      {
3417ec681f3Smrg         PIPE_FORMAT_R16_USCALED,
3427ec681f3Smrg         PIPE_FORMAT_R16G16_USCALED,
3437ec681f3Smrg         PIPE_FORMAT_R16G16B16_USCALED,
3447ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_USCALED
3457ec681f3Smrg      },
3467ec681f3Smrg      {
3477ec681f3Smrg         PIPE_FORMAT_R16_UNORM,
3487ec681f3Smrg         PIPE_FORMAT_R16G16_UNORM,
3497ec681f3Smrg         PIPE_FORMAT_R16G16B16_UNORM,
3507ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_UNORM
3517ec681f3Smrg      },
3527ec681f3Smrg      {
3537ec681f3Smrg         PIPE_FORMAT_R16_UINT,
3547ec681f3Smrg         PIPE_FORMAT_R16G16_UINT,
3557ec681f3Smrg         PIPE_FORMAT_R16G16B16_UINT,
3567ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_UINT
3577ec681f3Smrg      },
3587ec681f3Smrg   },
3597ec681f3Smrg   { /* GL_INT */
3607ec681f3Smrg      {
3617ec681f3Smrg         PIPE_FORMAT_R32_SSCALED,
3627ec681f3Smrg         PIPE_FORMAT_R32G32_SSCALED,
3637ec681f3Smrg         PIPE_FORMAT_R32G32B32_SSCALED,
3647ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_SSCALED
3657ec681f3Smrg      },
3667ec681f3Smrg      {
3677ec681f3Smrg         PIPE_FORMAT_R32_SNORM,
3687ec681f3Smrg         PIPE_FORMAT_R32G32_SNORM,
3697ec681f3Smrg         PIPE_FORMAT_R32G32B32_SNORM,
3707ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_SNORM
3717ec681f3Smrg      },
3727ec681f3Smrg      {
3737ec681f3Smrg         PIPE_FORMAT_R32_SINT,
3747ec681f3Smrg         PIPE_FORMAT_R32G32_SINT,
3757ec681f3Smrg         PIPE_FORMAT_R32G32B32_SINT,
3767ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_SINT
3777ec681f3Smrg      },
3787ec681f3Smrg   },
3797ec681f3Smrg   { /* GL_UNSIGNED_INT */
3807ec681f3Smrg      {
3817ec681f3Smrg         PIPE_FORMAT_R32_USCALED,
3827ec681f3Smrg         PIPE_FORMAT_R32G32_USCALED,
3837ec681f3Smrg         PIPE_FORMAT_R32G32B32_USCALED,
3847ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_USCALED
3857ec681f3Smrg      },
3867ec681f3Smrg      {
3877ec681f3Smrg         PIPE_FORMAT_R32_UNORM,
3887ec681f3Smrg         PIPE_FORMAT_R32G32_UNORM,
3897ec681f3Smrg         PIPE_FORMAT_R32G32B32_UNORM,
3907ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_UNORM
3917ec681f3Smrg      },
3927ec681f3Smrg      {
3937ec681f3Smrg         PIPE_FORMAT_R32_UINT,
3947ec681f3Smrg         PIPE_FORMAT_R32G32_UINT,
3957ec681f3Smrg         PIPE_FORMAT_R32G32B32_UINT,
3967ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_UINT
3977ec681f3Smrg      },
3987ec681f3Smrg   },
3997ec681f3Smrg   { /* GL_FLOAT */
4007ec681f3Smrg      {
4017ec681f3Smrg         PIPE_FORMAT_R32_FLOAT,
4027ec681f3Smrg         PIPE_FORMAT_R32G32_FLOAT,
4037ec681f3Smrg         PIPE_FORMAT_R32G32B32_FLOAT,
4047ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_FLOAT
4057ec681f3Smrg      },
4067ec681f3Smrg      {
4077ec681f3Smrg         PIPE_FORMAT_R32_FLOAT,
4087ec681f3Smrg         PIPE_FORMAT_R32G32_FLOAT,
4097ec681f3Smrg         PIPE_FORMAT_R32G32B32_FLOAT,
4107ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_FLOAT
4117ec681f3Smrg      },
4127ec681f3Smrg   },
4137ec681f3Smrg   {{0}}, /* GL_2_BYTES */
4147ec681f3Smrg   {{0}}, /* GL_3_BYTES */
4157ec681f3Smrg   {{0}}, /* GL_4_BYTES */
4167ec681f3Smrg   { /* GL_DOUBLE */
4177ec681f3Smrg      {
4187ec681f3Smrg         PIPE_FORMAT_R64_FLOAT,
4197ec681f3Smrg         PIPE_FORMAT_R64G64_FLOAT,
4207ec681f3Smrg         PIPE_FORMAT_R64G64B64_FLOAT,
4217ec681f3Smrg         PIPE_FORMAT_R64G64B64A64_FLOAT
4227ec681f3Smrg      },
4237ec681f3Smrg      {
4247ec681f3Smrg         PIPE_FORMAT_R64_FLOAT,
4257ec681f3Smrg         PIPE_FORMAT_R64G64_FLOAT,
4267ec681f3Smrg         PIPE_FORMAT_R64G64B64_FLOAT,
4277ec681f3Smrg         PIPE_FORMAT_R64G64B64A64_FLOAT
4287ec681f3Smrg      },
4297ec681f3Smrg   },
4307ec681f3Smrg   { /* GL_HALF_FLOAT */
4317ec681f3Smrg      {
4327ec681f3Smrg         PIPE_FORMAT_R16_FLOAT,
4337ec681f3Smrg         PIPE_FORMAT_R16G16_FLOAT,
4347ec681f3Smrg         PIPE_FORMAT_R16G16B16_FLOAT,
4357ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_FLOAT
4367ec681f3Smrg      },
4377ec681f3Smrg      {
4387ec681f3Smrg         PIPE_FORMAT_R16_FLOAT,
4397ec681f3Smrg         PIPE_FORMAT_R16G16_FLOAT,
4407ec681f3Smrg         PIPE_FORMAT_R16G16B16_FLOAT,
4417ec681f3Smrg         PIPE_FORMAT_R16G16B16A16_FLOAT
4427ec681f3Smrg      },
4437ec681f3Smrg   },
4447ec681f3Smrg   { /* GL_FIXED */
4457ec681f3Smrg      {
4467ec681f3Smrg         PIPE_FORMAT_R32_FIXED,
4477ec681f3Smrg         PIPE_FORMAT_R32G32_FIXED,
4487ec681f3Smrg         PIPE_FORMAT_R32G32B32_FIXED,
4497ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_FIXED
4507ec681f3Smrg      },
4517ec681f3Smrg      {
4527ec681f3Smrg         PIPE_FORMAT_R32_FIXED,
4537ec681f3Smrg         PIPE_FORMAT_R32G32_FIXED,
4547ec681f3Smrg         PIPE_FORMAT_R32G32B32_FIXED,
4557ec681f3Smrg         PIPE_FORMAT_R32G32B32A32_FIXED
4567ec681f3Smrg      },
4577ec681f3Smrg   },
4587ec681f3Smrg};
4597ec681f3Smrg
4607ec681f3Smrg/**
4617ec681f3Smrg * Return a PIPE_FORMAT_x for the given GL datatype and size.
4627ec681f3Smrg */
4637ec681f3Smrgstatic enum pipe_format
4647ec681f3Smrgvertex_format_to_pipe_format(GLubyte size, GLenum16 type, GLenum16 format,
4657ec681f3Smrg                             bool normalized, bool integer, bool doubles)
4667ec681f3Smrg{
4677ec681f3Smrg   assert(size >= 1 && size <= 4);
4687ec681f3Smrg   assert(format == GL_RGBA || format == GL_BGRA);
4697ec681f3Smrg
4707ec681f3Smrg   /* Raw doubles use 64_UINT. */
4717ec681f3Smrg   if (doubles)
4727ec681f3Smrg      return PIPE_FORMAT_R64_UINT + size - 1;
4737ec681f3Smrg
4747ec681f3Smrg   switch (type) {
4757ec681f3Smrg   case GL_HALF_FLOAT_OES:
4767ec681f3Smrg      type = GL_HALF_FLOAT;
4777ec681f3Smrg      break;
4787ec681f3Smrg
4797ec681f3Smrg   case GL_INT_2_10_10_10_REV:
4807ec681f3Smrg      assert(size == 4 && !integer);
4817ec681f3Smrg
4827ec681f3Smrg      if (format == GL_BGRA) {
4837ec681f3Smrg         if (normalized)
4847ec681f3Smrg            return PIPE_FORMAT_B10G10R10A2_SNORM;
4857ec681f3Smrg         else
4867ec681f3Smrg            return PIPE_FORMAT_B10G10R10A2_SSCALED;
4877ec681f3Smrg      } else {
4887ec681f3Smrg         if (normalized)
4897ec681f3Smrg            return PIPE_FORMAT_R10G10B10A2_SNORM;
4907ec681f3Smrg         else
4917ec681f3Smrg            return PIPE_FORMAT_R10G10B10A2_SSCALED;
4927ec681f3Smrg      }
4937ec681f3Smrg      break;
4947ec681f3Smrg
4957ec681f3Smrg   case GL_UNSIGNED_INT_2_10_10_10_REV:
4967ec681f3Smrg      assert(size == 4 && !integer);
4977ec681f3Smrg
4987ec681f3Smrg      if (format == GL_BGRA) {
4997ec681f3Smrg         if (normalized)
5007ec681f3Smrg            return PIPE_FORMAT_B10G10R10A2_UNORM;
5017ec681f3Smrg         else
5027ec681f3Smrg            return PIPE_FORMAT_B10G10R10A2_USCALED;
5037ec681f3Smrg      } else {
5047ec681f3Smrg         if (normalized)
5057ec681f3Smrg            return PIPE_FORMAT_R10G10B10A2_UNORM;
5067ec681f3Smrg         else
5077ec681f3Smrg            return PIPE_FORMAT_R10G10B10A2_USCALED;
5087ec681f3Smrg      }
5097ec681f3Smrg      break;
5107ec681f3Smrg
5117ec681f3Smrg   case GL_UNSIGNED_INT_10F_11F_11F_REV:
5127ec681f3Smrg      assert(size == 3 && !integer && format == GL_RGBA);
5137ec681f3Smrg      return PIPE_FORMAT_R11G11B10_FLOAT;
5147ec681f3Smrg
5157ec681f3Smrg   case GL_UNSIGNED_BYTE:
5167ec681f3Smrg      if (format == GL_BGRA) {
5177ec681f3Smrg         /* this is an odd-ball case */
5187ec681f3Smrg         assert(normalized);
5197ec681f3Smrg         return PIPE_FORMAT_B8G8R8A8_UNORM;
5207ec681f3Smrg      }
5217ec681f3Smrg      break;
5227ec681f3Smrg   }
5237ec681f3Smrg
5247ec681f3Smrg   unsigned index = integer*2 + normalized;
5257ec681f3Smrg   assert(index <= 2);
5267ec681f3Smrg   assert(type >= GL_BYTE && type <= GL_FIXED);
5277ec681f3Smrg   return vertex_formats[type - GL_BYTE][index][size-1];
5287ec681f3Smrg}
529af69d88dSmrg
530b9abf16eSmayavoid
531b9abf16eSmaya_mesa_set_vertex_format(struct gl_vertex_format *vertex_format,
532b9abf16eSmaya                        GLubyte size, GLenum16 type, GLenum16 format,
533b9abf16eSmaya                        GLboolean normalized, GLboolean integer,
534b9abf16eSmaya                        GLboolean doubles)
535b9abf16eSmaya{
536b9abf16eSmaya   assert(size <= 4);
537b9abf16eSmaya   vertex_format->Type = type;
538b9abf16eSmaya   vertex_format->Format = format;
539b9abf16eSmaya   vertex_format->Size = size;
540b9abf16eSmaya   vertex_format->Normalized = normalized;
541b9abf16eSmaya   vertex_format->Integer = integer;
542b9abf16eSmaya   vertex_format->Doubles = doubles;
543b9abf16eSmaya   vertex_format->_ElementSize = _mesa_bytes_per_vertex_attrib(size, type);
544b9abf16eSmaya   assert(vertex_format->_ElementSize <= 4*sizeof(double));
5457ec681f3Smrg   vertex_format->_PipeFormat =
5467ec681f3Smrg      vertex_format_to_pipe_format(size, type, format, normalized, integer,
5477ec681f3Smrg                                   doubles);
5487ec681f3Smrg   /* pipe_vertex_element::src_format has only 8 bits, assuming a signed enum */
5497ec681f3Smrg   assert(vertex_format->_PipeFormat <= 255);
550b9abf16eSmaya}
551b9abf16eSmaya
552b9abf16eSmaya
553af69d88dSmrg/**
554af69d88dSmrg * Examine the API profile and extensions to determine which types are legal
555af69d88dSmrg * for vertex arrays.  This is called once from update_array_format().
556af69d88dSmrg */
557af69d88dSmrgstatic GLbitfield
558af69d88dSmrgget_legal_types_mask(const struct gl_context *ctx)
559af69d88dSmrg{
560af69d88dSmrg   GLbitfield legalTypesMask = ALL_TYPE_BITS;
561af69d88dSmrg
562af69d88dSmrg   if (_mesa_is_gles(ctx)) {
563af69d88dSmrg      legalTypesMask &= ~(FIXED_GL_BIT |
564af69d88dSmrg                          DOUBLE_BIT |
565af69d88dSmrg                          UNSIGNED_INT_10F_11F_11F_REV_BIT);
566af69d88dSmrg
567af69d88dSmrg      /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
568af69d88dSmrg       * 3.0.  The 2_10_10_10 types are added in OpenGL ES 3.0 or
569af69d88dSmrg       * GL_OES_vertex_type_10_10_10_2.  GL_HALF_FLOAT data is not allowed
570af69d88dSmrg       * until 3.0 or with the GL_OES_vertex_half float extension, which isn't
571af69d88dSmrg       * quite as trivial as we'd like because it uses a different enum value
572af69d88dSmrg       * for GL_HALF_FLOAT_OES.
573af69d88dSmrg       */
574af69d88dSmrg      if (ctx->Version < 30) {
575af69d88dSmrg         legalTypesMask &= ~(UNSIGNED_INT_BIT |
576af69d88dSmrg                             INT_BIT |
577af69d88dSmrg                             UNSIGNED_INT_2_10_10_10_REV_BIT |
57801e04c3fSmrg                             INT_2_10_10_10_REV_BIT);
57901e04c3fSmrg
58001e04c3fSmrg         if (!_mesa_has_OES_vertex_half_float(ctx))
58101e04c3fSmrg            legalTypesMask &= ~HALF_BIT;
582af69d88dSmrg      }
583af69d88dSmrg   }
584af69d88dSmrg   else {
585af69d88dSmrg      legalTypesMask &= ~FIXED_ES_BIT;
586af69d88dSmrg
587af69d88dSmrg      if (!ctx->Extensions.ARB_ES2_compatibility)
588af69d88dSmrg         legalTypesMask &= ~FIXED_GL_BIT;
589af69d88dSmrg
590af69d88dSmrg      if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
591af69d88dSmrg         legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
592af69d88dSmrg                             INT_2_10_10_10_REV_BIT);
593af69d88dSmrg
594af69d88dSmrg      if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev)
595af69d88dSmrg         legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT;
596af69d88dSmrg   }
597af69d88dSmrg
598af69d88dSmrg   return legalTypesMask;
599af69d88dSmrg}
600af69d88dSmrg
60101e04c3fSmrgstatic GLenum
60201e04c3fSmrgget_array_format(const struct gl_context *ctx, GLint sizeMax, GLint *size)
60301e04c3fSmrg{
60401e04c3fSmrg   GLenum format = GL_RGBA;
60501e04c3fSmrg
60601e04c3fSmrg   /* Do size parameter checking.
60701e04c3fSmrg    * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and
60801e04c3fSmrg    * must be handled specially.
60901e04c3fSmrg    */
61001e04c3fSmrg   if (ctx->Extensions.EXT_vertex_array_bgra && sizeMax == BGRA_OR_4 &&
61101e04c3fSmrg       *size == GL_BGRA) {
61201e04c3fSmrg      format = GL_BGRA;
61301e04c3fSmrg      *size = 4;
61401e04c3fSmrg   }
61501e04c3fSmrg
61601e04c3fSmrg   return format;
61701e04c3fSmrg}
61801e04c3fSmrg
61901e04c3fSmrg
62001e04c3fSmrg/**
62101e04c3fSmrg * \param attrib         The index of the attribute array
62201e04c3fSmrg * \param size           Components per element (1, 2, 3 or 4)
62301e04c3fSmrg * \param type           Datatype of each component (GL_FLOAT, GL_INT, etc)
62401e04c3fSmrg * \param format         Either GL_RGBA or GL_BGRA.
62501e04c3fSmrg * \param normalized     Whether integer types are converted to floats in [-1, 1]
62601e04c3fSmrg * \param integer        Integer-valued values (will not be normalized to [-1, 1])
62701e04c3fSmrg * \param doubles        Double values not reduced to floats
62801e04c3fSmrg * \param relativeOffset Offset of the first element relative to the binding
62901e04c3fSmrg *                       offset.
63001e04c3fSmrg */
63101e04c3fSmrgvoid
63201e04c3fSmrg_mesa_update_array_format(struct gl_context *ctx,
63301e04c3fSmrg                          struct gl_vertex_array_object *vao,
63401e04c3fSmrg                          gl_vert_attrib attrib, GLint size, GLenum type,
63501e04c3fSmrg                          GLenum format, GLboolean normalized,
63601e04c3fSmrg                          GLboolean integer, GLboolean doubles,
63701e04c3fSmrg                          GLuint relativeOffset)
63801e04c3fSmrg{
63901e04c3fSmrg   struct gl_array_attributes *const array = &vao->VertexAttrib[attrib];
6407ec681f3Smrg   struct gl_vertex_format new_format;
64101e04c3fSmrg
64201e04c3fSmrg   assert(!vao->SharedAndImmutable);
64301e04c3fSmrg   assert(size <= 4);
64401e04c3fSmrg
6457ec681f3Smrg   _mesa_set_vertex_format(&new_format, size, type, format,
646b9abf16eSmaya                           normalized, integer, doubles);
64701e04c3fSmrg
6487ec681f3Smrg   if ((array->RelativeOffset == relativeOffset) &&
6497ec681f3Smrg       !memcmp(&new_format, &array->Format, sizeof(new_format)))
6507ec681f3Smrg      return;
6517ec681f3Smrg
6527ec681f3Smrg   array->RelativeOffset = relativeOffset;
6537ec681f3Smrg   array->Format = new_format;
6547ec681f3Smrg
655b9abf16eSmaya   vao->NewArrays |= vao->Enabled & VERT_BIT(attrib);
6567ec681f3Smrg   vao->NonDefaultStateMask |= BITFIELD_BIT(attrib);
65701e04c3fSmrg}
658af69d88dSmrg
659af69d88dSmrg/**
66001e04c3fSmrg * Does error checking of the format in an attrib array.
661af69d88dSmrg *
66201e04c3fSmrg * Called by *Pointer() and VertexAttrib*Format().
663af69d88dSmrg *
664af69d88dSmrg * \param func         Name of calling function used for error reporting
665af69d88dSmrg * \param attrib       The index of the attribute array
666af69d88dSmrg * \param legalTypes   Bitmask of *_BIT above indicating legal datatypes
667af69d88dSmrg * \param sizeMin      Min allowable size value
668af69d88dSmrg * \param sizeMax      Max allowable size value (may also be BGRA_OR_4)
669af69d88dSmrg * \param size         Components per element (1, 2, 3 or 4)
670af69d88dSmrg * \param type         Datatype of each component (GL_FLOAT, GL_INT, etc)
671af69d88dSmrg * \param normalized   Whether integer types are converted to floats in [-1, 1]
672af69d88dSmrg * \param integer      Integer-valued values (will not be normalized to [-1, 1])
67301e04c3fSmrg * \param doubles      Double values not reduced to floats
674af69d88dSmrg * \param relativeOffset Offset of the first element relative to the binding offset.
67501e04c3fSmrg * \return bool True if validation is successful, False otherwise.
676af69d88dSmrg */
677af69d88dSmrgstatic bool
67801e04c3fSmrgvalidate_array_format(struct gl_context *ctx, const char *func,
67901e04c3fSmrg                      struct gl_vertex_array_object *vao,
68001e04c3fSmrg                      GLuint attrib, GLbitfield legalTypesMask,
68101e04c3fSmrg                      GLint sizeMin, GLint sizeMax,
6827ec681f3Smrg                      GLint size, GLenum type, bool normalized,
6837ec681f3Smrg                      bool integer, bool doubles,
68401e04c3fSmrg                      GLuint relativeOffset, GLenum format)
68501e04c3fSmrg{
6863464ebd5Sriastradh   GLbitfield typeBit;
6873464ebd5Sriastradh
68801e04c3fSmrg   /* at most, one of these bools can be true */
68901e04c3fSmrg   assert((int) normalized + (int) integer + (int) doubles <= 1);
69001e04c3fSmrg
69101e04c3fSmrg   if (ctx->Array.LegalTypesMask == 0 || ctx->Array.LegalTypesMaskAPI != ctx->API) {
69201e04c3fSmrg      /* Compute the LegalTypesMask only once, unless the context API has
69301e04c3fSmrg       * changed, in which case we want to compute it again.  We can't do this
69401e04c3fSmrg       * in _mesa_init_varrays() below because extensions are not yet enabled
69501e04c3fSmrg       * at that point.
696af69d88dSmrg       */
697af69d88dSmrg      ctx->Array.LegalTypesMask = get_legal_types_mask(ctx);
69801e04c3fSmrg      ctx->Array.LegalTypesMaskAPI = ctx->API;
6993464ebd5Sriastradh   }
700af69d88dSmrg
701af69d88dSmrg   legalTypesMask &= ctx->Array.LegalTypesMask;
702af69d88dSmrg
703af69d88dSmrg   if (_mesa_is_gles(ctx) && sizeMax == BGRA_OR_4) {
704af69d88dSmrg      /* BGRA ordering is not supported in ES contexts.
705af69d88dSmrg       */
706af69d88dSmrg      sizeMax = 4;
7073464ebd5Sriastradh   }
7083464ebd5Sriastradh
7093464ebd5Sriastradh   typeBit = type_to_bit(ctx, type);
7103464ebd5Sriastradh   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
7113464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
71201e04c3fSmrg                  func, _mesa_enum_to_string(type));
713af69d88dSmrg      return false;
7143464ebd5Sriastradh   }
7153464ebd5Sriastradh
71601e04c3fSmrg   if (format == GL_BGRA) {
717af69d88dSmrg      /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
718af69d88dSmrg       *
719af69d88dSmrg       * "An INVALID_OPERATION error is generated under any of the following
720af69d88dSmrg       *  conditions:
721af69d88dSmrg       *    ...
722af69d88dSmrg       *    • size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV
723af69d88dSmrg       *      or UNSIGNED_INT_2_10_10_10_REV;
724af69d88dSmrg       *    ...
725af69d88dSmrg       *    • size is BGRA and normalized is FALSE;"
726af69d88dSmrg       */
727af69d88dSmrg      bool bgra_error = false;
728af69d88dSmrg
729af69d88dSmrg      if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
730af69d88dSmrg         if (type != GL_UNSIGNED_INT_2_10_10_10_REV &&
731af69d88dSmrg             type != GL_INT_2_10_10_10_REV &&
732af69d88dSmrg             type != GL_UNSIGNED_BYTE)
733af69d88dSmrg            bgra_error = true;
734af69d88dSmrg      } else if (type != GL_UNSIGNED_BYTE)
735af69d88dSmrg         bgra_error = true;
736af69d88dSmrg
737af69d88dSmrg      if (bgra_error) {
738af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)",
73901e04c3fSmrg                     func, _mesa_enum_to_string(type));
740af69d88dSmrg         return false;
741af69d88dSmrg      }
742af69d88dSmrg
743af69d88dSmrg      if (!normalized) {
744af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
745af69d88dSmrg                     "%s(size=GL_BGRA and normalized=GL_FALSE)", func);
746af69d88dSmrg         return false;
7473464ebd5Sriastradh      }
7483464ebd5Sriastradh   }
7493464ebd5Sriastradh   else if (size < sizeMin || size > sizeMax || size > 4) {
7503464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
751af69d88dSmrg      return false;
752af69d88dSmrg   }
753af69d88dSmrg
754af69d88dSmrg   if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
755af69d88dSmrg       (type == GL_UNSIGNED_INT_2_10_10_10_REV ||
756af69d88dSmrg        type == GL_INT_2_10_10_10_REV) && size != 4) {
757af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
758af69d88dSmrg      return false;
759af69d88dSmrg   }
760af69d88dSmrg
761af69d88dSmrg   /* The ARB_vertex_attrib_binding_spec says:
762af69d88dSmrg    *
763af69d88dSmrg    *   An INVALID_VALUE error is generated if <relativeoffset> is larger than
764af69d88dSmrg    *   the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.
765af69d88dSmrg    */
766af69d88dSmrg   if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) {
767af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
768af69d88dSmrg                  "%s(relativeOffset=%d > "
769af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)",
770af69d88dSmrg                  func, relativeOffset);
771af69d88dSmrg      return false;
772af69d88dSmrg   }
773af69d88dSmrg
774af69d88dSmrg   if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev &&
775af69d88dSmrg         type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) {
776af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
777af69d88dSmrg      return false;
7783464ebd5Sriastradh   }
7793464ebd5Sriastradh
780af69d88dSmrg   return true;
781af69d88dSmrg}
782af69d88dSmrg
783af69d88dSmrg/**
78401e04c3fSmrg * Do error checking for glVertex/Color/TexCoord/...Pointer functions.
785af69d88dSmrg *
786af69d88dSmrg * \param func  name of calling function used for error reporting
7877ec681f3Smrg * \param vao the vao to update
7887ec681f3Smrg * \param obj the bound buffer object
789af69d88dSmrg * \param attrib  the attribute array index to update
790af69d88dSmrg * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
791af69d88dSmrg * \param sizeMin  min allowable size value
792af69d88dSmrg * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
793af69d88dSmrg * \param size  components per element (1, 2, 3 or 4)
794af69d88dSmrg * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
795af69d88dSmrg * \param stride  stride between elements, in elements
796af69d88dSmrg * \param normalized  are integer types converted to floats in [-1, 1]?
797af69d88dSmrg * \param integer  integer-valued values (will not be normalized to [-1,1])
79801e04c3fSmrg * \param doubles  Double values not reduced to floats
799af69d88dSmrg * \param ptr  the address (or offset inside VBO) of the array data
800af69d88dSmrg */
801af69d88dSmrgstatic void
80201e04c3fSmrgvalidate_array(struct gl_context *ctx, const char *func,
8037ec681f3Smrg               struct gl_vertex_array_object *vao,
8047ec681f3Smrg               struct gl_buffer_object *obj,
80501e04c3fSmrg               GLuint attrib, GLbitfield legalTypesMask,
80601e04c3fSmrg               GLint sizeMin, GLint sizeMax,
80701e04c3fSmrg               GLint size, GLenum type, GLsizei stride,
80801e04c3fSmrg               GLboolean normalized, GLboolean integer, GLboolean doubles,
80901e04c3fSmrg               const GLvoid *ptr)
810af69d88dSmrg{
811af69d88dSmrg   /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says:
812af69d88dSmrg    *
813af69d88dSmrg    *     "Client vertex arrays - all vertex array attribute pointers must
814af69d88dSmrg    *     refer to buffer objects (section 2.9.2). The default vertex array
815af69d88dSmrg    *     object (the name zero) is also deprecated. Calling
816af69d88dSmrg    *     VertexAttribPointer when no buffer object or no vertex array object
817af69d88dSmrg    *     is bound will generate an INVALID_OPERATION error..."
818af69d88dSmrg    *
819af69d88dSmrg    * The check for VBOs is handled below.
820af69d88dSmrg    */
82101e04c3fSmrg   if (ctx->API == API_OPENGL_CORE && (vao == ctx->Array.DefaultVAO)) {
822af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)",
823af69d88dSmrg                  func);
824af69d88dSmrg      return;
825af69d88dSmrg   }
826af69d88dSmrg
8273464ebd5Sriastradh   if (stride < 0) {
8283464ebd5Sriastradh      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
8293464ebd5Sriastradh      return;
8303464ebd5Sriastradh   }
8314a49301eSmrg
83201e04c3fSmrg   if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 &&
83301e04c3fSmrg       stride > ctx->Const.MaxVertexAttribStride) {
83401e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
83501e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
83601e04c3fSmrg      return;
83701e04c3fSmrg   }
83801e04c3fSmrg
839af69d88dSmrg   /* Page 29 (page 44 of the PDF) of the OpenGL 3.3 spec says:
840af69d88dSmrg    *
841af69d88dSmrg    *     "An INVALID_OPERATION error is generated under any of the following
842af69d88dSmrg    *     conditions:
843af69d88dSmrg    *
844af69d88dSmrg    *     ...
845af69d88dSmrg    *
846af69d88dSmrg    *     * any of the *Pointer commands specifying the location and
847af69d88dSmrg    *       organization of vertex array data are called while zero is bound
848af69d88dSmrg    *       to the ARRAY_BUFFER buffer object binding point (see section
849af69d88dSmrg    *       2.9.6), and the pointer argument is not NULL."
850af69d88dSmrg    */
85101e04c3fSmrg   if (ptr != NULL && vao != ctx->Array.DefaultVAO &&
8527ec681f3Smrg       !obj) {
8533464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
8544a49301eSmrg      return;
8554a49301eSmrg   }
85601e04c3fSmrg}
8574a49301eSmrg
85801e04c3fSmrg
85901e04c3fSmrgstatic bool
86001e04c3fSmrgvalidate_array_and_format(struct gl_context *ctx, const char *func,
8617ec681f3Smrg                          struct gl_vertex_array_object *vao,
8627ec681f3Smrg                          struct gl_buffer_object *obj,
86301e04c3fSmrg                          GLuint attrib, GLbitfield legalTypes,
86401e04c3fSmrg                          GLint sizeMin, GLint sizeMax,
86501e04c3fSmrg                          GLint size, GLenum type, GLsizei stride,
86601e04c3fSmrg                          GLboolean normalized, GLboolean integer,
8677ec681f3Smrg                          GLboolean doubles, GLenum format, const GLvoid *ptr)
86801e04c3fSmrg{
8697ec681f3Smrg   validate_array(ctx, func, vao, obj, attrib, legalTypes, sizeMin, sizeMax,
8707ec681f3Smrg                  size, type, stride, normalized, integer, doubles, ptr);
87101e04c3fSmrg
87201e04c3fSmrg   return validate_array_format(ctx, func, vao, attrib, legalTypes, sizeMin,
87301e04c3fSmrg                                sizeMax, size, type, normalized, integer,
87401e04c3fSmrg                                doubles, 0, format);
87501e04c3fSmrg}
87601e04c3fSmrg
87701e04c3fSmrg
87801e04c3fSmrg/**
87901e04c3fSmrg * Update state for glVertex/Color/TexCoord/...Pointer functions.
88001e04c3fSmrg *
8817ec681f3Smrg * \param vao the vao to update
8827ec681f3Smrg * \param obj the bound buffer object
88301e04c3fSmrg * \param attrib  the attribute array index to update
88401e04c3fSmrg * \param format  Either GL_RGBA or GL_BGRA.
88501e04c3fSmrg * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
88601e04c3fSmrg * \param size  components per element (1, 2, 3 or 4)
88701e04c3fSmrg * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
88801e04c3fSmrg * \param stride  stride between elements, in elements
88901e04c3fSmrg * \param normalized  are integer types converted to floats in [-1, 1]?
89001e04c3fSmrg * \param integer  integer-valued values (will not be normalized to [-1,1])
89101e04c3fSmrg * \param doubles  Double values not reduced to floats
89201e04c3fSmrg * \param ptr  the address (or offset inside VBO) of the array data
89301e04c3fSmrg */
89401e04c3fSmrgstatic void
89501e04c3fSmrgupdate_array(struct gl_context *ctx,
8967ec681f3Smrg             struct gl_vertex_array_object *vao,
8977ec681f3Smrg             struct gl_buffer_object *obj,
89801e04c3fSmrg             GLuint attrib, GLenum format,
89901e04c3fSmrg             GLint sizeMax,
90001e04c3fSmrg             GLint size, GLenum type, GLsizei stride,
90101e04c3fSmrg             GLboolean normalized, GLboolean integer, GLboolean doubles,
90201e04c3fSmrg             const GLvoid *ptr)
90301e04c3fSmrg{
90401e04c3fSmrg   _mesa_update_array_format(ctx, vao, attrib, size, type, format,
90501e04c3fSmrg                             normalized, integer, doubles, 0);
9063464ebd5Sriastradh
907af69d88dSmrg   /* Reset the vertex attrib binding */
90801e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao, attrib, attrib);
9094a49301eSmrg
910af69d88dSmrg   /* The Stride and Ptr fields are not set by update_array_format() */
91101e04c3fSmrg   struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
9127ec681f3Smrg   if ((array->Stride != stride) || (array->Ptr != ptr)) {
9137ec681f3Smrg      array->Stride = stride;
9147ec681f3Smrg      array->Ptr = ptr;
9157ec681f3Smrg      vao->NewArrays |= vao->Enabled & VERT_BIT(attrib);
9167ec681f3Smrg      vao->NonDefaultStateMask |= BITFIELD_BIT(attrib);
9177ec681f3Smrg   }
918c1f859d4Smrg
919af69d88dSmrg   /* Update the vertex buffer binding */
920b9abf16eSmaya   GLsizei effectiveStride = stride != 0 ?
921b9abf16eSmaya      stride : array->Format._ElementSize;
92201e04c3fSmrg   _mesa_bind_vertex_buffer(ctx, vao, attrib,
9237ec681f3Smrg                            obj, (GLintptr) ptr,
9247ec681f3Smrg                            effectiveStride, false, false);
92501e04c3fSmrg}
92601e04c3fSmrg
9277ec681f3Smrg
9287ec681f3Smrg/* Helper function for all EXT_direct_state_access glVertexArray* functions */
9297ec681f3Smrgstatic bool
9307ec681f3Smrg_lookup_vao_and_vbo_dsa(struct gl_context *ctx,
9317ec681f3Smrg                        GLuint vaobj, GLuint buffer,
9327ec681f3Smrg                        GLintptr offset,
9337ec681f3Smrg                        struct gl_vertex_array_object** vao,
9347ec681f3Smrg                        struct gl_buffer_object** vbo,
9357ec681f3Smrg                        const char* caller)
9367ec681f3Smrg{
9377ec681f3Smrg   *vao = _mesa_lookup_vao_err(ctx, vaobj, true, caller);
9387ec681f3Smrg   if (!(*vao))
9397ec681f3Smrg      return false;
9407ec681f3Smrg
9417ec681f3Smrg   if (buffer != 0) {
9427ec681f3Smrg      *vbo = _mesa_lookup_bufferobj(ctx, buffer);
9437ec681f3Smrg      if (!_mesa_handle_bind_buffer_gen(ctx, buffer, vbo, caller))
9447ec681f3Smrg         return false;
9457ec681f3Smrg
9467ec681f3Smrg      if (offset < 0) {
9477ec681f3Smrg         _mesa_error(ctx, GL_INVALID_VALUE,
9487ec681f3Smrg                     "%s(negative offset with non-0 buffer)", caller);
9497ec681f3Smrg         return false;
9507ec681f3Smrg      }
9517ec681f3Smrg   } else {
9527ec681f3Smrg      *vbo = NULL;
9537ec681f3Smrg   }
9547ec681f3Smrg
9557ec681f3Smrg   return true;
9567ec681f3Smrg}
9577ec681f3Smrg
9587ec681f3Smrg
95901e04c3fSmrgvoid GLAPIENTRY
96001e04c3fSmrg_mesa_VertexPointer_no_error(GLint size, GLenum type, GLsizei stride,
96101e04c3fSmrg                             const GLvoid *ptr)
96201e04c3fSmrg{
96301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
96401e04c3fSmrg
9657ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
9667ec681f3Smrg                VERT_ATTRIB_POS, GL_RGBA, 4, size, type, stride,
96701e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
9687117f1b4Smrg}
9697117f1b4Smrg
9707117f1b4Smrg
9717117f1b4Smrgvoid GLAPIENTRY
9727117f1b4Smrg_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
9737117f1b4Smrg{
9747117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
97501e04c3fSmrg
97601e04c3fSmrg   GLenum format = GL_RGBA;
977af69d88dSmrg   GLbitfield legalTypes = (ctx->API == API_OPENGLES)
978af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
979af69d88dSmrg      : (SHORT_BIT | INT_BIT | FLOAT_BIT |
980af69d88dSmrg         DOUBLE_BIT | HALF_BIT |
981af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
982af69d88dSmrg         INT_2_10_10_10_REV_BIT);
9837117f1b4Smrg
9847ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexPointer",
9857ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
9867ec681f3Smrg                                  VERT_ATTRIB_POS, legalTypes, 2, 4, size,
9877ec681f3Smrg                                  type, stride, GL_FALSE, GL_FALSE, GL_FALSE,
9887ec681f3Smrg                                  format, ptr))
98901e04c3fSmrg      return;
99001e04c3fSmrg
9917ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
9927ec681f3Smrg                VERT_ATTRIB_POS, format, 4, size, type, stride,
99301e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
99401e04c3fSmrg}
99501e04c3fSmrg
99601e04c3fSmrg
9977ec681f3Smrgvoid GLAPIENTRY
9987ec681f3Smrg_mesa_VertexArrayVertexOffsetEXT(GLuint vaobj, GLuint buffer, GLint size,
9997ec681f3Smrg                                 GLenum type, GLsizei stride, GLintptr offset)
10007ec681f3Smrg{
10017ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
10027ec681f3Smrg
10037ec681f3Smrg   GLenum format = GL_RGBA;
10047ec681f3Smrg   GLbitfield legalTypes = (ctx->API == API_OPENGLES)
10057ec681f3Smrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
10067ec681f3Smrg      : (SHORT_BIT | INT_BIT | FLOAT_BIT |
10077ec681f3Smrg         DOUBLE_BIT | HALF_BIT |
10087ec681f3Smrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
10097ec681f3Smrg         INT_2_10_10_10_REV_BIT);
10107ec681f3Smrg
10117ec681f3Smrg   struct gl_vertex_array_object* vao;
10127ec681f3Smrg   struct gl_buffer_object* vbo;
10137ec681f3Smrg
10147ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
10157ec681f3Smrg                                &vao, &vbo,
10167ec681f3Smrg                                "glVertexArrayVertexOffsetEXT"))
10177ec681f3Smrg      return;
10187ec681f3Smrg
10197ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayVertexOffsetEXT",
10207ec681f3Smrg                                  vao, vbo,
10217ec681f3Smrg                                  VERT_ATTRIB_POS, legalTypes, 2, 4, size,
10227ec681f3Smrg                                  type, stride, GL_FALSE, GL_FALSE, GL_FALSE,
10237ec681f3Smrg                                  format, (void*) offset))
10247ec681f3Smrg      return;
10257ec681f3Smrg
10267ec681f3Smrg   update_array(ctx, vao, vbo,
10277ec681f3Smrg                VERT_ATTRIB_POS, format, 4, size, type, stride,
10287ec681f3Smrg                GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset);
10297ec681f3Smrg}
10307ec681f3Smrg
10317ec681f3Smrg
103201e04c3fSmrgvoid GLAPIENTRY
103301e04c3fSmrg_mesa_NormalPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr )
103401e04c3fSmrg{
103501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
10367117f1b4Smrg
10377ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
10387ec681f3Smrg                VERT_ATTRIB_NORMAL, GL_RGBA, 3, 3, type, stride, GL_TRUE,
103901e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
10407117f1b4Smrg}
10417117f1b4Smrg
10427117f1b4Smrg
10437117f1b4Smrgvoid GLAPIENTRY
10447117f1b4Smrg_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
10457117f1b4Smrg{
10467117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
104701e04c3fSmrg
104801e04c3fSmrg   GLenum format = GL_RGBA;
1049af69d88dSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
1050af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
1051af69d88dSmrg      : (BYTE_BIT | SHORT_BIT | INT_BIT |
1052af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
1053af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
1054af69d88dSmrg         INT_2_10_10_10_REV_BIT);
1055af69d88dSmrg
105601e04c3fSmrg   if (!validate_array_and_format(ctx, "glNormalPointer",
10577ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
105801e04c3fSmrg                                  VERT_ATTRIB_NORMAL, legalTypes, 3, 3, 3,
105901e04c3fSmrg                                  type, stride, GL_TRUE, GL_FALSE,
10607ec681f3Smrg                                  GL_FALSE, format, ptr))
106101e04c3fSmrg      return;
106201e04c3fSmrg
10637ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
10647ec681f3Smrg                VERT_ATTRIB_NORMAL, format, 3, 3, type, stride, GL_TRUE,
106501e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
106601e04c3fSmrg}
106701e04c3fSmrg
106801e04c3fSmrg
10697ec681f3Smrgvoid GLAPIENTRY
10707ec681f3Smrg_mesa_VertexArrayNormalOffsetEXT(GLuint vaobj, GLuint buffer, GLenum type,
10717ec681f3Smrg                                 GLsizei stride, GLintptr offset)
10727ec681f3Smrg{
10737ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
10747ec681f3Smrg
10757ec681f3Smrg   GLenum format = GL_RGBA;
10767ec681f3Smrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
10777ec681f3Smrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
10787ec681f3Smrg      : (BYTE_BIT | SHORT_BIT | INT_BIT |
10797ec681f3Smrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
10807ec681f3Smrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
10817ec681f3Smrg         INT_2_10_10_10_REV_BIT);
10827ec681f3Smrg
10837ec681f3Smrg   struct gl_vertex_array_object* vao;
10847ec681f3Smrg   struct gl_buffer_object* vbo;
10857ec681f3Smrg
10867ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
10877ec681f3Smrg                                &vao, &vbo,
10887ec681f3Smrg                                "glNormalPointer"))
10897ec681f3Smrg      return;
10907ec681f3Smrg
10917ec681f3Smrg   if (!validate_array_and_format(ctx, "glNormalPointer",
10927ec681f3Smrg                                  vao, vbo,
10937ec681f3Smrg                                  VERT_ATTRIB_NORMAL, legalTypes, 3, 3, 3,
10947ec681f3Smrg                                  type, stride, GL_TRUE, GL_FALSE,
10957ec681f3Smrg                                  GL_FALSE, format, (void*) offset))
10967ec681f3Smrg      return;
10977ec681f3Smrg
10987ec681f3Smrg   update_array(ctx, vao, vbo,
10997ec681f3Smrg                VERT_ATTRIB_NORMAL, format, 3, 3, type, stride, GL_TRUE,
11007ec681f3Smrg                GL_FALSE, GL_FALSE, (void*) offset);
11017ec681f3Smrg}
11027ec681f3Smrg
11037ec681f3Smrg
110401e04c3fSmrgvoid GLAPIENTRY
110501e04c3fSmrg_mesa_ColorPointer_no_error(GLint size, GLenum type, GLsizei stride,
110601e04c3fSmrg                            const GLvoid *ptr)
110701e04c3fSmrg{
110801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
11097117f1b4Smrg
111001e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
11117ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
11127ec681f3Smrg                VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size,
111301e04c3fSmrg                type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
11147117f1b4Smrg}
11157117f1b4Smrg
11167117f1b4Smrg
11177117f1b4Smrgvoid GLAPIENTRY
11187117f1b4Smrg_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
11197117f1b4Smrg{
11207117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
112101e04c3fSmrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3;
112201e04c3fSmrg
112301e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
1124af69d88dSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
1125af69d88dSmrg      ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT)
1126af69d88dSmrg      : (BYTE_BIT | UNSIGNED_BYTE_BIT |
1127af69d88dSmrg         SHORT_BIT | UNSIGNED_SHORT_BIT |
1128af69d88dSmrg         INT_BIT | UNSIGNED_INT_BIT |
1129af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
1130af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
1131af69d88dSmrg         INT_2_10_10_10_REV_BIT);
1132af69d88dSmrg
113301e04c3fSmrg   if (!validate_array_and_format(ctx, "glColorPointer",
11347ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
113501e04c3fSmrg                                  VERT_ATTRIB_COLOR0, legalTypes, sizeMin,
113601e04c3fSmrg                                  BGRA_OR_4, size, type, stride, GL_TRUE,
11377ec681f3Smrg                                  GL_FALSE, GL_FALSE, format, ptr))
113801e04c3fSmrg      return;
113901e04c3fSmrg
11407ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
11417ec681f3Smrg                VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size,
114201e04c3fSmrg                type, stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
114301e04c3fSmrg}
114401e04c3fSmrg
114501e04c3fSmrg
11467ec681f3Smrgvoid GLAPIENTRY
11477ec681f3Smrg_mesa_VertexArrayColorOffsetEXT(GLuint vaobj, GLuint buffer, GLint size,
11487ec681f3Smrg                                GLenum type, GLsizei stride, GLintptr offset)
11497ec681f3Smrg{
11507ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
11517ec681f3Smrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3;
11527ec681f3Smrg
11537ec681f3Smrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
11547ec681f3Smrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
11557ec681f3Smrg      ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT)
11567ec681f3Smrg      : (BYTE_BIT | UNSIGNED_BYTE_BIT |
11577ec681f3Smrg         SHORT_BIT | UNSIGNED_SHORT_BIT |
11587ec681f3Smrg         INT_BIT | UNSIGNED_INT_BIT |
11597ec681f3Smrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
11607ec681f3Smrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
11617ec681f3Smrg         INT_2_10_10_10_REV_BIT);
11627ec681f3Smrg
11637ec681f3Smrg   struct gl_vertex_array_object* vao;
11647ec681f3Smrg   struct gl_buffer_object* vbo;
11657ec681f3Smrg
11667ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
11677ec681f3Smrg                                &vao, &vbo,
11687ec681f3Smrg                                "glVertexArrayColorOffsetEXT"))
11697ec681f3Smrg      return;
11707ec681f3Smrg
11717ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayColorOffsetEXT",
11727ec681f3Smrg                                  vao, vbo,
11737ec681f3Smrg                                  VERT_ATTRIB_COLOR0, legalTypes, sizeMin,
11747ec681f3Smrg                                  BGRA_OR_4, size, type, stride, GL_TRUE,
11757ec681f3Smrg                                  GL_FALSE, GL_FALSE, format, (void*) offset))
11767ec681f3Smrg      return;
11777ec681f3Smrg
11787ec681f3Smrg   update_array(ctx, vao, vbo,
11797ec681f3Smrg                VERT_ATTRIB_COLOR0, format, BGRA_OR_4, size,
11807ec681f3Smrg                type, stride, GL_TRUE, GL_FALSE, GL_FALSE, (void*) offset);
11817ec681f3Smrg}
11827ec681f3Smrg
11837ec681f3Smrg
118401e04c3fSmrgvoid GLAPIENTRY
118501e04c3fSmrg_mesa_FogCoordPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr)
118601e04c3fSmrg{
118701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
1188af69d88dSmrg
11897ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
11907ec681f3Smrg                VERT_ATTRIB_FOG, GL_RGBA, 1, 1, type, stride, GL_FALSE,
119101e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
11927117f1b4Smrg}
11937117f1b4Smrg
11947117f1b4Smrg
11957117f1b4Smrgvoid GLAPIENTRY
1196af69d88dSmrg_mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
11977117f1b4Smrg{
11987117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
11997117f1b4Smrg
120001e04c3fSmrg   GLenum format = GL_RGBA;
120101e04c3fSmrg   const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
120201e04c3fSmrg
120301e04c3fSmrg   if (!validate_array_and_format(ctx, "glFogCoordPointer",
12047ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
120501e04c3fSmrg                                  VERT_ATTRIB_FOG, legalTypes, 1, 1, 1,
120601e04c3fSmrg                                  type, stride, GL_FALSE, GL_FALSE,
12077ec681f3Smrg                                  GL_FALSE, format, ptr))
120801e04c3fSmrg      return;
120901e04c3fSmrg
12107ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
12117ec681f3Smrg                VERT_ATTRIB_FOG, format, 1, 1, type, stride, GL_FALSE,
121201e04c3fSmrg                GL_FALSE, GL_FALSE, ptr);
121301e04c3fSmrg}
121401e04c3fSmrg
121501e04c3fSmrg
12167ec681f3Smrgvoid GLAPIENTRY
12177ec681f3Smrg_mesa_VertexArrayFogCoordOffsetEXT(GLuint vaobj, GLuint buffer, GLenum type,
12187ec681f3Smrg                                   GLsizei stride, GLintptr offset)
12197ec681f3Smrg{
12207ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
12217ec681f3Smrg
12227ec681f3Smrg   GLenum format = GL_RGBA;
12237ec681f3Smrg   const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
12247ec681f3Smrg
12257ec681f3Smrg   struct gl_vertex_array_object* vao;
12267ec681f3Smrg   struct gl_buffer_object* vbo;
12277ec681f3Smrg
12287ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
12297ec681f3Smrg                                &vao, &vbo,
12307ec681f3Smrg                                "glVertexArrayFogCoordOffsetEXT"))
12317ec681f3Smrg      return;
12327ec681f3Smrg
12337ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayFogCoordOffsetEXT",
12347ec681f3Smrg                                  vao, vbo,
12357ec681f3Smrg                                  VERT_ATTRIB_FOG, legalTypes, 1, 1, 1,
12367ec681f3Smrg                                  type, stride, GL_FALSE, GL_FALSE,
12377ec681f3Smrg                                  GL_FALSE, format, (void*) offset))
12387ec681f3Smrg      return;
12397ec681f3Smrg
12407ec681f3Smrg   update_array(ctx, vao, vbo,
12417ec681f3Smrg                VERT_ATTRIB_FOG, format, 1, 1, type, stride, GL_FALSE,
12427ec681f3Smrg                GL_FALSE, GL_FALSE, (void*) offset);
12437ec681f3Smrg}
12447ec681f3Smrg
12457ec681f3Smrg
124601e04c3fSmrgvoid GLAPIENTRY
124701e04c3fSmrg_mesa_IndexPointer_no_error(GLenum type, GLsizei stride, const GLvoid *ptr)
124801e04c3fSmrg{
124901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
1250af69d88dSmrg
12517ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
12527ec681f3Smrg                VERT_ATTRIB_COLOR_INDEX, GL_RGBA, 1, 1, type, stride,
125301e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
12547117f1b4Smrg}
12557117f1b4Smrg
12567117f1b4Smrg
12577117f1b4Smrgvoid GLAPIENTRY
12587117f1b4Smrg_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
12597117f1b4Smrg{
12607117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
12617117f1b4Smrg
126201e04c3fSmrg   GLenum format = GL_RGBA;
126301e04c3fSmrg   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT |
126401e04c3fSmrg                                     FLOAT_BIT | DOUBLE_BIT);
126501e04c3fSmrg
126601e04c3fSmrg   if (!validate_array_and_format(ctx, "glIndexPointer",
12677ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
126801e04c3fSmrg                                  VERT_ATTRIB_COLOR_INDEX,
126901e04c3fSmrg                                  legalTypes, 1, 1, 1, type, stride,
12707ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format, ptr))
127101e04c3fSmrg      return;
127201e04c3fSmrg
12737ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
12747ec681f3Smrg                VERT_ATTRIB_COLOR_INDEX, format, 1, 1, type, stride,
127501e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
127601e04c3fSmrg}
127701e04c3fSmrg
127801e04c3fSmrg
12797ec681f3Smrgvoid GLAPIENTRY
12807ec681f3Smrg_mesa_VertexArrayIndexOffsetEXT(GLuint vaobj, GLuint buffer, GLenum type,
12817ec681f3Smrg                                GLsizei stride, GLintptr offset)
12827ec681f3Smrg{
12837ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
12847ec681f3Smrg
12857ec681f3Smrg   GLenum format = GL_RGBA;
12867ec681f3Smrg   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT |
12877ec681f3Smrg                                     FLOAT_BIT | DOUBLE_BIT);
12887ec681f3Smrg
12897ec681f3Smrg   struct gl_vertex_array_object* vao;
12907ec681f3Smrg   struct gl_buffer_object* vbo;
12917ec681f3Smrg
12927ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
12937ec681f3Smrg                                &vao, &vbo,
12947ec681f3Smrg                                "glVertexArrayIndexOffsetEXT"))
12957ec681f3Smrg      return;
12967ec681f3Smrg
12977ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayIndexOffsetEXT",
12987ec681f3Smrg                                  vao, vbo,
12997ec681f3Smrg                                  VERT_ATTRIB_COLOR_INDEX,
13007ec681f3Smrg                                  legalTypes, 1, 1, 1, type, stride,
13017ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format, (void*) offset))
13027ec681f3Smrg      return;
13037ec681f3Smrg
13047ec681f3Smrg   update_array(ctx, vao, vbo,
13057ec681f3Smrg                VERT_ATTRIB_COLOR_INDEX, format, 1, 1, type, stride,
13067ec681f3Smrg                GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset);
13077ec681f3Smrg}
13087ec681f3Smrg
13097ec681f3Smrg
131001e04c3fSmrgvoid GLAPIENTRY
131101e04c3fSmrg_mesa_SecondaryColorPointer_no_error(GLint size, GLenum type,
131201e04c3fSmrg                                     GLsizei stride, const GLvoid *ptr)
131301e04c3fSmrg{
131401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
1315af69d88dSmrg
131601e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
13177ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
13187ec681f3Smrg                VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type,
131901e04c3fSmrg                stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
13207117f1b4Smrg}
13217117f1b4Smrg
13227117f1b4Smrg
13237117f1b4Smrgvoid GLAPIENTRY
1324af69d88dSmrg_mesa_SecondaryColorPointer(GLint size, GLenum type,
13257117f1b4Smrg			       GLsizei stride, const GLvoid *ptr)
13267117f1b4Smrg{
132701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
132801e04c3fSmrg
132901e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
13303464ebd5Sriastradh   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
13313464ebd5Sriastradh                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
13323464ebd5Sriastradh                                  INT_BIT | UNSIGNED_INT_BIT |
1333af69d88dSmrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
1334af69d88dSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
1335af69d88dSmrg                                  INT_2_10_10_10_REV_BIT);
13367117f1b4Smrg
133701e04c3fSmrg   if (!validate_array_and_format(ctx, "glSecondaryColorPointer",
13387ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
133901e04c3fSmrg                                  VERT_ATTRIB_COLOR1, legalTypes, 3,
134001e04c3fSmrg                                  BGRA_OR_4, size, type, stride,
13417ec681f3Smrg                                  GL_TRUE, GL_FALSE, GL_FALSE, format, ptr))
134201e04c3fSmrg      return;
134301e04c3fSmrg
13447ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
13457ec681f3Smrg                VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type,
134601e04c3fSmrg                stride, GL_TRUE, GL_FALSE, GL_FALSE, ptr);
134701e04c3fSmrg}
134801e04c3fSmrg
134901e04c3fSmrg
13507ec681f3Smrgvoid GLAPIENTRY
13517ec681f3Smrg_mesa_VertexArraySecondaryColorOffsetEXT(GLuint vaobj, GLuint buffer, GLint size,
13527ec681f3Smrg                                         GLenum type, GLsizei stride, GLintptr offset)
13537ec681f3Smrg{
13547ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
13557ec681f3Smrg
13567ec681f3Smrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
13577ec681f3Smrg   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
13587ec681f3Smrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
13597ec681f3Smrg                                  INT_BIT | UNSIGNED_INT_BIT |
13607ec681f3Smrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
13617ec681f3Smrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
13627ec681f3Smrg                                  INT_2_10_10_10_REV_BIT);
13637ec681f3Smrg
13647ec681f3Smrg   struct gl_vertex_array_object* vao;
13657ec681f3Smrg   struct gl_buffer_object* vbo;
13667ec681f3Smrg
13677ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
13687ec681f3Smrg                                &vao, &vbo,
13697ec681f3Smrg                                "glVertexArraySecondaryColorOffsetEXT"))
13707ec681f3Smrg      return;
13717ec681f3Smrg
13727ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArraySecondaryColorOffsetEXT",
13737ec681f3Smrg                                  vao, vbo,
13747ec681f3Smrg                                  VERT_ATTRIB_COLOR1, legalTypes, 3,
13757ec681f3Smrg                                  BGRA_OR_4, size, type, stride,
13767ec681f3Smrg                                  GL_TRUE, GL_FALSE, GL_FALSE, format, (void*) offset))
13777ec681f3Smrg      return;
13787ec681f3Smrg
13797ec681f3Smrg   update_array(ctx, vao, vbo,
13807ec681f3Smrg                VERT_ATTRIB_COLOR1, format, BGRA_OR_4, size, type,
13817ec681f3Smrg                stride, GL_TRUE, GL_FALSE, GL_FALSE, (void*) offset);
13827ec681f3Smrg}
13837ec681f3Smrg
13847ec681f3Smrg
138501e04c3fSmrgvoid GLAPIENTRY
138601e04c3fSmrg_mesa_TexCoordPointer_no_error(GLint size, GLenum type, GLsizei stride,
138701e04c3fSmrg                               const GLvoid *ptr)
138801e04c3fSmrg{
138901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
139001e04c3fSmrg   const GLuint unit = ctx->Array.ActiveTexture;
1391af69d88dSmrg
13927ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
13937ec681f3Smrg                VERT_ATTRIB_TEX(unit), GL_RGBA, 4, size, type,
139401e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
13957117f1b4Smrg}
13967117f1b4Smrg
13977117f1b4Smrg
13987117f1b4Smrgvoid GLAPIENTRY
13997117f1b4Smrg_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
14007117f1b4Smrg                      const GLvoid *ptr)
14017117f1b4Smrg{
14027117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
140301e04c3fSmrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1;
140401e04c3fSmrg   const GLuint unit = ctx->Array.ActiveTexture;
140501e04c3fSmrg
140601e04c3fSmrg   GLenum format = GL_RGBA;
140701e04c3fSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
1408af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
1409af69d88dSmrg      : (SHORT_BIT | INT_BIT |
1410af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
1411af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
1412af69d88dSmrg         INT_2_10_10_10_REV_BIT);
14137117f1b4Smrg
141401e04c3fSmrg   if (!validate_array_and_format(ctx, "glTexCoordPointer",
14157ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
141601e04c3fSmrg                                  VERT_ATTRIB_TEX(unit), legalTypes,
141701e04c3fSmrg                                  sizeMin, 4, size, type, stride,
14187ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format, ptr))
141901e04c3fSmrg      return;
142001e04c3fSmrg
14217ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
14227ec681f3Smrg                VERT_ATTRIB_TEX(unit), format, 4, size, type,
142301e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
142401e04c3fSmrg}
142501e04c3fSmrg
142601e04c3fSmrg
14277ec681f3Smrgvoid GLAPIENTRY
14287ec681f3Smrg_mesa_VertexArrayTexCoordOffsetEXT(GLuint vaobj, GLuint buffer, GLint size,
14297ec681f3Smrg                                   GLenum type, GLsizei stride, GLintptr offset)
14307ec681f3Smrg{
14317ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
14327ec681f3Smrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1;
14337ec681f3Smrg   const GLuint unit = ctx->Array.ActiveTexture;
14347ec681f3Smrg
14357ec681f3Smrg   GLenum format = GL_RGBA;
14367ec681f3Smrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
14377ec681f3Smrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
14387ec681f3Smrg      : (SHORT_BIT | INT_BIT |
14397ec681f3Smrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
14407ec681f3Smrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
14417ec681f3Smrg         INT_2_10_10_10_REV_BIT);
14427ec681f3Smrg
14437ec681f3Smrg   struct gl_vertex_array_object* vao;
14447ec681f3Smrg   struct gl_buffer_object* vbo;
14457ec681f3Smrg
14467ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
14477ec681f3Smrg                                &vao, &vbo,
14487ec681f3Smrg                                "glVertexArrayTexCoordOffsetEXT"))
14497ec681f3Smrg      return;
14507ec681f3Smrg
14517ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayTexCoordOffsetEXT",
14527ec681f3Smrg                                  vao, vbo,
14537ec681f3Smrg                                  VERT_ATTRIB_TEX(unit), legalTypes,
14547ec681f3Smrg                                  sizeMin, 4, size, type, stride,
14557ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format, (void*) offset))
14567ec681f3Smrg      return;
14577ec681f3Smrg
14587ec681f3Smrg   update_array(ctx, vao, vbo,
14597ec681f3Smrg                VERT_ATTRIB_TEX(unit), format, 4, size, type,
14607ec681f3Smrg                stride, GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset);
14617ec681f3Smrg}
14627ec681f3Smrg
14637ec681f3Smrg
14647ec681f3Smrgvoid GLAPIENTRY
14657ec681f3Smrg_mesa_VertexArrayMultiTexCoordOffsetEXT(GLuint vaobj, GLuint buffer, GLenum texunit,
14667ec681f3Smrg                                        GLint size, GLenum type, GLsizei stride,
14677ec681f3Smrg                                        GLintptr offset)
14687ec681f3Smrg{
14697ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
14707ec681f3Smrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1;
14717ec681f3Smrg   const GLuint unit = texunit - GL_TEXTURE0;
14727ec681f3Smrg
14737ec681f3Smrg   GLenum format = GL_RGBA;
14747ec681f3Smrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
14757ec681f3Smrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
14767ec681f3Smrg      : (SHORT_BIT | INT_BIT |
14777ec681f3Smrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
14787ec681f3Smrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
14797ec681f3Smrg         INT_2_10_10_10_REV_BIT);
14807ec681f3Smrg
14817ec681f3Smrg   struct gl_vertex_array_object* vao;
14827ec681f3Smrg   struct gl_buffer_object* vbo;
14837ec681f3Smrg
14847ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
14857ec681f3Smrg                                &vao, &vbo,
14867ec681f3Smrg                                "glVertexArrayMultiTexCoordOffsetEXT"))
14877ec681f3Smrg      return;
14887ec681f3Smrg
14897ec681f3Smrg   if (unit >= ctx->Const.MaxCombinedTextureImageUnits) {
14907ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexArrayMultiTexCoordOffsetEXT(texunit=%d)",
14917ec681f3Smrg         texunit);
14927ec681f3Smrg      return;
14937ec681f3Smrg   }
14947ec681f3Smrg
14957ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayMultiTexCoordOffsetEXT",
14967ec681f3Smrg                                  vao, vbo,
14977ec681f3Smrg                                  VERT_ATTRIB_TEX(unit), legalTypes,
14987ec681f3Smrg                                  sizeMin, 4, size, type, stride,
14997ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format, (void*) offset))
15007ec681f3Smrg      return;
15017ec681f3Smrg
15027ec681f3Smrg   update_array(ctx, vao, vbo,
15037ec681f3Smrg                VERT_ATTRIB_TEX(unit), format, 4, size, type,
15047ec681f3Smrg                stride, GL_FALSE, GL_FALSE, GL_FALSE, (void*) offset);
15057ec681f3Smrg}
15067ec681f3Smrg
15077ec681f3Smrg
150801e04c3fSmrgvoid GLAPIENTRY
150901e04c3fSmrg_mesa_EdgeFlagPointer_no_error(GLsizei stride, const GLvoid *ptr)
151001e04c3fSmrg{
151101e04c3fSmrg   /* this is the same type that glEdgeFlag uses */
151201e04c3fSmrg   const GLboolean integer = GL_FALSE;
151301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
1514cdc920a0Smrg
15157ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
15167ec681f3Smrg                VERT_ATTRIB_EDGEFLAG, GL_RGBA, 1, 1, GL_UNSIGNED_BYTE,
151701e04c3fSmrg                stride, GL_FALSE, integer, GL_FALSE, ptr);
15187117f1b4Smrg}
15197117f1b4Smrg
15207117f1b4Smrg
15217117f1b4Smrgvoid GLAPIENTRY
15227117f1b4Smrg_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
15237117f1b4Smrg{
1524af69d88dSmrg   /* this is the same type that glEdgeFlag uses */
1525af69d88dSmrg   const GLboolean integer = GL_FALSE;
15267117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
15277117f1b4Smrg
152801e04c3fSmrg   GLenum format = GL_RGBA;
152901e04c3fSmrg   const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
153001e04c3fSmrg
153101e04c3fSmrg   if (!validate_array_and_format(ctx, "glEdgeFlagPointer",
15327ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
153301e04c3fSmrg                                  VERT_ATTRIB_EDGEFLAG, legalTypes,
153401e04c3fSmrg                                  1, 1, 1, GL_UNSIGNED_BYTE, stride,
15357ec681f3Smrg                                  GL_FALSE, integer, GL_FALSE, format, ptr))
153601e04c3fSmrg      return;
1537af69d88dSmrg
15387ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
15397ec681f3Smrg                VERT_ATTRIB_EDGEFLAG, format, 1, 1, GL_UNSIGNED_BYTE,
154001e04c3fSmrg                stride, GL_FALSE, integer, GL_FALSE, ptr);
15417117f1b4Smrg}
15427117f1b4Smrg
15437117f1b4Smrg
15447ec681f3Smrgvoid GLAPIENTRY
15457ec681f3Smrg_mesa_VertexArrayEdgeFlagOffsetEXT(GLuint vaobj, GLuint buffer, GLsizei stride,
15467ec681f3Smrg                                   GLintptr offset)
15477ec681f3Smrg{
15487ec681f3Smrg   /* this is the same type that glEdgeFlag uses */
15497ec681f3Smrg   const GLboolean integer = GL_FALSE;
15507ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
15517ec681f3Smrg
15527ec681f3Smrg   GLenum format = GL_RGBA;
15537ec681f3Smrg   const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
15547ec681f3Smrg
15557ec681f3Smrg   struct gl_vertex_array_object* vao;
15567ec681f3Smrg   struct gl_buffer_object* vbo;
15577ec681f3Smrg
15587ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
15597ec681f3Smrg                                &vao, &vbo,
15607ec681f3Smrg                                "glVertexArrayEdgeFlagOffsetEXT"))
15617ec681f3Smrg      return;
15627ec681f3Smrg
15637ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayEdgeFlagOffsetEXT",
15647ec681f3Smrg                                  vao, vbo,
15657ec681f3Smrg                                  VERT_ATTRIB_EDGEFLAG, legalTypes,
15667ec681f3Smrg                                  1, 1, 1, GL_UNSIGNED_BYTE, stride,
15677ec681f3Smrg                                  GL_FALSE, integer, GL_FALSE, format, (void*) offset))
15687ec681f3Smrg      return;
15697ec681f3Smrg
15707ec681f3Smrg   update_array(ctx, vao, vbo,
15717ec681f3Smrg                VERT_ATTRIB_EDGEFLAG, format, 1, 1, GL_UNSIGNED_BYTE,
15727ec681f3Smrg                stride, GL_FALSE, integer, GL_FALSE, (void*) offset);
15737ec681f3Smrg}
15747ec681f3Smrg
15757ec681f3Smrg
1576c1f859d4Smrgvoid GLAPIENTRY
157701e04c3fSmrg_mesa_PointSizePointerOES_no_error(GLenum type, GLsizei stride,
157801e04c3fSmrg                                   const GLvoid *ptr)
1579c1f859d4Smrg{
1580c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
1581af69d88dSmrg
15827ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
15837ec681f3Smrg                VERT_ATTRIB_POINT_SIZE, GL_RGBA, 1, 1, type, stride,
158401e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
158501e04c3fSmrg}
158601e04c3fSmrg
158701e04c3fSmrg
158801e04c3fSmrgvoid GLAPIENTRY
158901e04c3fSmrg_mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr)
159001e04c3fSmrg{
159101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
1592c1f859d4Smrg
159301e04c3fSmrg   GLenum format = GL_RGBA;
15943464ebd5Sriastradh   if (ctx->API != API_OPENGLES) {
15953464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION,
15963464ebd5Sriastradh                  "glPointSizePointer(ES 1.x only)");
1597c1f859d4Smrg      return;
1598c1f859d4Smrg   }
159901e04c3fSmrg
160001e04c3fSmrg   const GLbitfield legalTypes = (FLOAT_BIT | FIXED_ES_BIT);
160101e04c3fSmrg
160201e04c3fSmrg   if (!validate_array_and_format(ctx, "glPointSizePointer",
16037ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
160401e04c3fSmrg                                  VERT_ATTRIB_POINT_SIZE, legalTypes,
160501e04c3fSmrg                                  1, 1, 1, type, stride, GL_FALSE, GL_FALSE,
16067ec681f3Smrg                                  GL_FALSE, format, ptr))
160701e04c3fSmrg      return;
160801e04c3fSmrg
16097ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
16107ec681f3Smrg                VERT_ATTRIB_POINT_SIZE, format, 1, 1, type, stride,
161101e04c3fSmrg                GL_FALSE, GL_FALSE, GL_FALSE, ptr);
161201e04c3fSmrg}
161301e04c3fSmrg
161401e04c3fSmrg
161501e04c3fSmrgvoid GLAPIENTRY
161601e04c3fSmrg_mesa_VertexAttribPointer_no_error(GLuint index, GLint size, GLenum type,
161701e04c3fSmrg                                   GLboolean normalized,
161801e04c3fSmrg                                   GLsizei stride, const GLvoid *ptr)
161901e04c3fSmrg{
162001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
162101e04c3fSmrg
162201e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
16237ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
16247ec681f3Smrg                VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4,
162501e04c3fSmrg                size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr);
1626c1f859d4Smrg}
1627c1f859d4Smrg
1628c1f859d4Smrg
16294a49301eSmrg/**
16304a49301eSmrg * Set a generic vertex attribute array.
16314a49301eSmrg * Note that these arrays DO NOT alias the conventional GL vertex arrays
16324a49301eSmrg * (position, normal, color, fog, texcoord, etc).
16334a49301eSmrg */
16347117f1b4Smrgvoid GLAPIENTRY
1635af69d88dSmrg_mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type,
16367117f1b4Smrg                             GLboolean normalized,
16377117f1b4Smrg                             GLsizei stride, const GLvoid *ptr)
16387117f1b4Smrg{
163901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
164001e04c3fSmrg
164101e04c3fSmrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
164201e04c3fSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
164301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(idx)");
164401e04c3fSmrg      return;
164501e04c3fSmrg   }
164601e04c3fSmrg
16473464ebd5Sriastradh   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
16483464ebd5Sriastradh                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
16493464ebd5Sriastradh                                  INT_BIT | UNSIGNED_INT_BIT |
16503464ebd5Sriastradh                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
1651af69d88dSmrg                                  FIXED_ES_BIT | FIXED_GL_BIT |
1652af69d88dSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
1653af69d88dSmrg                                  INT_2_10_10_10_REV_BIT |
1654af69d88dSmrg                                  UNSIGNED_INT_10F_11F_11F_REV_BIT);
16557117f1b4Smrg
165601e04c3fSmrg   if (!validate_array_and_format(ctx, "glVertexAttribPointer",
16577ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
165801e04c3fSmrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
165901e04c3fSmrg                                  1, BGRA_OR_4, size, type, stride,
16607ec681f3Smrg                                  normalized, GL_FALSE, GL_FALSE, format, ptr))
16617117f1b4Smrg      return;
16627117f1b4Smrg
16637ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
16647ec681f3Smrg                VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4,
166501e04c3fSmrg                size, type, stride, normalized, GL_FALSE, GL_FALSE, ptr);
166601e04c3fSmrg}
166701e04c3fSmrg
166801e04c3fSmrg
16697ec681f3Smrgvoid GLAPIENTRY
16707ec681f3Smrg_mesa_VertexArrayVertexAttribOffsetEXT(GLuint vaobj, GLuint buffer, GLuint index, GLint size,
16717ec681f3Smrg                                       GLenum type, GLboolean normalized,
16727ec681f3Smrg                                       GLsizei stride, GLintptr offset)
16737ec681f3Smrg{
16747ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
16757ec681f3Smrg   GLenum format = get_array_format(ctx, BGRA_OR_4, &size);
16767ec681f3Smrg   struct gl_vertex_array_object* vao;
16777ec681f3Smrg   struct gl_buffer_object* vbo;
16787ec681f3Smrg
16797ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
16807ec681f3Smrg                                &vao, &vbo,
16817ec681f3Smrg                                "glVertexArrayVertexAttribOffsetEXT"))
16827ec681f3Smrg      return;
16837ec681f3Smrg
16847ec681f3Smrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
16857ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexArrayVertexAttribOffsetEXT(idx)");
16867ec681f3Smrg      return;
16877ec681f3Smrg   }
16887ec681f3Smrg
16897ec681f3Smrg   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
16907ec681f3Smrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
16917ec681f3Smrg                                  INT_BIT | UNSIGNED_INT_BIT |
16927ec681f3Smrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
16937ec681f3Smrg                                  FIXED_ES_BIT | FIXED_GL_BIT |
16947ec681f3Smrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
16957ec681f3Smrg                                  INT_2_10_10_10_REV_BIT |
16967ec681f3Smrg                                  UNSIGNED_INT_10F_11F_11F_REV_BIT);
16977ec681f3Smrg
16987ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayVertexAttribOffsetEXT",
16997ec681f3Smrg                                  vao, vbo,
17007ec681f3Smrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
17017ec681f3Smrg                                  1, BGRA_OR_4, size, type, stride,
17027ec681f3Smrg                                  normalized, GL_FALSE, GL_FALSE, format, (void*) offset))
17037ec681f3Smrg      return;
17047ec681f3Smrg
17057ec681f3Smrg   update_array(ctx, vao, vbo,
17067ec681f3Smrg                VERT_ATTRIB_GENERIC(index), format, BGRA_OR_4,
17077ec681f3Smrg                size, type, stride, normalized, GL_FALSE, GL_FALSE, (void*) offset);
17087ec681f3Smrg}
17097ec681f3Smrg
17107ec681f3Smrg
17117ec681f3Smrgvoid GLAPIENTRY
17127ec681f3Smrg_mesa_VertexArrayVertexAttribLOffsetEXT(GLuint vaobj, GLuint buffer, GLuint index, GLint size,
17137ec681f3Smrg                                        GLenum type, GLsizei stride, GLintptr offset)
17147ec681f3Smrg{
17157ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
17167ec681f3Smrg   GLenum format = GL_RGBA;
17177ec681f3Smrg   struct gl_vertex_array_object* vao;
17187ec681f3Smrg   struct gl_buffer_object* vbo;
17197ec681f3Smrg
17207ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
17217ec681f3Smrg                                &vao, &vbo,
17227ec681f3Smrg                                "glVertexArrayVertexAttribLOffsetEXT"))
17237ec681f3Smrg      return;
17247ec681f3Smrg
17257ec681f3Smrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
17267ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexArrayVertexAttribLOffsetEXT(idx)");
17277ec681f3Smrg      return;
17287ec681f3Smrg   }
17297ec681f3Smrg
17307ec681f3Smrg   const GLbitfield legalTypes = DOUBLE_BIT;
17317ec681f3Smrg
17327ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayVertexAttribLOffsetEXT",
17337ec681f3Smrg                                  vao, vbo,
17347ec681f3Smrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
17357ec681f3Smrg                                  1, 4, size, type, stride,
17367ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_TRUE, format, (void*) offset))
17377ec681f3Smrg      return;
17387ec681f3Smrg
17397ec681f3Smrg   update_array(ctx, vao, vbo,
17407ec681f3Smrg                VERT_ATTRIB_GENERIC(index), format, 4,
17417ec681f3Smrg                size, type, stride, GL_FALSE, GL_FALSE, GL_TRUE, (void*) offset);
17427ec681f3Smrg}
17437ec681f3Smrg
17447ec681f3Smrg
174501e04c3fSmrgvoid GLAPIENTRY
174601e04c3fSmrg_mesa_VertexAttribIPointer_no_error(GLuint index, GLint size, GLenum type,
174701e04c3fSmrg                                    GLsizei stride, const GLvoid *ptr)
174801e04c3fSmrg{
174901e04c3fSmrg   const GLboolean normalized = GL_FALSE;
175001e04c3fSmrg   const GLboolean integer = GL_TRUE;
175101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
175201e04c3fSmrg
17537ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
17547ec681f3Smrg                VERT_ATTRIB_GENERIC(index), GL_RGBA, 4,  size, type,
175501e04c3fSmrg                stride, normalized, integer, GL_FALSE, ptr);
17563464ebd5Sriastradh}
17573464ebd5Sriastradh
17583464ebd5Sriastradh
17593464ebd5Sriastradh/**
17603464ebd5Sriastradh * GL_EXT_gpu_shader4 / GL 3.0.
17613464ebd5Sriastradh * Set an integer-valued vertex attribute array.
17623464ebd5Sriastradh * Note that these arrays DO NOT alias the conventional GL vertex arrays
17633464ebd5Sriastradh * (position, normal, color, fog, texcoord, etc).
17643464ebd5Sriastradh */
17653464ebd5Sriastradhvoid GLAPIENTRY
17663464ebd5Sriastradh_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
17673464ebd5Sriastradh                           GLsizei stride, const GLvoid *ptr)
17683464ebd5Sriastradh{
17693464ebd5Sriastradh   const GLboolean normalized = GL_FALSE;
17703464ebd5Sriastradh   const GLboolean integer = GL_TRUE;
17713464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
17723464ebd5Sriastradh
177301e04c3fSmrg   GLenum format = GL_RGBA;
1774af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
17753464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)");
17763464ebd5Sriastradh      return;
17777117f1b4Smrg   }
17787117f1b4Smrg
177901e04c3fSmrg   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
178001e04c3fSmrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
178101e04c3fSmrg                                  INT_BIT | UNSIGNED_INT_BIT);
178201e04c3fSmrg
178301e04c3fSmrg   if (!validate_array_and_format(ctx, "glVertexAttribIPointer",
17847ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
178501e04c3fSmrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
178601e04c3fSmrg                                  1, 4, size, type, stride,
17877ec681f3Smrg                                  normalized, integer, GL_FALSE, format, ptr))
178801e04c3fSmrg      return;
178901e04c3fSmrg
17907ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
17917ec681f3Smrg                VERT_ATTRIB_GENERIC(index), format, 4,  size, type,
179201e04c3fSmrg                stride, normalized, integer, GL_FALSE, ptr);
17933464ebd5Sriastradh}
17943464ebd5Sriastradh
17953464ebd5Sriastradh
179601e04c3fSmrgvoid GLAPIENTRY
179701e04c3fSmrg_mesa_VertexAttribLPointer_no_error(GLuint index, GLint size, GLenum type,
179801e04c3fSmrg                                    GLsizei stride, const GLvoid *ptr)
179901e04c3fSmrg{
180001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
180101e04c3fSmrg
18027ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
18037ec681f3Smrg                VERT_ATTRIB_GENERIC(index), GL_RGBA, 4, size, type,
180401e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr);
180501e04c3fSmrg}
180601e04c3fSmrg
18073464ebd5Sriastradh
18087ec681f3Smrgvoid GLAPIENTRY
18097ec681f3Smrg_mesa_VertexArrayVertexAttribIOffsetEXT(GLuint vaobj, GLuint buffer, GLuint index, GLint size,
18107ec681f3Smrg                                        GLenum type, GLsizei stride, GLintptr offset)
18117ec681f3Smrg{
18127ec681f3Smrg   const GLboolean normalized = GL_FALSE;
18137ec681f3Smrg   const GLboolean integer = GL_TRUE;
18147ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
18157ec681f3Smrg   GLenum format = GL_RGBA;
18167ec681f3Smrg
18177ec681f3Smrg   struct gl_vertex_array_object* vao;
18187ec681f3Smrg   struct gl_buffer_object* vbo;
18197ec681f3Smrg
18207ec681f3Smrg   if (!_lookup_vao_and_vbo_dsa(ctx, vaobj, buffer, offset,
18217ec681f3Smrg                                &vao, &vbo,
18227ec681f3Smrg                                "glVertexArrayVertexAttribIOffsetEXT"))
18237ec681f3Smrg      return;
18247ec681f3Smrg
18257ec681f3Smrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
18267ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexArrayVertexAttribIOffsetEXT(index)");
18277ec681f3Smrg      return;
18287ec681f3Smrg   }
18297ec681f3Smrg
18307ec681f3Smrg   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
18317ec681f3Smrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
18327ec681f3Smrg                                  INT_BIT | UNSIGNED_INT_BIT);
18337ec681f3Smrg
18347ec681f3Smrg   if (!validate_array_and_format(ctx, "glVertexArrayVertexAttribIOffsetEXT",
18357ec681f3Smrg                                  vao, vbo,
18367ec681f3Smrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
18377ec681f3Smrg                                  1, 4, size, type, stride,
18387ec681f3Smrg                                  normalized, integer, GL_FALSE, format, (void*) offset))
18397ec681f3Smrg      return;
18407ec681f3Smrg
18417ec681f3Smrg   update_array(ctx, vao, vbo,
18427ec681f3Smrg                VERT_ATTRIB_GENERIC(index), format, 4,  size, type,
18437ec681f3Smrg                stride, normalized, integer, GL_FALSE, (void*) offset);
18447ec681f3Smrg}
18457ec681f3Smrg
18467ec681f3Smrg
18473464ebd5Sriastradhvoid GLAPIENTRY
184801e04c3fSmrg_mesa_VertexAttribLPointer(GLuint index, GLint size, GLenum type,
184901e04c3fSmrg                           GLsizei stride, const GLvoid *ptr)
18503464ebd5Sriastradh{
18513464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
18523464ebd5Sriastradh
185301e04c3fSmrg   GLenum format = GL_RGBA;
1854af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
185501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribLPointer(index)");
18567117f1b4Smrg      return;
18577117f1b4Smrg   }
18587117f1b4Smrg
185901e04c3fSmrg   const GLbitfield legalTypes = DOUBLE_BIT;
186001e04c3fSmrg
186101e04c3fSmrg   if (!validate_array_and_format(ctx, "glVertexAttribLPointer",
18627ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
186301e04c3fSmrg                                  VERT_ATTRIB_GENERIC(index), legalTypes,
186401e04c3fSmrg                                  1, 4, size, type, stride,
18657ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_TRUE, format, ptr))
186601e04c3fSmrg      return;
186701e04c3fSmrg
18687ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
18697ec681f3Smrg                VERT_ATTRIB_GENERIC(index), format, 4, size, type,
187001e04c3fSmrg                stride, GL_FALSE, GL_FALSE, GL_TRUE, ptr);
187101e04c3fSmrg}
187201e04c3fSmrg
1873af69d88dSmrg
187401e04c3fSmrgvoid
1875b9abf16eSmaya_mesa_enable_vertex_array_attribs(struct gl_context *ctx,
1876b9abf16eSmaya                                  struct gl_vertex_array_object *vao,
1877b9abf16eSmaya                                  GLbitfield attrib_bits)
187801e04c3fSmrg{
1879b9abf16eSmaya   assert((attrib_bits & ~VERT_BIT_ALL) == 0);
188001e04c3fSmrg   assert(!vao->SharedAndImmutable);
18813464ebd5Sriastradh
1882b9abf16eSmaya   /* Only work on bits that are disabled */
1883b9abf16eSmaya   attrib_bits &= ~vao->Enabled;
1884b9abf16eSmaya   if (attrib_bits) {
1885af69d88dSmrg      /* was disabled, now being enabled */
1886b9abf16eSmaya      vao->Enabled |= attrib_bits;
1887b9abf16eSmaya      vao->NewArrays |= attrib_bits;
18887ec681f3Smrg      vao->NonDefaultStateMask |= attrib_bits;
188901e04c3fSmrg
189001e04c3fSmrg      /* Update the map mode if needed */
1891b9abf16eSmaya      if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0))
189201e04c3fSmrg         update_attribute_map_mode(ctx, vao);
18937ec681f3Smrg
18947ec681f3Smrg      vao->_EnabledWithMapMode =
18957ec681f3Smrg         _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled);
189601e04c3fSmrg   }
189701e04c3fSmrg}
189801e04c3fSmrg
189901e04c3fSmrgstatic void
190001e04c3fSmrgenable_vertex_array_attrib(struct gl_context *ctx,
190101e04c3fSmrg                           struct gl_vertex_array_object *vao,
190201e04c3fSmrg                           GLuint index,
190301e04c3fSmrg                           const char *func)
190401e04c3fSmrg{
190501e04c3fSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
190601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
190701e04c3fSmrg      return;
1908af69d88dSmrg   }
190901e04c3fSmrg
191001e04c3fSmrg   _mesa_enable_vertex_array_attrib(ctx, vao, VERT_ATTRIB_GENERIC(index));
19113464ebd5Sriastradh}
19123464ebd5Sriastradh
19133464ebd5Sriastradh
19143464ebd5Sriastradhvoid GLAPIENTRY
191501e04c3fSmrg_mesa_EnableVertexAttribArray(GLuint index)
191601e04c3fSmrg{
191701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
191801e04c3fSmrg   enable_vertex_array_attrib(ctx, ctx->Array.VAO, index,
191901e04c3fSmrg                              "glEnableVertexAttribArray");
192001e04c3fSmrg}
192101e04c3fSmrg
192201e04c3fSmrg
192301e04c3fSmrgvoid GLAPIENTRY
192401e04c3fSmrg_mesa_EnableVertexAttribArray_no_error(GLuint index)
192501e04c3fSmrg{
192601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
192701e04c3fSmrg   _mesa_enable_vertex_array_attrib(ctx, ctx->Array.VAO,
192801e04c3fSmrg                                    VERT_ATTRIB_GENERIC(index));
192901e04c3fSmrg}
193001e04c3fSmrg
193101e04c3fSmrg
193201e04c3fSmrgvoid GLAPIENTRY
193301e04c3fSmrg_mesa_EnableVertexArrayAttrib(GLuint vaobj, GLuint index)
19343464ebd5Sriastradh{
193501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
1936af69d88dSmrg   struct gl_vertex_array_object *vao;
193701e04c3fSmrg
193801e04c3fSmrg   /* The ARB_direct_state_access specification says:
193901e04c3fSmrg    *
194001e04c3fSmrg    *   "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
194101e04c3fSmrg    *    and DisableVertexArrayAttrib if <vaobj> is not
194201e04c3fSmrg    *    [compatibility profile: zero or] the name of an existing vertex
194301e04c3fSmrg    *    array object."
194401e04c3fSmrg    */
19457ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glEnableVertexArrayAttrib");
194601e04c3fSmrg   if (!vao)
194701e04c3fSmrg      return;
194801e04c3fSmrg
194901e04c3fSmrg   enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttrib");
195001e04c3fSmrg}
195101e04c3fSmrg
19527ec681f3Smrgvoid GLAPIENTRY
19537ec681f3Smrg_mesa_EnableVertexArrayAttribEXT(GLuint vaobj, GLuint index)
19547ec681f3Smrg{
19557ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
19567ec681f3Smrg   struct gl_vertex_array_object* vao = _mesa_lookup_vao_err(ctx, vaobj,
19577ec681f3Smrg                                                             true,
19587ec681f3Smrg                                                             "glEnableVertexArrayAttribEXT");
19597ec681f3Smrg   if (!vao)
19607ec681f3Smrg      return;
19617ec681f3Smrg
19627ec681f3Smrg   enable_vertex_array_attrib(ctx, vao, index, "glEnableVertexArrayAttribEXT");
19637ec681f3Smrg}
19647ec681f3Smrg
196501e04c3fSmrg
196601e04c3fSmrgvoid GLAPIENTRY
196701e04c3fSmrg_mesa_EnableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index)
196801e04c3fSmrg{
196901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
197001e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
197101e04c3fSmrg   _mesa_enable_vertex_array_attrib(ctx, vao, VERT_ATTRIB_GENERIC(index));
197201e04c3fSmrg}
197301e04c3fSmrg
197401e04c3fSmrg
197501e04c3fSmrgvoid
1976b9abf16eSmaya_mesa_disable_vertex_array_attribs(struct gl_context *ctx,
1977b9abf16eSmaya                                   struct gl_vertex_array_object *vao,
1978b9abf16eSmaya                                   GLbitfield attrib_bits)
197901e04c3fSmrg{
1980b9abf16eSmaya   assert((attrib_bits & ~VERT_BIT_ALL) == 0);
198101e04c3fSmrg   assert(!vao->SharedAndImmutable);
198201e04c3fSmrg
1983b9abf16eSmaya   /* Only work on bits that are enabled */
1984b9abf16eSmaya   attrib_bits &= vao->Enabled;
1985b9abf16eSmaya   if (attrib_bits) {
198601e04c3fSmrg      /* was enabled, now being disabled */
1987b9abf16eSmaya      vao->Enabled &= ~attrib_bits;
1988b9abf16eSmaya      vao->NewArrays |= attrib_bits;
198901e04c3fSmrg
199001e04c3fSmrg      /* Update the map mode if needed */
1991b9abf16eSmaya      if (attrib_bits & (VERT_BIT_POS|VERT_BIT_GENERIC0))
199201e04c3fSmrg         update_attribute_map_mode(ctx, vao);
19937ec681f3Smrg
19947ec681f3Smrg      vao->_EnabledWithMapMode =
19957ec681f3Smrg         _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled);
199601e04c3fSmrg   }
199701e04c3fSmrg}
199801e04c3fSmrg
199901e04c3fSmrg
200001e04c3fSmrgvoid GLAPIENTRY
200101e04c3fSmrg_mesa_DisableVertexAttribArray(GLuint index)
200201e04c3fSmrg{
20033464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
20043464ebd5Sriastradh
2005af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
200601e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexAttribArray(index)");
20073464ebd5Sriastradh      return;
20083464ebd5Sriastradh   }
20093464ebd5Sriastradh
201001e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
201101e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
201201e04c3fSmrg}
20133464ebd5Sriastradh
2014af69d88dSmrg
201501e04c3fSmrgvoid GLAPIENTRY
201601e04c3fSmrg_mesa_DisableVertexAttribArray_no_error(GLuint index)
201701e04c3fSmrg{
201801e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
201901e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
202001e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, ctx->Array.VAO, attrib);
202101e04c3fSmrg}
202201e04c3fSmrg
202301e04c3fSmrg
202401e04c3fSmrgvoid GLAPIENTRY
202501e04c3fSmrg_mesa_DisableVertexArrayAttrib(GLuint vaobj, GLuint index)
202601e04c3fSmrg{
202701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
202801e04c3fSmrg   struct gl_vertex_array_object *vao;
202901e04c3fSmrg
203001e04c3fSmrg   /* The ARB_direct_state_access specification says:
203101e04c3fSmrg    *
203201e04c3fSmrg    *   "An INVALID_OPERATION error is generated by EnableVertexArrayAttrib
203301e04c3fSmrg    *    and DisableVertexArrayAttrib if <vaobj> is not
203401e04c3fSmrg    *    [compatibility profile: zero or] the name of an existing vertex
203501e04c3fSmrg    *    array object."
203601e04c3fSmrg    */
20377ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glDisableVertexArrayAttrib");
20387ec681f3Smrg   if (!vao)
20397ec681f3Smrg      return;
20407ec681f3Smrg
20417ec681f3Smrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
20427ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexArrayAttrib(index)");
20437ec681f3Smrg      return;
20447ec681f3Smrg   }
20457ec681f3Smrg
20467ec681f3Smrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
20477ec681f3Smrg   _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
20487ec681f3Smrg}
20497ec681f3Smrg
20507ec681f3Smrgvoid GLAPIENTRY
20517ec681f3Smrg_mesa_DisableVertexArrayAttribEXT(GLuint vaobj, GLuint index)
20527ec681f3Smrg{
20537ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
20547ec681f3Smrg   struct gl_vertex_array_object* vao = _mesa_lookup_vao_err(ctx, vaobj,
20557ec681f3Smrg                                                             true,
20567ec681f3Smrg                                                             "glEnableVertexArrayAttribEXT");
205701e04c3fSmrg   if (!vao)
205801e04c3fSmrg      return;
205901e04c3fSmrg
206001e04c3fSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
206101e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glDisableVertexArrayAttrib(index)");
206201e04c3fSmrg      return;
2063af69d88dSmrg   }
206401e04c3fSmrg
206501e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
206601e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
206701e04c3fSmrg}
206801e04c3fSmrg
206901e04c3fSmrg
207001e04c3fSmrgvoid GLAPIENTRY
207101e04c3fSmrg_mesa_DisableVertexArrayAttrib_no_error(GLuint vaobj, GLuint index)
207201e04c3fSmrg{
207301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
207401e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
207501e04c3fSmrg   const gl_vert_attrib attrib = VERT_ATTRIB_GENERIC(index);
207601e04c3fSmrg   _mesa_disable_vertex_array_attrib(ctx, vao, attrib);
20773464ebd5Sriastradh}
20783464ebd5Sriastradh
20793464ebd5Sriastradh
20803464ebd5Sriastradh/**
20813464ebd5Sriastradh * Return info for a vertex attribute array (no alias with legacy
20823464ebd5Sriastradh * vertex attributes (pos, normal, color, etc)).  This function does
20833464ebd5Sriastradh * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
20843464ebd5Sriastradh */
20853464ebd5Sriastradhstatic GLuint
208601e04c3fSmrgget_vertex_array_attrib(struct gl_context *ctx,
208701e04c3fSmrg                        const struct gl_vertex_array_object *vao,
208801e04c3fSmrg                        GLuint index, GLenum pname,
208901e04c3fSmrg                        const char *caller)
20903464ebd5Sriastradh{
209101e04c3fSmrg   const struct gl_array_attributes *array;
20927ec681f3Smrg   struct gl_buffer_object *buf;
20933464ebd5Sriastradh
2094af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
20953464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
20963464ebd5Sriastradh      return 0;
20973464ebd5Sriastradh   }
20983464ebd5Sriastradh
209901e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(index) < ARRAY_SIZE(vao->VertexAttrib));
21003464ebd5Sriastradh
2101af69d88dSmrg   array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
21023464ebd5Sriastradh
21033464ebd5Sriastradh   switch (pname) {
21043464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
2105b9abf16eSmaya      return !!(vao->Enabled & VERT_BIT_GENERIC(index));
21063464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
2107b9abf16eSmaya      return (array->Format.Format == GL_BGRA) ? GL_BGRA : array->Format.Size;
21083464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
21093464ebd5Sriastradh      return array->Stride;
21103464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
2111b9abf16eSmaya      return array->Format.Type;
21123464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
2113b9abf16eSmaya      return array->Format.Normalized;
21143464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
21157ec681f3Smrg      buf = vao->BufferBinding[array->BufferBindingIndex].BufferObj;
21167ec681f3Smrg      return buf ? buf->Name : 0;
21173464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
2118af69d88dSmrg      if ((_mesa_is_desktop_gl(ctx)
2119af69d88dSmrg           && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4))
2120af69d88dSmrg          || _mesa_is_gles3(ctx)) {
2121b9abf16eSmaya         return array->Format.Integer;
21224a49301eSmrg      }
21233464ebd5Sriastradh      goto error;
212401e04c3fSmrg   case GL_VERTEX_ATTRIB_ARRAY_LONG:
212501e04c3fSmrg      if (_mesa_is_desktop_gl(ctx)) {
2126b9abf16eSmaya         return array->Format.Doubles;
212701e04c3fSmrg      }
212801e04c3fSmrg      goto error;
21293464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
2130af69d88dSmrg      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
2131af69d88dSmrg          || _mesa_is_gles3(ctx)) {
213201e04c3fSmrg         return vao->BufferBinding[array->BufferBindingIndex].InstanceDivisor;
2133af69d88dSmrg      }
2134af69d88dSmrg      goto error;
2135af69d88dSmrg   case GL_VERTEX_ATTRIB_BINDING:
213601e04c3fSmrg      if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) {
213701e04c3fSmrg         return array->BufferBindingIndex - VERT_ATTRIB_GENERIC0;
2138af69d88dSmrg      }
2139af69d88dSmrg      goto error;
2140af69d88dSmrg   case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
214101e04c3fSmrg      if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) {
2142af69d88dSmrg         return array->RelativeOffset;
21434a49301eSmrg      }
21443464ebd5Sriastradh      goto error;
21453464ebd5Sriastradh   default:
21463464ebd5Sriastradh      ; /* fall-through */
21473464ebd5Sriastradh   }
21484a49301eSmrg
21493464ebd5Sriastradherror:
21503464ebd5Sriastradh   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname);
21513464ebd5Sriastradh   return 0;
21523464ebd5Sriastradh}
21533464ebd5Sriastradh
21543464ebd5Sriastradh
21553464ebd5Sriastradhstatic const GLfloat *
21563464ebd5Sriastradhget_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
21573464ebd5Sriastradh{
21583464ebd5Sriastradh   if (index == 0) {
2159af69d88dSmrg      if (_mesa_attr_zero_aliases_vertex(ctx)) {
21603464ebd5Sriastradh	 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
21613464ebd5Sriastradh	 return NULL;
21623464ebd5Sriastradh      }
21633464ebd5Sriastradh   }
2164af69d88dSmrg   else if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
21653464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE,
21663464ebd5Sriastradh		  "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function);
21673464ebd5Sriastradh      return NULL;
21683464ebd5Sriastradh   }
21693464ebd5Sriastradh
217001e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(index) <
217101e04c3fSmrg          ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
2172af69d88dSmrg
21733464ebd5Sriastradh   FLUSH_CURRENT(ctx, 0);
2174af69d88dSmrg   return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)];
21753464ebd5Sriastradh}
21763464ebd5Sriastradh
21773464ebd5Sriastradhvoid GLAPIENTRY
2178af69d88dSmrg_mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
21793464ebd5Sriastradh{
21803464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
21813464ebd5Sriastradh
21823464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
21833464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv");
21843464ebd5Sriastradh      if (v != NULL) {
21853464ebd5Sriastradh         COPY_4V(params, v);
21863464ebd5Sriastradh      }
21874a49301eSmrg   }
21884a49301eSmrg   else {
218901e04c3fSmrg      params[0] = (GLfloat) get_vertex_array_attrib(ctx, ctx->Array.VAO,
219001e04c3fSmrg                                                    index, pname,
21913464ebd5Sriastradh                                                    "glGetVertexAttribfv");
21924a49301eSmrg   }
21933464ebd5Sriastradh}
21944a49301eSmrg
21953464ebd5Sriastradh
21963464ebd5Sriastradhvoid GLAPIENTRY
2197af69d88dSmrg_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params)
21983464ebd5Sriastradh{
21993464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
22003464ebd5Sriastradh
22013464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
22023464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv");
22033464ebd5Sriastradh      if (v != NULL) {
22043464ebd5Sriastradh         params[0] = (GLdouble) v[0];
22053464ebd5Sriastradh         params[1] = (GLdouble) v[1];
22063464ebd5Sriastradh         params[2] = (GLdouble) v[2];
22073464ebd5Sriastradh         params[3] = (GLdouble) v[3];
22083464ebd5Sriastradh      }
22093464ebd5Sriastradh   }
22103464ebd5Sriastradh   else {
221101e04c3fSmrg      params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
221201e04c3fSmrg                                                     index, pname,
22133464ebd5Sriastradh                                                     "glGetVertexAttribdv");
22147117f1b4Smrg   }
22153464ebd5Sriastradh}
22167117f1b4Smrg
221701e04c3fSmrgvoid GLAPIENTRY
221801e04c3fSmrg_mesa_GetVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params)
221901e04c3fSmrg{
222001e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
222101e04c3fSmrg
222201e04c3fSmrg   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
222301e04c3fSmrg      const GLdouble *v =
222401e04c3fSmrg         (const GLdouble *)get_current_attrib(ctx, index,
222501e04c3fSmrg                                              "glGetVertexAttribLdv");
222601e04c3fSmrg      if (v != NULL) {
222701e04c3fSmrg         params[0] = v[0];
222801e04c3fSmrg         params[1] = v[1];
222901e04c3fSmrg         params[2] = v[2];
223001e04c3fSmrg         params[3] = v[3];
223101e04c3fSmrg      }
223201e04c3fSmrg   }
223301e04c3fSmrg   else {
223401e04c3fSmrg      params[0] = (GLdouble) get_vertex_array_attrib(ctx, ctx->Array.VAO,
223501e04c3fSmrg                                                     index, pname,
223601e04c3fSmrg                                                     "glGetVertexAttribLdv");
223701e04c3fSmrg   }
223801e04c3fSmrg}
22393464ebd5Sriastradh
22403464ebd5Sriastradhvoid GLAPIENTRY
2241af69d88dSmrg_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
22423464ebd5Sriastradh{
22433464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
22443464ebd5Sriastradh
22453464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
22463464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv");
22473464ebd5Sriastradh      if (v != NULL) {
22483464ebd5Sriastradh         /* XXX should floats in[0,1] be scaled to full int range? */
22493464ebd5Sriastradh         params[0] = (GLint) v[0];
22503464ebd5Sriastradh         params[1] = (GLint) v[1];
22513464ebd5Sriastradh         params[2] = (GLint) v[2];
22523464ebd5Sriastradh         params[3] = (GLint) v[3];
22533464ebd5Sriastradh      }
22543464ebd5Sriastradh   }
22553464ebd5Sriastradh   else {
225601e04c3fSmrg      params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
225701e04c3fSmrg                                                  index, pname,
22583464ebd5Sriastradh                                                  "glGetVertexAttribiv");
22593464ebd5Sriastradh   }
22603464ebd5Sriastradh}
22613464ebd5Sriastradh
226201e04c3fSmrgvoid GLAPIENTRY
226301e04c3fSmrg_mesa_GetVertexAttribLui64vARB(GLuint index, GLenum pname, GLuint64EXT *params)
226401e04c3fSmrg{
226501e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
226601e04c3fSmrg
226701e04c3fSmrg   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
226801e04c3fSmrg      const GLuint64 *v =
226901e04c3fSmrg         (const GLuint64 *)get_current_attrib(ctx, index,
227001e04c3fSmrg                                              "glGetVertexAttribLui64vARB");
227101e04c3fSmrg      if (v != NULL) {
227201e04c3fSmrg         params[0] = v[0];
227301e04c3fSmrg         params[1] = v[1];
227401e04c3fSmrg         params[2] = v[2];
227501e04c3fSmrg         params[3] = v[3];
227601e04c3fSmrg      }
227701e04c3fSmrg   }
227801e04c3fSmrg   else {
227901e04c3fSmrg      params[0] = (GLuint64) get_vertex_array_attrib(ctx, ctx->Array.VAO,
228001e04c3fSmrg                                                     index, pname,
228101e04c3fSmrg                                                     "glGetVertexAttribLui64vARB");
228201e04c3fSmrg   }
228301e04c3fSmrg}
228401e04c3fSmrg
22853464ebd5Sriastradh
22863464ebd5Sriastradh/** GL 3.0 */
22873464ebd5Sriastradhvoid GLAPIENTRY
22883464ebd5Sriastradh_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
22893464ebd5Sriastradh{
22903464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
22913464ebd5Sriastradh
22923464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
2293af69d88dSmrg      const GLint *v = (const GLint *)
22943464ebd5Sriastradh	 get_current_attrib(ctx, index, "glGetVertexAttribIiv");
22953464ebd5Sriastradh      if (v != NULL) {
2296af69d88dSmrg         COPY_4V(params, v);
22973464ebd5Sriastradh      }
22983464ebd5Sriastradh   }
22993464ebd5Sriastradh   else {
230001e04c3fSmrg      params[0] = (GLint) get_vertex_array_attrib(ctx, ctx->Array.VAO,
230101e04c3fSmrg                                                  index, pname,
23023464ebd5Sriastradh                                                  "glGetVertexAttribIiv");
23033464ebd5Sriastradh   }
23043464ebd5Sriastradh}
23053464ebd5Sriastradh
23063464ebd5Sriastradh
23073464ebd5Sriastradh/** GL 3.0 */
23083464ebd5Sriastradhvoid GLAPIENTRY
23093464ebd5Sriastradh_mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
23103464ebd5Sriastradh{
23113464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
23123464ebd5Sriastradh
23133464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
2314af69d88dSmrg      const GLuint *v = (const GLuint *)
23153464ebd5Sriastradh	 get_current_attrib(ctx, index, "glGetVertexAttribIuiv");
23163464ebd5Sriastradh      if (v != NULL) {
2317af69d88dSmrg         COPY_4V(params, v);
23183464ebd5Sriastradh      }
23193464ebd5Sriastradh   }
23203464ebd5Sriastradh   else {
232101e04c3fSmrg      params[0] = get_vertex_array_attrib(ctx, ctx->Array.VAO,
232201e04c3fSmrg                                          index, pname,
23233464ebd5Sriastradh                                          "glGetVertexAttribIuiv");
23243464ebd5Sriastradh   }
23253464ebd5Sriastradh}
23263464ebd5Sriastradh
23273464ebd5Sriastradh
23283464ebd5Sriastradhvoid GLAPIENTRY
2329af69d88dSmrg_mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
23303464ebd5Sriastradh{
23313464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
23323464ebd5Sriastradh
2333af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
23343464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
23353464ebd5Sriastradh      return;
23363464ebd5Sriastradh   }
23373464ebd5Sriastradh
23383464ebd5Sriastradh   if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
23393464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
23403464ebd5Sriastradh      return;
23413464ebd5Sriastradh   }
23423464ebd5Sriastradh
234301e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(index) <
234401e04c3fSmrg          ARRAY_SIZE(ctx->Array.VAO->VertexAttrib));
234501e04c3fSmrg
234601e04c3fSmrg   *pointer = (GLvoid *)
234701e04c3fSmrg      ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
234801e04c3fSmrg}
234901e04c3fSmrg
235001e04c3fSmrg
235101e04c3fSmrg/** ARB_direct_state_access */
235201e04c3fSmrgvoid GLAPIENTRY
235301e04c3fSmrg_mesa_GetVertexArrayIndexediv(GLuint vaobj, GLuint index,
235401e04c3fSmrg                              GLenum pname, GLint *params)
235501e04c3fSmrg{
235601e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
235701e04c3fSmrg   struct gl_vertex_array_object *vao;
23587ec681f3Smrg   struct gl_buffer_object *buf;
235901e04c3fSmrg
236001e04c3fSmrg   /* The ARB_direct_state_access specification says:
236101e04c3fSmrg    *
236201e04c3fSmrg    *    "An INVALID_OPERATION error is generated if <vaobj> is not
236301e04c3fSmrg    *     [compatibility profile: zero or] the name of an existing
236401e04c3fSmrg    *     vertex array object."
236501e04c3fSmrg    */
23667ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayIndexediv");
236701e04c3fSmrg   if (!vao)
236801e04c3fSmrg      return;
236901e04c3fSmrg
237001e04c3fSmrg   /* The ARB_direct_state_access specification says:
237101e04c3fSmrg    *
237201e04c3fSmrg    *    "For GetVertexArrayIndexediv, <pname> must be one of
237301e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_ENABLED, VERTEX_ATTRIB_ARRAY_SIZE,
237401e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_STRIDE, VERTEX_ATTRIB_ARRAY_TYPE,
237501e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_NORMALIZED, VERTEX_ATTRIB_ARRAY_INTEGER,
237601e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_LONG, VERTEX_ATTRIB_ARRAY_DIVISOR, or
237701e04c3fSmrg    *     VERTEX_ATTRIB_RELATIVE_OFFSET."
237801e04c3fSmrg    *
237901e04c3fSmrg    * and:
238001e04c3fSmrg    *
238101e04c3fSmrg    *    "Add GetVertexArrayIndexediv in 'Get Command' for
238201e04c3fSmrg    *     VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
238301e04c3fSmrg    *     VERTEX_ATTRIB_BINDING,
238401e04c3fSmrg    *     VERTEX_ATTRIB_RELATIVE_OFFSET,
238501e04c3fSmrg    *     VERTEX_BINDING_OFFSET, and
238601e04c3fSmrg    *     VERTEX_BINDING_STRIDE states"
238701e04c3fSmrg    *
238801e04c3fSmrg    * The only parameter name common to both lists is
238901e04c3fSmrg    * VERTEX_ATTRIB_RELATIVE_OFFSET.  Also note that VERTEX_BINDING_BUFFER
239001e04c3fSmrg    * and VERTEX_BINDING_DIVISOR are missing from both lists.  It seems
239101e04c3fSmrg    * pretty clear however that the intent is that it should be possible
239201e04c3fSmrg    * to query all vertex attrib and binding states that can be set with
239301e04c3fSmrg    * a DSA function.
239401e04c3fSmrg    */
239501e04c3fSmrg   switch (pname) {
239601e04c3fSmrg   case GL_VERTEX_BINDING_OFFSET:
239701e04c3fSmrg      params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Offset;
239801e04c3fSmrg      break;
239901e04c3fSmrg   case GL_VERTEX_BINDING_STRIDE:
240001e04c3fSmrg      params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Stride;
240101e04c3fSmrg      break;
240201e04c3fSmrg   case GL_VERTEX_BINDING_DIVISOR:
240301e04c3fSmrg      params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor;
240401e04c3fSmrg      break;
240501e04c3fSmrg   case GL_VERTEX_BINDING_BUFFER:
24067ec681f3Smrg      buf = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].BufferObj;
24077ec681f3Smrg      params[0] = buf ? buf->Name : 0;
240801e04c3fSmrg      break;
240901e04c3fSmrg   default:
241001e04c3fSmrg      params[0] = get_vertex_array_attrib(ctx, vao, index, pname,
241101e04c3fSmrg                                          "glGetVertexArrayIndexediv");
241201e04c3fSmrg      break;
241301e04c3fSmrg   }
241401e04c3fSmrg}
241501e04c3fSmrg
241601e04c3fSmrg
241701e04c3fSmrgvoid GLAPIENTRY
241801e04c3fSmrg_mesa_GetVertexArrayIndexed64iv(GLuint vaobj, GLuint index,
241901e04c3fSmrg                                GLenum pname, GLint64 *params)
242001e04c3fSmrg{
242101e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
242201e04c3fSmrg   struct gl_vertex_array_object *vao;
242301e04c3fSmrg
242401e04c3fSmrg   /* The ARB_direct_state_access specification says:
242501e04c3fSmrg    *
242601e04c3fSmrg    *    "An INVALID_OPERATION error is generated if <vaobj> is not
242701e04c3fSmrg    *     [compatibility profile: zero or] the name of an existing
242801e04c3fSmrg    *     vertex array object."
242901e04c3fSmrg    */
24307ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayIndexed64iv");
243101e04c3fSmrg   if (!vao)
243201e04c3fSmrg      return;
243301e04c3fSmrg
243401e04c3fSmrg   /* The ARB_direct_state_access specification says:
243501e04c3fSmrg    *
243601e04c3fSmrg    *    "For GetVertexArrayIndexed64iv, <pname> must be
243701e04c3fSmrg    *     VERTEX_BINDING_OFFSET."
243801e04c3fSmrg    *
243901e04c3fSmrg    * and:
244001e04c3fSmrg    *
244101e04c3fSmrg    *    "An INVALID_ENUM error is generated if <pname> is not one of
244201e04c3fSmrg    *     the valid values listed above for the corresponding command."
244301e04c3fSmrg    */
244401e04c3fSmrg   if (pname != GL_VERTEX_BINDING_OFFSET) {
244501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIndexed64iv("
244601e04c3fSmrg                  "pname != GL_VERTEX_BINDING_OFFSET)");
244701e04c3fSmrg      return;
244801e04c3fSmrg   }
244901e04c3fSmrg
245001e04c3fSmrg   /* The ARB_direct_state_access specification says:
245101e04c3fSmrg    *
245201e04c3fSmrg    *    "An INVALID_VALUE error is generated if <index> is greater than
245301e04c3fSmrg    *     or equal to the value of MAX_VERTEX_ATTRIBS."
245401e04c3fSmrg    *
245501e04c3fSmrg    * Since the index refers to a buffer binding in this case, the intended
245601e04c3fSmrg    * limit must be MAX_VERTEX_ATTRIB_BINDINGS.  Both limits are currently
245701e04c3fSmrg    * required to be the same, so in practice this doesn't matter.
245801e04c3fSmrg    */
245901e04c3fSmrg   if (index >= ctx->Const.MaxVertexAttribBindings) {
246001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayIndexed64iv(index"
246101e04c3fSmrg                  "%d >= the value of GL_MAX_VERTEX_ATTRIB_BINDINGS (%d))",
246201e04c3fSmrg                  index, ctx->Const.MaxVertexAttribBindings);
246301e04c3fSmrg      return;
246401e04c3fSmrg   }
24653464ebd5Sriastradh
246601e04c3fSmrg   params[0] = vao->BufferBinding[VERT_ATTRIB_GENERIC(index)].Offset;
24677117f1b4Smrg}
24687117f1b4Smrg
24697117f1b4Smrg
24707117f1b4Smrgvoid GLAPIENTRY
24717117f1b4Smrg_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
24727117f1b4Smrg                       GLsizei count, const GLvoid *ptr)
24737117f1b4Smrg{
24747117f1b4Smrg   (void) count;
24757117f1b4Smrg   _mesa_VertexPointer(size, type, stride, ptr);
24767117f1b4Smrg}
24777117f1b4Smrg
24787117f1b4Smrg
24797117f1b4Smrgvoid GLAPIENTRY
24807117f1b4Smrg_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
24817117f1b4Smrg                       const GLvoid *ptr)
24827117f1b4Smrg{
24837117f1b4Smrg   (void) count;
24847117f1b4Smrg   _mesa_NormalPointer(type, stride, ptr);
24857117f1b4Smrg}
24867117f1b4Smrg
24877117f1b4Smrg
24887117f1b4Smrgvoid GLAPIENTRY
24897117f1b4Smrg_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
24907117f1b4Smrg                      const GLvoid *ptr)
24917117f1b4Smrg{
24927117f1b4Smrg   (void) count;
24937117f1b4Smrg   _mesa_ColorPointer(size, type, stride, ptr);
24947117f1b4Smrg}
24957117f1b4Smrg
24967117f1b4Smrg
24977117f1b4Smrgvoid GLAPIENTRY
24987117f1b4Smrg_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
24997117f1b4Smrg                      const GLvoid *ptr)
25007117f1b4Smrg{
25017117f1b4Smrg   (void) count;
25027117f1b4Smrg   _mesa_IndexPointer(type, stride, ptr);
25037117f1b4Smrg}
25047117f1b4Smrg
25057117f1b4Smrg
25067117f1b4Smrgvoid GLAPIENTRY
25077117f1b4Smrg_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
25087117f1b4Smrg                         GLsizei count, const GLvoid *ptr)
25097117f1b4Smrg{
25107117f1b4Smrg   (void) count;
25117117f1b4Smrg   _mesa_TexCoordPointer(size, type, stride, ptr);
25127117f1b4Smrg}
25137117f1b4Smrg
25147117f1b4Smrg
25157ec681f3Smrgvoid GLAPIENTRY
25167ec681f3Smrg_mesa_MultiTexCoordPointerEXT(GLenum texunit, GLint size, GLenum type,
25177ec681f3Smrg                              GLsizei stride, const GLvoid *ptr)
25187ec681f3Smrg{
25197ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
25207ec681f3Smrg   const GLint sizeMin = 1;
25217ec681f3Smrg   const GLuint unit = texunit - GL_TEXTURE0;
25227ec681f3Smrg
25237ec681f3Smrg   GLenum format = GL_RGBA;
25247ec681f3Smrg   const GLbitfield legalTypes = (SHORT_BIT | INT_BIT |
25257ec681f3Smrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
25267ec681f3Smrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
25277ec681f3Smrg                                  INT_2_10_10_10_REV_BIT);
25287ec681f3Smrg
25297ec681f3Smrg   if (!validate_array_and_format(ctx, "glMultiTexCoordPointerEXT",
25307ec681f3Smrg                                  ctx->Array.VAO, ctx->Array.ArrayBufferObj,
25317ec681f3Smrg                                  VERT_ATTRIB_TEX(unit), legalTypes,
25327ec681f3Smrg                                  sizeMin, 4, size, type, stride,
25337ec681f3Smrg                                  GL_FALSE, GL_FALSE, GL_FALSE, format, ptr))
25347ec681f3Smrg      return;
25357ec681f3Smrg
25367ec681f3Smrg   update_array(ctx, ctx->Array.VAO, ctx->Array.ArrayBufferObj,
25377ec681f3Smrg                VERT_ATTRIB_TEX(unit), format, 4, size, type,
25387ec681f3Smrg                stride, GL_FALSE, GL_FALSE, GL_FALSE, ptr);
25397ec681f3Smrg}
25407ec681f3Smrg
25417ec681f3Smrg
25427117f1b4Smrgvoid GLAPIENTRY
25437117f1b4Smrg_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
25447117f1b4Smrg{
25457117f1b4Smrg   (void) count;
25467117f1b4Smrg   _mesa_EdgeFlagPointer(stride, ptr);
25477117f1b4Smrg}
25487117f1b4Smrg
25497117f1b4Smrg
25507ec681f3Smrgbool
25517ec681f3Smrg_mesa_get_interleaved_layout(GLenum format,
25527ec681f3Smrg                             struct gl_interleaved_layout *layout)
25537117f1b4Smrg{
25547ec681f3Smrg   int f = sizeof(GLfloat);
25557ec681f3Smrg   int c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
25567117f1b4Smrg
25577ec681f3Smrg   memset(layout, 0, sizeof(*layout));
25587117f1b4Smrg
25597117f1b4Smrg   switch (format) {
25607117f1b4Smrg      case GL_V2F:
25617ec681f3Smrg         layout->vcomps = 2;
25627ec681f3Smrg         layout->defstride = 2 * f;
25637117f1b4Smrg         break;
25647117f1b4Smrg      case GL_V3F:
25657ec681f3Smrg         layout->vcomps = 3;
25667ec681f3Smrg         layout->defstride = 3 * f;
25677117f1b4Smrg         break;
25687117f1b4Smrg      case GL_C4UB_V2F:
25697ec681f3Smrg         layout->cflag = true;
25707ec681f3Smrg         layout->ccomps = 4;  layout->vcomps = 2;
25717ec681f3Smrg         layout->ctype = GL_UNSIGNED_BYTE;
25727ec681f3Smrg         layout->voffset = c;
25737ec681f3Smrg         layout->defstride = c + 2 * f;
25747117f1b4Smrg         break;
25757117f1b4Smrg      case GL_C4UB_V3F:
25767ec681f3Smrg         layout->cflag = true;
25777ec681f3Smrg         layout->ccomps = 4;  layout->vcomps = 3;
25787ec681f3Smrg         layout->ctype = GL_UNSIGNED_BYTE;
25797ec681f3Smrg         layout->voffset = c;
25807ec681f3Smrg         layout->defstride = c + 3 * f;
25817117f1b4Smrg         break;
25827117f1b4Smrg      case GL_C3F_V3F:
25837ec681f3Smrg         layout->cflag = true;
25847ec681f3Smrg         layout->ccomps = 3;  layout->vcomps = 3;
25857ec681f3Smrg         layout->ctype = GL_FLOAT;
25867ec681f3Smrg         layout->voffset = 3 * f;
25877ec681f3Smrg         layout->defstride = 6 * f;
25887117f1b4Smrg         break;
25897117f1b4Smrg      case GL_N3F_V3F:
25907ec681f3Smrg         layout->nflag = true;
25917ec681f3Smrg         layout->vcomps = 3;
25927ec681f3Smrg         layout->voffset = 3 * f;
25937ec681f3Smrg         layout->defstride = 6 * f;
25947117f1b4Smrg         break;
25957117f1b4Smrg      case GL_C4F_N3F_V3F:
25967ec681f3Smrg         layout->cflag = true;  layout->nflag = true;
25977ec681f3Smrg         layout->ccomps = 4;  layout->vcomps = 3;
25987ec681f3Smrg         layout->ctype = GL_FLOAT;
25997ec681f3Smrg         layout->noffset = 4 * f;
26007ec681f3Smrg         layout->voffset = 7 * f;
26017ec681f3Smrg         layout->defstride = 10 * f;
26027117f1b4Smrg         break;
26037117f1b4Smrg      case GL_T2F_V3F:
26047ec681f3Smrg         layout->tflag = true;
26057ec681f3Smrg         layout->tcomps = 2;  layout->vcomps = 3;
26067ec681f3Smrg         layout->voffset = 2 * f;
26077ec681f3Smrg         layout->defstride = 5 * f;
26087117f1b4Smrg         break;
26097117f1b4Smrg      case GL_T4F_V4F:
26107ec681f3Smrg         layout->tflag = true;
26117ec681f3Smrg         layout->tcomps = 4;  layout->vcomps = 4;
26127ec681f3Smrg         layout->voffset = 4 * f;
26137ec681f3Smrg         layout->defstride = 8 * f;
26147117f1b4Smrg         break;
26157117f1b4Smrg      case GL_T2F_C4UB_V3F:
26167ec681f3Smrg         layout->tflag = true;  layout->cflag = true;
26177ec681f3Smrg         layout->tcomps = 2;  layout->ccomps = 4;  layout->vcomps = 3;
26187ec681f3Smrg         layout->ctype = GL_UNSIGNED_BYTE;
26197ec681f3Smrg         layout->coffset = 2 * f;
26207ec681f3Smrg         layout->voffset = c + 2 * f;
26217ec681f3Smrg         layout->defstride = c + 5 * f;
26227117f1b4Smrg         break;
26237117f1b4Smrg      case GL_T2F_C3F_V3F:
26247ec681f3Smrg         layout->tflag = true;  layout->cflag = true;
26257ec681f3Smrg         layout->tcomps = 2;  layout->ccomps = 3;  layout->vcomps = 3;
26267ec681f3Smrg         layout->ctype = GL_FLOAT;
26277ec681f3Smrg         layout->coffset = 2 * f;
26287ec681f3Smrg         layout->voffset = 5 * f;
26297ec681f3Smrg         layout->defstride = 8 * f;
26307117f1b4Smrg         break;
26317117f1b4Smrg      case GL_T2F_N3F_V3F:
26327ec681f3Smrg         layout->tflag = true;    layout->nflag = true;
26337ec681f3Smrg         layout->tcomps = 2;  layout->vcomps = 3;
26347ec681f3Smrg         layout->noffset = 2 * f;
26357ec681f3Smrg         layout->voffset = 5 * f;
26367ec681f3Smrg         layout->defstride = 8 * f;
26377117f1b4Smrg         break;
26387117f1b4Smrg      case GL_T2F_C4F_N3F_V3F:
26397ec681f3Smrg         layout->tflag = true;  layout->cflag = true;  layout->nflag = true;
26407ec681f3Smrg         layout->tcomps = 2;  layout->ccomps = 4;  layout->vcomps = 3;
26417ec681f3Smrg         layout->ctype = GL_FLOAT;
26427ec681f3Smrg         layout->coffset = 2 * f;
26437ec681f3Smrg         layout->noffset = 6 * f;
26447ec681f3Smrg         layout->voffset = 9 * f;
26457ec681f3Smrg         layout->defstride = 12 * f;
26467117f1b4Smrg         break;
26477117f1b4Smrg      case GL_T4F_C4F_N3F_V4F:
26487ec681f3Smrg         layout->tflag = true;  layout->cflag = true;  layout->nflag = true;
26497ec681f3Smrg         layout->tcomps = 4;  layout->ccomps = 4;  layout->vcomps = 4;
26507ec681f3Smrg         layout->ctype = GL_FLOAT;
26517ec681f3Smrg         layout->coffset = 4 * f;
26527ec681f3Smrg         layout->noffset = 8 * f;
26537ec681f3Smrg         layout->voffset = 11 * f;
26547ec681f3Smrg         layout->defstride = 15 * f;
26557117f1b4Smrg         break;
26567117f1b4Smrg      default:
26577ec681f3Smrg         return false;
26587ec681f3Smrg   }
26597ec681f3Smrg   return true;
26607ec681f3Smrg}
26617ec681f3Smrg
26627ec681f3Smrgvoid GLAPIENTRY
26637ec681f3Smrg_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
26647ec681f3Smrg{
26657ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
26667ec681f3Smrg   struct gl_interleaved_layout layout;
26677ec681f3Smrg
26687ec681f3Smrg   if (stride < 0) {
26697ec681f3Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
26707ec681f3Smrg      return;
26717ec681f3Smrg   }
26727ec681f3Smrg
26737ec681f3Smrg   if (!_mesa_get_interleaved_layout(format, &layout)) {
26747ec681f3Smrg      _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
26757ec681f3Smrg      return;
26767117f1b4Smrg   }
26777117f1b4Smrg
26787117f1b4Smrg   if (stride==0) {
26797ec681f3Smrg      stride = layout.defstride;
26807117f1b4Smrg   }
26817117f1b4Smrg
26827117f1b4Smrg   _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
26837117f1b4Smrg   _mesa_DisableClientState( GL_INDEX_ARRAY );
26847117f1b4Smrg   /* XXX also disable secondary color and generic arrays? */
26857117f1b4Smrg
26867117f1b4Smrg   /* Texcoords */
26877ec681f3Smrg   if (layout.tflag) {
26887117f1b4Smrg      _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
26897ec681f3Smrg      _mesa_TexCoordPointer( layout.tcomps, GL_FLOAT, stride,
26907ec681f3Smrg                             (GLubyte *) pointer + layout.toffset );
26917117f1b4Smrg   }
26927117f1b4Smrg   else {
26937117f1b4Smrg      _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
26947117f1b4Smrg   }
26957117f1b4Smrg
26967117f1b4Smrg   /* Color */
26977ec681f3Smrg   if (layout.cflag) {
26987117f1b4Smrg      _mesa_EnableClientState( GL_COLOR_ARRAY );
26997ec681f3Smrg      _mesa_ColorPointer( layout.ccomps, layout.ctype, stride,
27007ec681f3Smrg			  (GLubyte *) pointer + layout.coffset );
27017117f1b4Smrg   }
27027117f1b4Smrg   else {
27037117f1b4Smrg      _mesa_DisableClientState( GL_COLOR_ARRAY );
27047117f1b4Smrg   }
27057117f1b4Smrg
27067117f1b4Smrg
27077117f1b4Smrg   /* Normals */
27087ec681f3Smrg   if (layout.nflag) {
27097117f1b4Smrg      _mesa_EnableClientState( GL_NORMAL_ARRAY );
27107ec681f3Smrg      _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + layout.noffset );
27117117f1b4Smrg   }
27127117f1b4Smrg   else {
27137117f1b4Smrg      _mesa_DisableClientState( GL_NORMAL_ARRAY );
27147117f1b4Smrg   }
27157117f1b4Smrg
27167117f1b4Smrg   /* Vertices */
27177117f1b4Smrg   _mesa_EnableClientState( GL_VERTEX_ARRAY );
27187ec681f3Smrg   _mesa_VertexPointer( layout.vcomps, GL_FLOAT, stride,
27197ec681f3Smrg			(GLubyte *) pointer + layout.voffset );
27207117f1b4Smrg}
27217117f1b4Smrg
27227117f1b4Smrg
27237117f1b4Smrgvoid GLAPIENTRY
27247117f1b4Smrg_mesa_LockArraysEXT(GLint first, GLsizei count)
27257117f1b4Smrg{
27267117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2727af69d88dSmrg
27287117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
27297117f1b4Smrg      _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
27307117f1b4Smrg
2731c1f859d4Smrg   if (first < 0) {
2732c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
2733c1f859d4Smrg      return;
27347117f1b4Smrg   }
2735c1f859d4Smrg   if (count <= 0) {
2736c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
2737c1f859d4Smrg      return;
2738c1f859d4Smrg   }
2739c1f859d4Smrg   if (ctx->Array.LockCount != 0) {
2740c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
2741c1f859d4Smrg      return;
27427117f1b4Smrg   }
27437117f1b4Smrg
2744c1f859d4Smrg   ctx->Array.LockFirst = first;
2745c1f859d4Smrg   ctx->Array.LockCount = count;
27467117f1b4Smrg}
27477117f1b4Smrg
27487117f1b4Smrg
27497117f1b4Smrgvoid GLAPIENTRY
27507117f1b4Smrg_mesa_UnlockArraysEXT( void )
27517117f1b4Smrg{
27527117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
2753af69d88dSmrg
27547117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
27557117f1b4Smrg      _mesa_debug(ctx, "glUnlockArrays\n");
27567117f1b4Smrg
2757c1f859d4Smrg   if (ctx->Array.LockCount == 0) {
2758c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
2759c1f859d4Smrg      return;
2760c1f859d4Smrg   }
2761c1f859d4Smrg
27627117f1b4Smrg   ctx->Array.LockFirst = 0;
27637117f1b4Smrg   ctx->Array.LockCount = 0;
27647117f1b4Smrg}
27657117f1b4Smrg
27667117f1b4Smrg
276701e04c3fSmrgstatic void
276801e04c3fSmrgprimitive_restart_index(struct gl_context *ctx, GLuint index)
27697117f1b4Smrg{
277001e04c3fSmrg   ctx->Array.RestartIndex = index;
27717ec681f3Smrg   _mesa_update_derived_primitive_restart_state(ctx);
27727117f1b4Smrg}
27737117f1b4Smrg
27747117f1b4Smrg
277501e04c3fSmrg/**
277601e04c3fSmrg * GL_NV_primitive_restart and GL 3.1
277701e04c3fSmrg */
27787117f1b4Smrgvoid GLAPIENTRY
277901e04c3fSmrg_mesa_PrimitiveRestartIndex_no_error(GLuint index)
27807117f1b4Smrg{
27817117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
278201e04c3fSmrg   primitive_restart_index(ctx, index);
27837117f1b4Smrg}
27847117f1b4Smrg
27857117f1b4Smrg
27867117f1b4Smrgvoid GLAPIENTRY
278701e04c3fSmrg_mesa_PrimitiveRestartIndex(GLuint index)
27887117f1b4Smrg{
27897117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
27907117f1b4Smrg
279101e04c3fSmrg   if (!ctx->Extensions.NV_primitive_restart && ctx->Version < 31) {
279201e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()");
279301e04c3fSmrg      return;
27947117f1b4Smrg   }
279501e04c3fSmrg
279601e04c3fSmrg   primitive_restart_index(ctx, index);
27977117f1b4Smrg}
27987117f1b4Smrg
27997117f1b4Smrg
28003464ebd5Sriastradhvoid GLAPIENTRY
28017ec681f3Smrg_mesa_VertexAttribDivisor_no_error(GLuint index, GLuint divisor)
28027ec681f3Smrg{
28037ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
28047ec681f3Smrg
28057ec681f3Smrg   const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index);
28067ec681f3Smrg   struct gl_vertex_array_object * const vao = ctx->Array.VAO;
28077ec681f3Smrg
28087ec681f3Smrg   assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
28097ec681f3Smrg
28107ec681f3Smrg   /* The ARB_vertex_attrib_binding spec says:
28117ec681f3Smrg    *
28127ec681f3Smrg    *    "The command
28137ec681f3Smrg    *
28147ec681f3Smrg    *       void VertexAttribDivisor(uint index, uint divisor);
28157ec681f3Smrg    *
28167ec681f3Smrg    *     is equivalent to (assuming no errors are generated):
28177ec681f3Smrg    *
28187ec681f3Smrg    *       VertexAttribBinding(index, index);
28197ec681f3Smrg    *       VertexBindingDivisor(index, divisor);"
28207ec681f3Smrg    */
28217ec681f3Smrg   _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
28227ec681f3Smrg   vertex_binding_divisor(ctx, vao, genericIndex, divisor);
28237ec681f3Smrg}
28247ec681f3Smrg
28257ec681f3Smrg
28267ec681f3Smrg/**
28277ec681f3Smrg * See GL_ARB_instanced_arrays.
28287ec681f3Smrg * Note that the instance divisor only applies to generic arrays, not
28297ec681f3Smrg * the legacy vertex arrays.
28307ec681f3Smrg */
28317ec681f3Smrgvoid GLAPIENTRY
28327ec681f3Smrg_mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
28333464ebd5Sriastradh{
28343464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
28353464ebd5Sriastradh
283601e04c3fSmrg   const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index);
283701e04c3fSmrg   struct gl_vertex_array_object * const vao = ctx->Array.VAO;
28383464ebd5Sriastradh
28397ec681f3Smrg   if (!ctx->Extensions.ARB_instanced_arrays) {
28407ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
28417ec681f3Smrg      return;
28427ec681f3Smrg   }
28437ec681f3Smrg
28447ec681f3Smrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
28457ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE,
28467ec681f3Smrg                  "glVertexAttribDivisor(index = %u)", index);
28477ec681f3Smrg      return;
28487ec681f3Smrg   }
28497ec681f3Smrg
285001e04c3fSmrg   assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
285101e04c3fSmrg
285201e04c3fSmrg   /* The ARB_vertex_attrib_binding spec says:
285301e04c3fSmrg    *
285401e04c3fSmrg    *    "The command
285501e04c3fSmrg    *
285601e04c3fSmrg    *       void VertexAttribDivisor(uint index, uint divisor);
285701e04c3fSmrg    *
285801e04c3fSmrg    *     is equivalent to (assuming no errors are generated):
285901e04c3fSmrg    *
286001e04c3fSmrg    *       VertexAttribBinding(index, index);
286101e04c3fSmrg    *       VertexBindingDivisor(index, divisor);"
286201e04c3fSmrg    */
286301e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
286401e04c3fSmrg   vertex_binding_divisor(ctx, vao, genericIndex, divisor);
28653464ebd5Sriastradh}
28663464ebd5Sriastradh
28673464ebd5Sriastradh
28683464ebd5Sriastradhvoid GLAPIENTRY
28697ec681f3Smrg_mesa_VertexArrayVertexAttribDivisorEXT(GLuint vaobj, GLuint index, GLuint divisor)
28703464ebd5Sriastradh{
28713464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
2872af69d88dSmrg
287301e04c3fSmrg   const gl_vert_attrib genericIndex = VERT_ATTRIB_GENERIC(index);
28747ec681f3Smrg   struct gl_vertex_array_object * vao;
28757ec681f3Smrg   /* The ARB_instanced_arrays spec says:
28767ec681f3Smrg    *
28777ec681f3Smrg    *     "The vertex array object named by vaobj must
28787ec681f3Smrg    *     be generated by GenVertexArrays (and not since deleted);
28797ec681f3Smrg    *     otherwise an INVALID_OPERATION error is generated."
28807ec681f3Smrg    */
28817ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj,
28827ec681f3Smrg                              false,
28837ec681f3Smrg                              "glVertexArrayVertexAttribDivisorEXT");
28847ec681f3Smrg   if (!vao)
28857ec681f3Smrg      return;
28863464ebd5Sriastradh
28873464ebd5Sriastradh   if (!ctx->Extensions.ARB_instanced_arrays) {
28887ec681f3Smrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexArrayVertexAttribDivisorEXT()");
28893464ebd5Sriastradh      return;
28903464ebd5Sriastradh   }
28913464ebd5Sriastradh
2892af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
289301e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
28947ec681f3Smrg                  "glVertexArrayVertexAttribDivisorEXT(index = %u)", index);
28953464ebd5Sriastradh      return;
28963464ebd5Sriastradh   }
28973464ebd5Sriastradh
289801e04c3fSmrg   assert(genericIndex < ARRAY_SIZE(vao->VertexAttrib));
2899af69d88dSmrg
2900af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2901af69d88dSmrg    *
2902af69d88dSmrg    *    "The command
2903af69d88dSmrg    *
2904af69d88dSmrg    *       void VertexAttribDivisor(uint index, uint divisor);
2905af69d88dSmrg    *
2906af69d88dSmrg    *     is equivalent to (assuming no errors are generated):
2907af69d88dSmrg    *
2908af69d88dSmrg    *       VertexAttribBinding(index, index);
2909af69d88dSmrg    *       VertexBindingDivisor(index, divisor);"
2910af69d88dSmrg    */
291101e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao, genericIndex, genericIndex);
291201e04c3fSmrg   vertex_binding_divisor(ctx, vao, genericIndex, divisor);
2913af69d88dSmrg}
2914af69d88dSmrg
2915af69d88dSmrg
29167ec681f3Smrg
291701e04c3fSmrgstatic ALWAYS_INLINE void
291801e04c3fSmrgvertex_array_vertex_buffer(struct gl_context *ctx,
291901e04c3fSmrg                           struct gl_vertex_array_object *vao,
292001e04c3fSmrg                           GLuint bindingIndex, GLuint buffer, GLintptr offset,
292101e04c3fSmrg                           GLsizei stride, bool no_error, const char *func)
2922af69d88dSmrg{
2923af69d88dSmrg   struct gl_buffer_object *vbo;
29247ec681f3Smrg   struct gl_buffer_object *current_buf =
29257ec681f3Smrg      vao->BufferBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj;
29267ec681f3Smrg
29277ec681f3Smrg   if (current_buf && buffer == current_buf->Name) {
29287ec681f3Smrg      vbo = current_buf;
292901e04c3fSmrg   } else if (buffer != 0) {
293001e04c3fSmrg      vbo = _mesa_lookup_bufferobj(ctx, buffer);
2931af69d88dSmrg
293201e04c3fSmrg      if (!no_error && !vbo && _mesa_is_gles31(ctx)) {
293301e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", func);
293401e04c3fSmrg         return;
293501e04c3fSmrg      }
293601e04c3fSmrg      /* From the GL_ARB_vertex_attrib_array spec:
293701e04c3fSmrg       *
293801e04c3fSmrg       *   "[Core profile only:]
293901e04c3fSmrg       *    An INVALID_OPERATION error is generated if buffer is not zero or a
294001e04c3fSmrg       *    name returned from a previous call to GenBuffers, or if such a name
294101e04c3fSmrg       *    has since been deleted with DeleteBuffers.
294201e04c3fSmrg       *
294301e04c3fSmrg       * Otherwise, we fall back to the same compat profile behavior as other
294401e04c3fSmrg       * object references (automatically gen it).
294501e04c3fSmrg       */
294601e04c3fSmrg      if (!_mesa_handle_bind_buffer_gen(ctx, buffer, &vbo, func))
294701e04c3fSmrg         return;
294801e04c3fSmrg   } else {
294901e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
295001e04c3fSmrg       *
295101e04c3fSmrg       *    "If <buffer> is zero, any buffer object attached to this
295201e04c3fSmrg       *     bindpoint is detached."
295301e04c3fSmrg       */
29547ec681f3Smrg      vbo = NULL;
2955af69d88dSmrg   }
2956af69d88dSmrg
295701e04c3fSmrg   _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex),
29587ec681f3Smrg                            vbo, offset, stride, false, false);
295901e04c3fSmrg}
296001e04c3fSmrg
296101e04c3fSmrg
296201e04c3fSmrg/**
296301e04c3fSmrg * GL_ARB_vertex_attrib_binding
296401e04c3fSmrg */
296501e04c3fSmrgstatic void
296601e04c3fSmrgvertex_array_vertex_buffer_err(struct gl_context *ctx,
296701e04c3fSmrg                               struct gl_vertex_array_object *vao,
296801e04c3fSmrg                               GLuint bindingIndex, GLuint buffer,
296901e04c3fSmrg                               GLintptr offset, GLsizei stride,
297001e04c3fSmrg                               const char *func)
297101e04c3fSmrg{
297201e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
297301e04c3fSmrg
2974af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2975af69d88dSmrg    *
2976af69d88dSmrg    *    "An INVALID_VALUE error is generated if <bindingindex> is greater than
2977af69d88dSmrg    *     the value of MAX_VERTEX_ATTRIB_BINDINGS."
2978af69d88dSmrg    */
2979af69d88dSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
2980af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
298101e04c3fSmrg                  "%s(bindingindex=%u > "
2982af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
298301e04c3fSmrg                  func, bindingIndex);
2984af69d88dSmrg      return;
2985af69d88dSmrg   }
2986af69d88dSmrg
2987af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
2988af69d88dSmrg    *
2989af69d88dSmrg    *    "The error INVALID_VALUE is generated if <stride> or <offset>
2990af69d88dSmrg    *     are negative."
2991af69d88dSmrg    */
2992af69d88dSmrg   if (offset < 0) {
2993af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
299401e04c3fSmrg                  "%s(offset=%" PRId64 " < 0)",
299501e04c3fSmrg                  func, (int64_t) offset);
2996af69d88dSmrg      return;
2997af69d88dSmrg   }
2998af69d88dSmrg
2999af69d88dSmrg   if (stride < 0) {
3000af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
300101e04c3fSmrg                  "%s(stride=%d < 0)", func, stride);
3002af69d88dSmrg      return;
3003af69d88dSmrg   }
3004af69d88dSmrg
300501e04c3fSmrg   if (((_mesa_is_desktop_gl(ctx) && ctx->Version >= 44) || _mesa_is_gles31(ctx)) &&
300601e04c3fSmrg       stride > ctx->Const.MaxVertexAttribStride) {
300701e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride=%d > "
300801e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, stride);
300901e04c3fSmrg      return;
3010af69d88dSmrg   }
3011af69d88dSmrg
301201e04c3fSmrg   vertex_array_vertex_buffer(ctx, vao, bindingIndex, buffer, offset,
301301e04c3fSmrg                              stride, false, func);
3014af69d88dSmrg}
3015af69d88dSmrg
3016af69d88dSmrg
3017af69d88dSmrgvoid GLAPIENTRY
301801e04c3fSmrg_mesa_BindVertexBuffer_no_error(GLuint bindingIndex, GLuint buffer,
301901e04c3fSmrg                                GLintptr offset, GLsizei stride)
3020af69d88dSmrg{
3021af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
302201e04c3fSmrg   vertex_array_vertex_buffer(ctx, ctx->Array.VAO, bindingIndex,
302301e04c3fSmrg                              buffer, offset, stride, true,
302401e04c3fSmrg                              "glBindVertexBuffer");
302501e04c3fSmrg}
3026af69d88dSmrg
302701e04c3fSmrg
302801e04c3fSmrgvoid GLAPIENTRY
302901e04c3fSmrg_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
303001e04c3fSmrg                       GLsizei stride)
303101e04c3fSmrg{
303201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
3033af69d88dSmrg
3034af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
3035af69d88dSmrg    *
303601e04c3fSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
303701e04c3fSmrg    *     is bound."
3038af69d88dSmrg    */
303901e04c3fSmrg   if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
3040af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
3041af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
304201e04c3fSmrg                  "glBindVertexBuffer(No array object bound)");
3043af69d88dSmrg      return;
3044af69d88dSmrg   }
3045af69d88dSmrg
304601e04c3fSmrg   vertex_array_vertex_buffer_err(ctx, ctx->Array.VAO, bindingIndex,
304701e04c3fSmrg                                  buffer, offset, stride,
304801e04c3fSmrg                                  "glBindVertexBuffer");
304901e04c3fSmrg}
305001e04c3fSmrg
305101e04c3fSmrg
305201e04c3fSmrgvoid GLAPIENTRY
305301e04c3fSmrg_mesa_VertexArrayVertexBuffer_no_error(GLuint vaobj, GLuint bindingIndex,
305401e04c3fSmrg                                       GLuint buffer, GLintptr offset,
305501e04c3fSmrg                                       GLsizei stride)
305601e04c3fSmrg{
305701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
305801e04c3fSmrg
305901e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
306001e04c3fSmrg   vertex_array_vertex_buffer(ctx, vao, bindingIndex, buffer, offset,
306101e04c3fSmrg                              stride, true, "glVertexArrayVertexBuffer");
306201e04c3fSmrg}
306301e04c3fSmrg
306401e04c3fSmrg
306501e04c3fSmrgvoid GLAPIENTRY
306601e04c3fSmrg_mesa_VertexArrayVertexBuffer(GLuint vaobj, GLuint bindingIndex, GLuint buffer,
306701e04c3fSmrg                              GLintptr offset, GLsizei stride)
306801e04c3fSmrg{
306901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
307001e04c3fSmrg   struct gl_vertex_array_object *vao;
307101e04c3fSmrg
307201e04c3fSmrg   /* The ARB_direct_state_access specification says:
3073af69d88dSmrg    *
307401e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
307501e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
307601e04c3fSmrg    *    existing vertex array object."
3077af69d88dSmrg    */
30787ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayVertexBuffer");
307901e04c3fSmrg   if (!vao)
3080af69d88dSmrg      return;
308101e04c3fSmrg
308201e04c3fSmrg   vertex_array_vertex_buffer_err(ctx, vao, bindingIndex, buffer, offset,
308301e04c3fSmrg                                  stride, "glVertexArrayVertexBuffer");
308401e04c3fSmrg}
308501e04c3fSmrg
308601e04c3fSmrg
30877ec681f3Smrgvoid GLAPIENTRY
30887ec681f3Smrg_mesa_VertexArrayBindVertexBufferEXT(GLuint vaobj, GLuint bindingIndex, GLuint buffer,
30897ec681f3Smrg                                     GLintptr offset, GLsizei stride)
30907ec681f3Smrg{
30917ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
30927ec681f3Smrg   struct gl_vertex_array_object *vao;
30937ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, true, "glVertexArrayBindVertexBufferEXT");
30947ec681f3Smrg   if (!vao)
30957ec681f3Smrg      return;
30967ec681f3Smrg
30977ec681f3Smrg   vertex_array_vertex_buffer_err(ctx, vao, bindingIndex, buffer, offset,
30987ec681f3Smrg                                  stride, "glVertexArrayBindVertexBufferEXT");
30997ec681f3Smrg}
31007ec681f3Smrg
31017ec681f3Smrg
310201e04c3fSmrgstatic ALWAYS_INLINE void
310301e04c3fSmrgvertex_array_vertex_buffers(struct gl_context *ctx,
310401e04c3fSmrg                            struct gl_vertex_array_object *vao,
310501e04c3fSmrg                            GLuint first, GLsizei count, const GLuint *buffers,
310601e04c3fSmrg                            const GLintptr *offsets, const GLsizei *strides,
310701e04c3fSmrg                            bool no_error, const char *func)
310801e04c3fSmrg{
310901e04c3fSmrg   GLint i;
3110af69d88dSmrg
3111af69d88dSmrg   if (!buffers) {
3112af69d88dSmrg      /**
3113af69d88dSmrg       * The ARB_multi_bind spec says:
3114af69d88dSmrg       *
3115af69d88dSmrg       *    "If <buffers> is NULL, each affected vertex buffer binding point
3116af69d88dSmrg       *     from <first> through <first>+<count>-1 will be reset to have no
3117af69d88dSmrg       *     bound buffer object.  In this case, the offsets and strides
3118af69d88dSmrg       *     associated with the binding points are set to default values,
3119af69d88dSmrg       *     ignoring <offsets> and <strides>."
3120af69d88dSmrg       */
3121af69d88dSmrg      for (i = 0; i < count; i++)
312201e04c3fSmrg         _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
31237ec681f3Smrg                                  NULL, 0, 16, false, false);
3124af69d88dSmrg
3125af69d88dSmrg      return;
3126af69d88dSmrg   }
3127af69d88dSmrg
3128af69d88dSmrg   /* Note that the error semantics for multi-bind commands differ from
3129af69d88dSmrg    * those of other GL commands.
3130af69d88dSmrg    *
3131af69d88dSmrg    * The Issues section in the ARB_multi_bind spec says:
3132af69d88dSmrg    *
3133af69d88dSmrg    *    "(11) Typically, OpenGL specifies that if an error is generated by
3134af69d88dSmrg    *          a command, that command has no effect.  This is somewhat
3135af69d88dSmrg    *          unfortunate for multi-bind commands, because it would require
3136af69d88dSmrg    *          a first pass to scan the entire list of bound objects for
3137af69d88dSmrg    *          errors and then a second pass to actually perform the
3138af69d88dSmrg    *          bindings.  Should we have different error semantics?
3139af69d88dSmrg    *
3140af69d88dSmrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
3141af69d88dSmrg    *       one of the <count> binding points are invalid, that binding
3142af69d88dSmrg    *       point is not updated and an error will be generated.  However,
3143af69d88dSmrg    *       other binding points in the same command will be updated if
3144af69d88dSmrg    *       their parameters are valid and no other error occurs."
3145af69d88dSmrg    */
3146af69d88dSmrg
31477ec681f3Smrg   _mesa_HashLockMaybeLocked(ctx->Shared->BufferObjects,
31487ec681f3Smrg                             ctx->BufferObjectsLocked);
3149af69d88dSmrg
3150af69d88dSmrg   for (i = 0; i < count; i++) {
3151af69d88dSmrg      struct gl_buffer_object *vbo;
3152af69d88dSmrg
315301e04c3fSmrg      if (!no_error) {
315401e04c3fSmrg         /* The ARB_multi_bind spec says:
315501e04c3fSmrg          *
315601e04c3fSmrg          *    "An INVALID_VALUE error is generated if any value in
315701e04c3fSmrg          *     <offsets> or <strides> is negative (per binding)."
315801e04c3fSmrg          */
315901e04c3fSmrg         if (offsets[i] < 0) {
316001e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
316101e04c3fSmrg                        "%s(offsets[%u]=%" PRId64 " < 0)",
316201e04c3fSmrg                        func, i, (int64_t) offsets[i]);
316301e04c3fSmrg            continue;
316401e04c3fSmrg         }
3165af69d88dSmrg
316601e04c3fSmrg         if (strides[i] < 0) {
316701e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
316801e04c3fSmrg                        "%s(strides[%u]=%d < 0)",
316901e04c3fSmrg                        func, i, strides[i]);
317001e04c3fSmrg            continue;
317101e04c3fSmrg         }
317201e04c3fSmrg
317301e04c3fSmrg         if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 44 &&
317401e04c3fSmrg             strides[i] > ctx->Const.MaxVertexAttribStride) {
317501e04c3fSmrg            _mesa_error(ctx, GL_INVALID_VALUE,
317601e04c3fSmrg                        "%s(strides[%u]=%d > "
317701e04c3fSmrg                        "GL_MAX_VERTEX_ATTRIB_STRIDE)", func, i, strides[i]);
317801e04c3fSmrg            continue;
317901e04c3fSmrg         }
3180af69d88dSmrg      }
3181af69d88dSmrg
3182af69d88dSmrg      if (buffers[i]) {
3183af69d88dSmrg         struct gl_vertex_buffer_binding *binding =
318401e04c3fSmrg            &vao->BufferBinding[VERT_ATTRIB_GENERIC(first + i)];
3185af69d88dSmrg
31867ec681f3Smrg         if (buffers[i] == 0)
31877ec681f3Smrg            vbo = NULL;
31887ec681f3Smrg         else if (binding->BufferObj && binding->BufferObj->Name == buffers[i])
3189af69d88dSmrg            vbo = binding->BufferObj;
31907ec681f3Smrg         else {
31917ec681f3Smrg            bool error;
31927ec681f3Smrg            vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i, func,
31937ec681f3Smrg                                                    &error);
31947ec681f3Smrg            if (error)
31957ec681f3Smrg               continue;
31967ec681f3Smrg         }
3197af69d88dSmrg      } else {
31987ec681f3Smrg         vbo = NULL;
3199af69d88dSmrg      }
3200af69d88dSmrg
320101e04c3fSmrg      _mesa_bind_vertex_buffer(ctx, vao, VERT_ATTRIB_GENERIC(first + i),
32027ec681f3Smrg                               vbo, offsets[i], strides[i], false, false);
3203af69d88dSmrg   }
3204af69d88dSmrg
32057ec681f3Smrg   _mesa_HashUnlockMaybeLocked(ctx->Shared->BufferObjects,
32067ec681f3Smrg                               ctx->BufferObjectsLocked);
3207af69d88dSmrg}
3208af69d88dSmrg
3209af69d88dSmrg
321001e04c3fSmrgstatic void
321101e04c3fSmrgvertex_array_vertex_buffers_err(struct gl_context *ctx,
321201e04c3fSmrg                                struct gl_vertex_array_object *vao,
321301e04c3fSmrg                                GLuint first, GLsizei count,
321401e04c3fSmrg                                const GLuint *buffers, const GLintptr *offsets,
321501e04c3fSmrg                                const GLsizei *strides, const char *func)
3216af69d88dSmrg{
3217af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3218af69d88dSmrg
321901e04c3fSmrg   /* The ARB_multi_bind spec says:
3220af69d88dSmrg    *
322101e04c3fSmrg    *    "An INVALID_OPERATION error is generated if <first> + <count>
322201e04c3fSmrg    *     is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS."
3223af69d88dSmrg    */
322401e04c3fSmrg   if (first + count > ctx->Const.MaxVertexAttribBindings) {
3225af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
322601e04c3fSmrg                  "%s(first=%u + count=%d > the value of "
322701e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)",
322801e04c3fSmrg                  func, first, count, ctx->Const.MaxVertexAttribBindings);
3229af69d88dSmrg      return;
3230af69d88dSmrg   }
3231af69d88dSmrg
323201e04c3fSmrg   vertex_array_vertex_buffers(ctx, vao, first, count, buffers, offsets,
323301e04c3fSmrg                               strides, false, func);
323401e04c3fSmrg}
323501e04c3fSmrg
3236af69d88dSmrg
323701e04c3fSmrgvoid GLAPIENTRY
323801e04c3fSmrg_mesa_BindVertexBuffers_no_error(GLuint first, GLsizei count,
323901e04c3fSmrg                                 const GLuint *buffers, const GLintptr *offsets,
324001e04c3fSmrg                                 const GLsizei *strides)
324101e04c3fSmrg{
324201e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
3243af69d88dSmrg
324401e04c3fSmrg   vertex_array_vertex_buffers(ctx, ctx->Array.VAO, first, count,
324501e04c3fSmrg                               buffers, offsets, strides, true,
324601e04c3fSmrg                               "glBindVertexBuffers");
3247af69d88dSmrg}
3248af69d88dSmrg
3249af69d88dSmrg
3250af69d88dSmrgvoid GLAPIENTRY
325101e04c3fSmrg_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
325201e04c3fSmrg                        const GLintptr *offsets, const GLsizei *strides)
3253af69d88dSmrg{
3254af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
3255af69d88dSmrg
3256af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
3257af69d88dSmrg    *
325801e04c3fSmrg    *    "An INVALID_OPERATION error is generated if no
325901e04c3fSmrg    *     vertex array object is bound."
3260af69d88dSmrg    */
3261af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
3262af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
3263af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
326401e04c3fSmrg                  "glBindVertexBuffers(No array object bound)");
3265af69d88dSmrg      return;
3266af69d88dSmrg   }
3267af69d88dSmrg
326801e04c3fSmrg   vertex_array_vertex_buffers_err(ctx, ctx->Array.VAO, first, count,
326901e04c3fSmrg                                   buffers, offsets, strides,
327001e04c3fSmrg                                   "glBindVertexBuffers");
327101e04c3fSmrg}
327201e04c3fSmrg
327301e04c3fSmrg
32747ec681f3Smrgvoid
32757ec681f3Smrg_mesa_InternalBindVertexBuffers(struct gl_context *ctx,
32767ec681f3Smrg                                const struct glthread_attrib_binding *buffers,
32777ec681f3Smrg                                GLbitfield buffer_mask,
32787ec681f3Smrg                                GLboolean restore_pointers)
32797ec681f3Smrg{
32807ec681f3Smrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
32817ec681f3Smrg   unsigned param_index = 0;
32827ec681f3Smrg
32837ec681f3Smrg   if (restore_pointers) {
32847ec681f3Smrg      while (buffer_mask) {
32857ec681f3Smrg         unsigned i = u_bit_scan(&buffer_mask);
32867ec681f3Smrg
32877ec681f3Smrg         _mesa_bind_vertex_buffer(ctx, vao, i, NULL,
32887ec681f3Smrg                                  (GLintptr)buffers[param_index].original_pointer,
32897ec681f3Smrg                                  vao->BufferBinding[i].Stride, false, false);
32907ec681f3Smrg         param_index++;
32917ec681f3Smrg      }
32927ec681f3Smrg      return;
32937ec681f3Smrg   }
32947ec681f3Smrg
32957ec681f3Smrg   while (buffer_mask) {
32967ec681f3Smrg      unsigned i = u_bit_scan(&buffer_mask);
32977ec681f3Smrg      struct gl_buffer_object *buf = buffers[param_index].buffer;
32987ec681f3Smrg
32997ec681f3Smrg      /* The buffer reference is passed to _mesa_bind_vertex_buffer. */
33007ec681f3Smrg      _mesa_bind_vertex_buffer(ctx, vao, i, buf, buffers[param_index].offset,
33017ec681f3Smrg                               vao->BufferBinding[i].Stride, true, true);
33027ec681f3Smrg      param_index++;
33037ec681f3Smrg   }
33047ec681f3Smrg}
33057ec681f3Smrg
33067ec681f3Smrg
330701e04c3fSmrgvoid GLAPIENTRY
330801e04c3fSmrg_mesa_VertexArrayVertexBuffers_no_error(GLuint vaobj, GLuint first,
330901e04c3fSmrg                                        GLsizei count, const GLuint *buffers,
331001e04c3fSmrg                                        const GLintptr *offsets,
331101e04c3fSmrg                                        const GLsizei *strides)
331201e04c3fSmrg{
331301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
331401e04c3fSmrg
331501e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
331601e04c3fSmrg   vertex_array_vertex_buffers(ctx, vao, first, count,
331701e04c3fSmrg                               buffers, offsets, strides, true,
331801e04c3fSmrg                               "glVertexArrayVertexBuffers");
331901e04c3fSmrg}
332001e04c3fSmrg
332101e04c3fSmrg
332201e04c3fSmrgvoid GLAPIENTRY
332301e04c3fSmrg_mesa_VertexArrayVertexBuffers(GLuint vaobj, GLuint first, GLsizei count,
332401e04c3fSmrg                               const GLuint *buffers,
332501e04c3fSmrg                               const GLintptr *offsets, const GLsizei *strides)
332601e04c3fSmrg{
332701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
332801e04c3fSmrg   struct gl_vertex_array_object *vao;
332901e04c3fSmrg
333001e04c3fSmrg   /* The ARB_direct_state_access specification says:
3331af69d88dSmrg    *
333201e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayVertexBuffer
333301e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
333401e04c3fSmrg    *    existing vertex array object."
3335af69d88dSmrg    */
33367ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayVertexBuffers");
333701e04c3fSmrg   if (!vao)
3338af69d88dSmrg      return;
333901e04c3fSmrg
334001e04c3fSmrg   vertex_array_vertex_buffers_err(ctx, vao, first, count,
334101e04c3fSmrg                                   buffers, offsets, strides,
334201e04c3fSmrg                                   "glVertexArrayVertexBuffers");
334301e04c3fSmrg}
334401e04c3fSmrg
334501e04c3fSmrg
334601e04c3fSmrgstatic void
334701e04c3fSmrgvertex_attrib_format(GLuint attribIndex, GLint size, GLenum type,
334801e04c3fSmrg                     GLboolean normalized, GLboolean integer,
334901e04c3fSmrg                     GLboolean doubles, GLbitfield legalTypes,
335001e04c3fSmrg                     GLsizei sizeMax, GLuint relativeOffset,
335101e04c3fSmrg                     const char *func)
335201e04c3fSmrg{
335301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
335401e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
335501e04c3fSmrg
335601e04c3fSmrg   GLenum format = get_array_format(ctx, sizeMax, &size);
335701e04c3fSmrg
335801e04c3fSmrg   if (!_mesa_is_no_error_enabled(ctx)) {
335901e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
336001e04c3fSmrg       *
336101e04c3fSmrg       *    "An INVALID_OPERATION error is generated under any of the
336201e04c3fSmrg       *    following conditions:
336301e04c3fSmrg       *     - if no vertex array object is currently bound (see section
336401e04c3fSmrg       *       2.10);
336501e04c3fSmrg       *     - ..."
336601e04c3fSmrg       *
336701e04c3fSmrg       * This error condition only applies to VertexAttribFormat and
336801e04c3fSmrg       * VertexAttribIFormat in the extension spec, but we assume that this
336901e04c3fSmrg       * is an oversight.  In the OpenGL 4.3 (Core Profile) spec, it applies
337001e04c3fSmrg       * to all three functions.
337101e04c3fSmrg       */
337201e04c3fSmrg      if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
337301e04c3fSmrg          ctx->Array.VAO == ctx->Array.DefaultVAO) {
337401e04c3fSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
337501e04c3fSmrg                     "%s(No array object bound)", func);
337601e04c3fSmrg         return;
337701e04c3fSmrg      }
337801e04c3fSmrg
337901e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
338001e04c3fSmrg       *
338101e04c3fSmrg       *   "The error INVALID_VALUE is generated if index is greater than or
338201e04c3fSmrg       *   equal to the value of MAX_VERTEX_ATTRIBS."
338301e04c3fSmrg       */
338401e04c3fSmrg      if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
338501e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
338601e04c3fSmrg                     "%s(attribindex=%u > "
338701e04c3fSmrg                     "GL_MAX_VERTEX_ATTRIBS)",
338801e04c3fSmrg                     func, attribIndex);
338901e04c3fSmrg         return;
339001e04c3fSmrg      }
339101e04c3fSmrg
339201e04c3fSmrg      if (!validate_array_format(ctx, func, ctx->Array.VAO,
339301e04c3fSmrg                                 VERT_ATTRIB_GENERIC(attribIndex),
339401e04c3fSmrg                                 legalTypes, 1, sizeMax, size, type,
339501e04c3fSmrg                                 normalized, integer, doubles, relativeOffset,
339601e04c3fSmrg                                 format)) {
339701e04c3fSmrg         return;
339801e04c3fSmrg      }
3399af69d88dSmrg   }
3400af69d88dSmrg
340101e04c3fSmrg   _mesa_update_array_format(ctx, ctx->Array.VAO,
340201e04c3fSmrg                             VERT_ATTRIB_GENERIC(attribIndex), size, type,
340301e04c3fSmrg                             format, normalized, integer, doubles,
340401e04c3fSmrg                             relativeOffset);
340501e04c3fSmrg}
340601e04c3fSmrg
340701e04c3fSmrg
340801e04c3fSmrgvoid GLAPIENTRY
340901e04c3fSmrg_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
341001e04c3fSmrg                         GLboolean normalized, GLuint relativeOffset)
341101e04c3fSmrg{
341201e04c3fSmrg   vertex_attrib_format(attribIndex, size, type, normalized,
341301e04c3fSmrg                        GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
341401e04c3fSmrg                        BGRA_OR_4, relativeOffset,
341501e04c3fSmrg                        "glVertexAttribFormat");
341601e04c3fSmrg}
341701e04c3fSmrg
3418af69d88dSmrg
341901e04c3fSmrgvoid GLAPIENTRY
342001e04c3fSmrg_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
342101e04c3fSmrg                          GLuint relativeOffset)
342201e04c3fSmrg{
342301e04c3fSmrg   vertex_attrib_format(attribIndex, size, type, GL_FALSE,
342401e04c3fSmrg                        GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK, 4,
342501e04c3fSmrg                        relativeOffset, "glVertexAttribIFormat");
3426af69d88dSmrg}
3427af69d88dSmrg
3428af69d88dSmrg
3429af69d88dSmrgvoid GLAPIENTRY
3430af69d88dSmrg_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
3431af69d88dSmrg                          GLuint relativeOffset)
3432af69d88dSmrg{
343301e04c3fSmrg   vertex_attrib_format(attribIndex, size, type, GL_FALSE, GL_FALSE,
343401e04c3fSmrg                        GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK, 4,
343501e04c3fSmrg                        relativeOffset, "glVertexAttribLFormat");
343601e04c3fSmrg}
343701e04c3fSmrg
3438af69d88dSmrg
343901e04c3fSmrgstatic void
34407ec681f3Smrgvertex_array_attrib_format(GLuint vaobj, bool isExtDsa, GLuint attribIndex,
34417ec681f3Smrg                           GLint size, GLenum type, GLboolean normalized,
344201e04c3fSmrg                           GLboolean integer, GLboolean doubles,
344301e04c3fSmrg                           GLbitfield legalTypes, GLsizei sizeMax,
344401e04c3fSmrg                           GLuint relativeOffset, const char *func)
344501e04c3fSmrg{
3446af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
344701e04c3fSmrg   struct gl_vertex_array_object *vao;
344801e04c3fSmrg
3449af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
3450af69d88dSmrg
345101e04c3fSmrg   GLenum format = get_array_format(ctx, sizeMax, &size);
345201e04c3fSmrg
345301e04c3fSmrg   if (_mesa_is_no_error_enabled(ctx)) {
345401e04c3fSmrg      vao = _mesa_lookup_vao(ctx, vaobj);
345501e04c3fSmrg      if (!vao)
345601e04c3fSmrg         return;
345701e04c3fSmrg   } else {
34587ec681f3Smrg      vao = _mesa_lookup_vao_err(ctx, vaobj, isExtDsa, func);
345901e04c3fSmrg      if (!vao)
346001e04c3fSmrg         return;
346101e04c3fSmrg
346201e04c3fSmrg      /* The ARB_vertex_attrib_binding spec says:
346301e04c3fSmrg       *
346401e04c3fSmrg       *   "The error INVALID_VALUE is generated if index is greater than or
346501e04c3fSmrg       *   equal to the value of MAX_VERTEX_ATTRIBS."
346601e04c3fSmrg       */
346701e04c3fSmrg      if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
346801e04c3fSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
346901e04c3fSmrg                     "%s(attribindex=%u > GL_MAX_VERTEX_ATTRIBS)",
347001e04c3fSmrg                     func, attribIndex);
347101e04c3fSmrg         return;
347201e04c3fSmrg      }
347301e04c3fSmrg
347401e04c3fSmrg      if (!validate_array_format(ctx, func, vao,
347501e04c3fSmrg                                 VERT_ATTRIB_GENERIC(attribIndex),
347601e04c3fSmrg                                 legalTypes, 1, sizeMax, size, type,
347701e04c3fSmrg                                 normalized, integer, doubles, relativeOffset,
347801e04c3fSmrg                                 format)) {
347901e04c3fSmrg         return;
348001e04c3fSmrg      }
3481af69d88dSmrg   }
3482af69d88dSmrg
348301e04c3fSmrg   _mesa_update_array_format(ctx, vao, VERT_ATTRIB_GENERIC(attribIndex), size,
348401e04c3fSmrg                             type, format, normalized, integer, doubles,
348501e04c3fSmrg                             relativeOffset);
348601e04c3fSmrg}
348701e04c3fSmrg
348801e04c3fSmrg
348901e04c3fSmrgvoid GLAPIENTRY
349001e04c3fSmrg_mesa_VertexArrayAttribFormat(GLuint vaobj, GLuint attribIndex, GLint size,
349101e04c3fSmrg                              GLenum type, GLboolean normalized,
349201e04c3fSmrg                              GLuint relativeOffset)
349301e04c3fSmrg{
34947ec681f3Smrg   vertex_array_attrib_format(vaobj, false, attribIndex, size, type, normalized,
349501e04c3fSmrg                              GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
349601e04c3fSmrg                              BGRA_OR_4, relativeOffset,
349701e04c3fSmrg                              "glVertexArrayAttribFormat");
349801e04c3fSmrg}
349901e04c3fSmrg
350001e04c3fSmrg
35017ec681f3Smrgvoid GLAPIENTRY
35027ec681f3Smrg_mesa_VertexArrayVertexAttribFormatEXT(GLuint vaobj, GLuint attribIndex, GLint size,
35037ec681f3Smrg                                       GLenum type, GLboolean normalized,
35047ec681f3Smrg                                       GLuint relativeOffset)
35057ec681f3Smrg{
35067ec681f3Smrg   vertex_array_attrib_format(vaobj, true, attribIndex, size, type, normalized,
35077ec681f3Smrg                              GL_FALSE, GL_FALSE, ATTRIB_FORMAT_TYPES_MASK,
35087ec681f3Smrg                              BGRA_OR_4, relativeOffset,
35097ec681f3Smrg                              "glVertexArrayVertexAttribFormatEXT");
35107ec681f3Smrg}
35117ec681f3Smrg
35127ec681f3Smrg
351301e04c3fSmrgvoid GLAPIENTRY
351401e04c3fSmrg_mesa_VertexArrayAttribIFormat(GLuint vaobj, GLuint attribIndex,
351501e04c3fSmrg                               GLint size, GLenum type,
351601e04c3fSmrg                               GLuint relativeOffset)
351701e04c3fSmrg{
35187ec681f3Smrg   vertex_array_attrib_format(vaobj, false, attribIndex, size, type, GL_FALSE,
351901e04c3fSmrg                              GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK,
352001e04c3fSmrg                              4, relativeOffset,
352101e04c3fSmrg                              "glVertexArrayAttribIFormat");
352201e04c3fSmrg}
352301e04c3fSmrg
352401e04c3fSmrg
35257ec681f3Smrgvoid GLAPIENTRY
35267ec681f3Smrg_mesa_VertexArrayVertexAttribIFormatEXT(GLuint vaobj, GLuint attribIndex,
35277ec681f3Smrg                                        GLint size, GLenum type,
35287ec681f3Smrg                                        GLuint relativeOffset)
35297ec681f3Smrg{
35307ec681f3Smrg   vertex_array_attrib_format(vaobj, true, attribIndex, size, type, GL_FALSE,
35317ec681f3Smrg                              GL_TRUE, GL_FALSE, ATTRIB_IFORMAT_TYPES_MASK,
35327ec681f3Smrg                              4, relativeOffset,
35337ec681f3Smrg                              "glVertexArrayVertexAttribIFormatEXT");
35347ec681f3Smrg}
35357ec681f3Smrg
35367ec681f3Smrg
353701e04c3fSmrgvoid GLAPIENTRY
353801e04c3fSmrg_mesa_VertexArrayAttribLFormat(GLuint vaobj, GLuint attribIndex,
353901e04c3fSmrg                               GLint size, GLenum type,
354001e04c3fSmrg                               GLuint relativeOffset)
354101e04c3fSmrg{
35427ec681f3Smrg   vertex_array_attrib_format(vaobj, false, attribIndex, size, type, GL_FALSE,
354301e04c3fSmrg                              GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK,
354401e04c3fSmrg                              4, relativeOffset,
354501e04c3fSmrg                              "glVertexArrayAttribLFormat");
354601e04c3fSmrg}
354701e04c3fSmrg
354801e04c3fSmrg
35497ec681f3Smrgvoid GLAPIENTRY
35507ec681f3Smrg_mesa_VertexArrayVertexAttribLFormatEXT(GLuint vaobj, GLuint attribIndex,
35517ec681f3Smrg                                        GLint size, GLenum type,
35527ec681f3Smrg                                        GLuint relativeOffset)
35537ec681f3Smrg{
35547ec681f3Smrg   vertex_array_attrib_format(vaobj, true, attribIndex, size, type, GL_FALSE,
35557ec681f3Smrg                              GL_FALSE, GL_TRUE, ATTRIB_LFORMAT_TYPES_MASK,
35567ec681f3Smrg                              4, relativeOffset,
35577ec681f3Smrg                              "glVertexArrayVertexAttribLFormatEXT");
35587ec681f3Smrg}
35597ec681f3Smrg
35607ec681f3Smrg
356101e04c3fSmrgstatic void
356201e04c3fSmrgvertex_array_attrib_binding(struct gl_context *ctx,
356301e04c3fSmrg                            struct gl_vertex_array_object *vao,
356401e04c3fSmrg                            GLuint attribIndex, GLuint bindingIndex,
356501e04c3fSmrg                            const char *func)
356601e04c3fSmrg{
356701e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
356801e04c3fSmrg
3569af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
3570af69d88dSmrg    *
357101e04c3fSmrg    *    "<attribindex> must be less than the value of MAX_VERTEX_ATTRIBS and
357201e04c3fSmrg    *     <bindingindex> must be less than the value of
357301e04c3fSmrg    *     MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE
357401e04c3fSmrg    *     is generated."
3575af69d88dSmrg    */
3576af69d88dSmrg   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
3577af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
357801e04c3fSmrg                  "%s(attribindex=%u >= "
3579af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIBS)",
358001e04c3fSmrg                  func, attribIndex);
358101e04c3fSmrg      return;
358201e04c3fSmrg   }
358301e04c3fSmrg
358401e04c3fSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
358501e04c3fSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
358601e04c3fSmrg                  "%s(bindingindex=%u >= "
358701e04c3fSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
358801e04c3fSmrg                  func, bindingIndex);
3589af69d88dSmrg      return;
3590af69d88dSmrg   }
3591af69d88dSmrg
359201e04c3fSmrg   assert(VERT_ATTRIB_GENERIC(attribIndex) < ARRAY_SIZE(vao->VertexAttrib));
359301e04c3fSmrg
359401e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao,
359501e04c3fSmrg                               VERT_ATTRIB_GENERIC(attribIndex),
359601e04c3fSmrg                               VERT_ATTRIB_GENERIC(bindingIndex));
359701e04c3fSmrg}
359801e04c3fSmrg
3599af69d88dSmrg
360001e04c3fSmrgvoid GLAPIENTRY
360101e04c3fSmrg_mesa_VertexAttribBinding_no_error(GLuint attribIndex, GLuint bindingIndex)
360201e04c3fSmrg{
360301e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
360401e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, ctx->Array.VAO,
360501e04c3fSmrg                               VERT_ATTRIB_GENERIC(attribIndex),
360601e04c3fSmrg                               VERT_ATTRIB_GENERIC(bindingIndex));
3607af69d88dSmrg}
3608af69d88dSmrg
3609af69d88dSmrg
3610af69d88dSmrgvoid GLAPIENTRY
3611af69d88dSmrg_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
3612af69d88dSmrg{
3613af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
3614af69d88dSmrg
3615af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
3616af69d88dSmrg    *
3617af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
3618af69d88dSmrg    *     is bound."
3619af69d88dSmrg    */
362001e04c3fSmrg   if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
3621af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
3622af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3623af69d88dSmrg                  "glVertexAttribBinding(No array object bound)");
3624af69d88dSmrg      return;
3625af69d88dSmrg   }
3626af69d88dSmrg
362701e04c3fSmrg   vertex_array_attrib_binding(ctx, ctx->Array.VAO,
362801e04c3fSmrg                               attribIndex, bindingIndex,
362901e04c3fSmrg                               "glVertexAttribBinding");
363001e04c3fSmrg}
363101e04c3fSmrg
363201e04c3fSmrg
363301e04c3fSmrgvoid GLAPIENTRY
363401e04c3fSmrg_mesa_VertexArrayAttribBinding_no_error(GLuint vaobj, GLuint attribIndex,
363501e04c3fSmrg                                        GLuint bindingIndex)
363601e04c3fSmrg{
363701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
363801e04c3fSmrg
363901e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
364001e04c3fSmrg   _mesa_vertex_attrib_binding(ctx, vao,
364101e04c3fSmrg                               VERT_ATTRIB_GENERIC(attribIndex),
364201e04c3fSmrg                               VERT_ATTRIB_GENERIC(bindingIndex));
364301e04c3fSmrg}
364401e04c3fSmrg
364501e04c3fSmrg
364601e04c3fSmrgvoid GLAPIENTRY
364701e04c3fSmrg_mesa_VertexArrayAttribBinding(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex)
364801e04c3fSmrg{
364901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
365001e04c3fSmrg   struct gl_vertex_array_object *vao;
365101e04c3fSmrg
365201e04c3fSmrg   /* The ARB_direct_state_access specification says:
3653af69d88dSmrg    *
365401e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayAttribBinding
365501e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
365601e04c3fSmrg    *    existing vertex array object."
3657af69d88dSmrg    */
36587ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayAttribBinding");
365901e04c3fSmrg   if (!vao)
366001e04c3fSmrg      return;
366101e04c3fSmrg
366201e04c3fSmrg   vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex,
366301e04c3fSmrg                               "glVertexArrayAttribBinding");
366401e04c3fSmrg}
366501e04c3fSmrg
366601e04c3fSmrg
36677ec681f3Smrgvoid GLAPIENTRY
36687ec681f3Smrg_mesa_VertexArrayVertexAttribBindingEXT(GLuint vaobj, GLuint attribIndex, GLuint bindingIndex)
36697ec681f3Smrg{
36707ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
36717ec681f3Smrg   struct gl_vertex_array_object *vao;
36727ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, true, "glVertexArrayVertexAttribBindingEXT");
36737ec681f3Smrg   if (!vao)
36747ec681f3Smrg      return;
36757ec681f3Smrg
36767ec681f3Smrg   vertex_array_attrib_binding(ctx, vao, attribIndex, bindingIndex,
36777ec681f3Smrg                               "glVertexArrayVertexAttribBindingEXT");
36787ec681f3Smrg}
36797ec681f3Smrg
36807ec681f3Smrg
368101e04c3fSmrgstatic void
368201e04c3fSmrgvertex_array_binding_divisor(struct gl_context *ctx,
368301e04c3fSmrg                             struct gl_vertex_array_object *vao,
368401e04c3fSmrg                             GLuint bindingIndex, GLuint divisor,
368501e04c3fSmrg                             const char *func)
368601e04c3fSmrg{
368701e04c3fSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
368801e04c3fSmrg
368901e04c3fSmrg   if (!ctx->Extensions.ARB_instanced_arrays) {
369001e04c3fSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", func);
3691af69d88dSmrg      return;
3692af69d88dSmrg   }
3693af69d88dSmrg
369401e04c3fSmrg   /* The ARB_vertex_attrib_binding spec says:
369501e04c3fSmrg    *
369601e04c3fSmrg    *    "An INVALID_VALUE error is generated if <bindingindex> is greater
369701e04c3fSmrg    *     than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS."
369801e04c3fSmrg    */
3699af69d88dSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
3700af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
370101e04c3fSmrg                  "%s(bindingindex=%u > "
3702af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
370301e04c3fSmrg                  func, bindingIndex);
3704af69d88dSmrg      return;
3705af69d88dSmrg   }
3706af69d88dSmrg
370701e04c3fSmrg   vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
370801e04c3fSmrg}
370901e04c3fSmrg
3710af69d88dSmrg
371101e04c3fSmrgvoid GLAPIENTRY
371201e04c3fSmrg_mesa_VertexBindingDivisor_no_error(GLuint bindingIndex, GLuint divisor)
371301e04c3fSmrg{
371401e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
371501e04c3fSmrg   vertex_binding_divisor(ctx, ctx->Array.VAO,
371601e04c3fSmrg                          VERT_ATTRIB_GENERIC(bindingIndex), divisor);
3717af69d88dSmrg}
3718af69d88dSmrg
3719af69d88dSmrg
3720af69d88dSmrgvoid GLAPIENTRY
3721af69d88dSmrg_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
3722af69d88dSmrg{
3723af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
3724af69d88dSmrg
3725af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
3726af69d88dSmrg    *
3727af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
3728af69d88dSmrg    *     is bound."
3729af69d88dSmrg    */
373001e04c3fSmrg   if ((ctx->API == API_OPENGL_CORE || _mesa_is_gles31(ctx)) &&
3731af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
3732af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
3733af69d88dSmrg                  "glVertexBindingDivisor(No array object bound)");
3734af69d88dSmrg      return;
3735af69d88dSmrg   }
3736af69d88dSmrg
373701e04c3fSmrg   vertex_array_binding_divisor(ctx, ctx->Array.VAO,
373801e04c3fSmrg                                bindingIndex, divisor,
373901e04c3fSmrg                                "glVertexBindingDivisor");
374001e04c3fSmrg}
374101e04c3fSmrg
374201e04c3fSmrg
374301e04c3fSmrgvoid GLAPIENTRY
374401e04c3fSmrg_mesa_VertexArrayBindingDivisor_no_error(GLuint vaobj, GLuint bindingIndex,
374501e04c3fSmrg                                         GLuint divisor)
374601e04c3fSmrg{
374701e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
3748af69d88dSmrg
374901e04c3fSmrg   struct gl_vertex_array_object *vao = _mesa_lookup_vao(ctx, vaobj);
375001e04c3fSmrg   vertex_binding_divisor(ctx, vao, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
3751af69d88dSmrg}
3752af69d88dSmrg
37533464ebd5Sriastradh
375401e04c3fSmrgvoid GLAPIENTRY
375501e04c3fSmrg_mesa_VertexArrayBindingDivisor(GLuint vaobj, GLuint bindingIndex,
375601e04c3fSmrg                                GLuint divisor)
375701e04c3fSmrg{
375801e04c3fSmrg   struct gl_vertex_array_object *vao;
375901e04c3fSmrg   GET_CURRENT_CONTEXT(ctx);
376001e04c3fSmrg
376101e04c3fSmrg   /* The ARB_direct_state_access specification says:
376201e04c3fSmrg    *
376301e04c3fSmrg    *   "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor
376401e04c3fSmrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
376501e04c3fSmrg    *    existing vertex array object."
376601e04c3fSmrg    */
37677ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayBindingDivisor");
376801e04c3fSmrg   if (!vao)
376901e04c3fSmrg       return;
377001e04c3fSmrg
377101e04c3fSmrg   vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor,
377201e04c3fSmrg                                "glVertexArrayBindingDivisor");
37734a49301eSmrg}
37744a49301eSmrg
377501e04c3fSmrg
37767ec681f3Smrgvoid GLAPIENTRY
37777ec681f3Smrg_mesa_VertexArrayVertexBindingDivisorEXT(GLuint vaobj, GLuint bindingIndex,
37787ec681f3Smrg                                         GLuint divisor)
3779af69d88dSmrg{
37807ec681f3Smrg   struct gl_vertex_array_object *vao;
37817ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
3782af69d88dSmrg
37837ec681f3Smrg   /* The ARB_direct_state_access specification says:
37847ec681f3Smrg    *
37857ec681f3Smrg    *   "An INVALID_OPERATION error is generated by VertexArrayBindingDivisor
37867ec681f3Smrg    *    if <vaobj> is not [compatibility profile: zero or] the name of an
37877ec681f3Smrg    *    existing vertex array object."
37887ec681f3Smrg    */
37897ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, true, "glVertexArrayVertexBindingDivisorEXT");
37907ec681f3Smrg   if (!vao)
37917ec681f3Smrg       return;
37924a49301eSmrg
37937ec681f3Smrg   vertex_array_binding_divisor(ctx, vao, bindingIndex, divisor,
37947ec681f3Smrg                                "glVertexArrayVertexBindingDivisorEXT");
3795af69d88dSmrg}
37964a49301eSmrg
37974a49301eSmrg/**
37984a49301eSmrg * Print current vertex object/array info.  For debug.
37994a49301eSmrg */
38004a49301eSmrgvoid
38013464ebd5Sriastradh_mesa_print_arrays(struct gl_context *ctx)
38024a49301eSmrg{
380301e04c3fSmrg   const struct gl_vertex_array_object *vao = ctx->Array.VAO;
38044a49301eSmrg
380501e04c3fSmrg   fprintf(stderr, "Array Object %u\n", vao->Name);
3806af69d88dSmrg
3807b9abf16eSmaya   GLbitfield mask = vao->Enabled;
3808b9abf16eSmaya   while (mask) {
3809b9abf16eSmaya      const gl_vert_attrib i = u_bit_scan(&mask);
381001e04c3fSmrg      const struct gl_array_attributes *array = &vao->VertexAttrib[i];
381101e04c3fSmrg
381201e04c3fSmrg      const struct gl_vertex_buffer_binding *binding =
381301e04c3fSmrg         &vao->BufferBinding[array->BufferBindingIndex];
381401e04c3fSmrg      const struct gl_buffer_object *bo = binding->BufferObj;
381501e04c3fSmrg
381601e04c3fSmrg      fprintf(stderr, "  %s: Ptr=%p, Type=%s, Size=%d, ElemSize=%u, "
381701e04c3fSmrg              "Stride=%d, Buffer=%u(Size %lu)\n",
381801e04c3fSmrg              gl_vert_attrib_name((gl_vert_attrib)i),
3819b9abf16eSmaya              array->Ptr, _mesa_enum_to_string(array->Format.Type),
3820b9abf16eSmaya              array->Format.Size,
38217ec681f3Smrg              array->Format._ElementSize, binding->Stride, bo ? bo->Name : 0,
38227ec681f3Smrg              (unsigned long)(bo ? bo->Size : 0));
382301e04c3fSmrg   }
38244a49301eSmrg}
38254a49301eSmrg
38267ec681f3Smrg/**
38277ec681f3Smrg * Initialize attributes of a vertex array within a vertex array object.
38287ec681f3Smrg * \param vao  the container vertex array object
38297ec681f3Smrg * \param index  which array in the VAO to initialize
38307ec681f3Smrg * \param size  number of components (1, 2, 3 or 4) per attribute
38317ec681f3Smrg * \param type  datatype of the attribute (GL_FLOAT, GL_INT, etc).
38327ec681f3Smrg */
38337ec681f3Smrgstatic void
38347ec681f3Smrginit_array(struct gl_context *ctx,
38357ec681f3Smrg           struct gl_vertex_array_object *vao,
38367ec681f3Smrg           gl_vert_attrib index, GLint size, GLint type)
38377ec681f3Smrg{
38387ec681f3Smrg   assert(index < ARRAY_SIZE(vao->VertexAttrib));
38397ec681f3Smrg   struct gl_array_attributes *array = &vao->VertexAttrib[index];
38407ec681f3Smrg   assert(index < ARRAY_SIZE(vao->BufferBinding));
38417ec681f3Smrg   struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
38427ec681f3Smrg
38437ec681f3Smrg   _mesa_set_vertex_format(&array->Format, size, type, GL_RGBA,
38447ec681f3Smrg                           GL_FALSE, GL_FALSE, GL_FALSE);
38457ec681f3Smrg   array->Stride = 0;
38467ec681f3Smrg   array->Ptr = NULL;
38477ec681f3Smrg   array->RelativeOffset = 0;
38487ec681f3Smrg   ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex,
38497ec681f3Smrg                        VERT_ATTRIB_MAX - 1);
38507ec681f3Smrg   array->BufferBindingIndex = index;
38517ec681f3Smrg
38527ec681f3Smrg   binding->Offset = 0;
38537ec681f3Smrg   binding->Stride = array->Format._ElementSize;
38547ec681f3Smrg   binding->BufferObj = NULL;
38557ec681f3Smrg   binding->_BoundArrays = BITFIELD_BIT(index);
38567ec681f3Smrg}
38577ec681f3Smrg
38587ec681f3Smrgstatic void
38597ec681f3Smrginit_default_vao_state(struct gl_context *ctx)
38607ec681f3Smrg{
38617ec681f3Smrg   struct gl_vertex_array_object *vao = &ctx->Array.DefaultVAOState;
38627ec681f3Smrg
38637ec681f3Smrg   vao->RefCount = 1;
38647ec681f3Smrg   vao->SharedAndImmutable = false;
38657ec681f3Smrg
38667ec681f3Smrg   /* Init the individual arrays */
38677ec681f3Smrg   for (unsigned i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) {
38687ec681f3Smrg      switch (i) {
38697ec681f3Smrg      case VERT_ATTRIB_NORMAL:
38707ec681f3Smrg         init_array(ctx, vao, VERT_ATTRIB_NORMAL, 3, GL_FLOAT);
38717ec681f3Smrg         break;
38727ec681f3Smrg      case VERT_ATTRIB_COLOR1:
38737ec681f3Smrg         init_array(ctx, vao, VERT_ATTRIB_COLOR1, 3, GL_FLOAT);
38747ec681f3Smrg         break;
38757ec681f3Smrg      case VERT_ATTRIB_FOG:
38767ec681f3Smrg         init_array(ctx, vao, VERT_ATTRIB_FOG, 1, GL_FLOAT);
38777ec681f3Smrg         break;
38787ec681f3Smrg      case VERT_ATTRIB_COLOR_INDEX:
38797ec681f3Smrg         init_array(ctx, vao, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT);
38807ec681f3Smrg         break;
38817ec681f3Smrg      case VERT_ATTRIB_EDGEFLAG:
38827ec681f3Smrg         init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_UNSIGNED_BYTE);
38837ec681f3Smrg         break;
38847ec681f3Smrg      case VERT_ATTRIB_POINT_SIZE:
38857ec681f3Smrg         init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT);
38867ec681f3Smrg         break;
38877ec681f3Smrg      default:
38887ec681f3Smrg         init_array(ctx, vao, i, 4, GL_FLOAT);
38897ec681f3Smrg         break;
38907ec681f3Smrg      }
38917ec681f3Smrg   }
38927ec681f3Smrg
38937ec681f3Smrg   vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY;
38947ec681f3Smrg}
38954a49301eSmrg
38967117f1b4Smrg/**
38977117f1b4Smrg * Initialize vertex array state for given context.
38987117f1b4Smrg */
389901e04c3fSmrgvoid
39003464ebd5Sriastradh_mesa_init_varray(struct gl_context *ctx)
39017117f1b4Smrg{
39027ec681f3Smrg   init_default_vao_state(ctx);
39037ec681f3Smrg
390401e04c3fSmrg   ctx->Array.DefaultVAO = _mesa_new_vao(ctx, 0);
3905af69d88dSmrg   _mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO);
390601e04c3fSmrg   ctx->Array._EmptyVAO = _mesa_new_vao(ctx, ~0u);
390701e04c3fSmrg   _mesa_reference_vao(ctx, &ctx->Array._DrawVAO, ctx->Array._EmptyVAO);
39087117f1b4Smrg   ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
39094a49301eSmrg
39104a49301eSmrg   ctx->Array.Objects = _mesa_NewHashTable();
39114a49301eSmrg}
39124a49301eSmrg
39134a49301eSmrg
39144a49301eSmrg/**
39154a49301eSmrg * Callback for deleting an array object.  Called by _mesa_HashDeleteAll().
39164a49301eSmrg */
39174a49301eSmrgstatic void
39187ec681f3Smrgdelete_arrayobj_cb(void *data, void *userData)
39194a49301eSmrg{
3920af69d88dSmrg   struct gl_vertex_array_object *vao = (struct gl_vertex_array_object *) data;
39213464ebd5Sriastradh   struct gl_context *ctx = (struct gl_context *) userData;
3922af69d88dSmrg   _mesa_delete_vao(ctx, vao);
39234a49301eSmrg}
39244a49301eSmrg
39254a49301eSmrg
39264a49301eSmrg/**
39274a49301eSmrg * Free vertex array state for given context.
39284a49301eSmrg */
392901e04c3fSmrgvoid
39303464ebd5Sriastradh_mesa_free_varray_data(struct gl_context *ctx)
39314a49301eSmrg{
39324a49301eSmrg   _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
39334a49301eSmrg   _mesa_DeleteHashTable(ctx->Array.Objects);
39347117f1b4Smrg}
39357ec681f3Smrg
39367ec681f3Smrgvoid GLAPIENTRY
39377ec681f3Smrg_mesa_GetVertexArrayIntegervEXT(GLuint vaobj, GLenum pname, GLint *param)
39387ec681f3Smrg{
39397ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
39407ec681f3Smrg   struct gl_vertex_array_object* vao;
39417ec681f3Smrg   struct gl_buffer_object *buf;
39427ec681f3Smrg   void* ptr;
39437ec681f3Smrg
39447ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, true,
39457ec681f3Smrg                              "glGetVertexArrayIntegervEXT");
39467ec681f3Smrg   if (!vao)
39477ec681f3Smrg      return;
39487ec681f3Smrg
39497ec681f3Smrg   /* The EXT_direct_state_access spec says:
39507ec681f3Smrg    *
39517ec681f3Smrg    *    "For GetVertexArrayIntegervEXT, pname must be one of the "Get value" tokens
39527ec681f3Smrg    *    in tables 6.6, 6.7, 6.8, and 6.9 that use GetIntegerv, IsEnabled, or
39537ec681f3Smrg    *    GetPointerv for their "Get command" (so excluding the VERTEX_ATTRIB_*
39547ec681f3Smrg    *    tokens)."
39557ec681f3Smrg    */
39567ec681f3Smrg   switch (pname) {
39577ec681f3Smrg      /* Tokens using GetIntegerv */
39587ec681f3Smrg      case GL_CLIENT_ACTIVE_TEXTURE:
39597ec681f3Smrg         *param = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture;
39607ec681f3Smrg         break;
39617ec681f3Smrg      case GL_VERTEX_ARRAY_SIZE:
39627ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_POS].Format.Size;
39637ec681f3Smrg         break;
39647ec681f3Smrg      case GL_VERTEX_ARRAY_TYPE:
39657ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_POS].Format.Type;
39667ec681f3Smrg         break;
39677ec681f3Smrg      case GL_VERTEX_ARRAY_STRIDE:
39687ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_POS].Stride;
39697ec681f3Smrg         break;
39707ec681f3Smrg      case GL_VERTEX_ARRAY_BUFFER_BINDING:
39717ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_POS].BufferObj;
39727ec681f3Smrg         *param = buf ? buf->Name : 0;
39737ec681f3Smrg         break;
39747ec681f3Smrg      case GL_COLOR_ARRAY_SIZE:
39757ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR0].Format.Size;
39767ec681f3Smrg         break;
39777ec681f3Smrg      case GL_COLOR_ARRAY_TYPE:
39787ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR0].Format.Type;
39797ec681f3Smrg         break;
39807ec681f3Smrg      case GL_COLOR_ARRAY_STRIDE:
39817ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR0].Stride;
39827ec681f3Smrg         break;
39837ec681f3Smrg      case GL_COLOR_ARRAY_BUFFER_BINDING:
39847ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_COLOR0].BufferObj;
39857ec681f3Smrg         *param = buf ? buf->Name : 0;
39867ec681f3Smrg         break;
39877ec681f3Smrg      case GL_EDGE_FLAG_ARRAY_STRIDE:
39887ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Stride;
39897ec681f3Smrg         break;
39907ec681f3Smrg      case GL_EDGE_FLAG_ARRAY_BUFFER_BINDING:
39917ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_EDGEFLAG].BufferObj;
39927ec681f3Smrg         *param = buf ? buf->Name : 0;
39937ec681f3Smrg         break;
39947ec681f3Smrg      case GL_INDEX_ARRAY_TYPE:
39957ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Format.Type;
39967ec681f3Smrg         break;
39977ec681f3Smrg      case GL_INDEX_ARRAY_STRIDE:
39987ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Stride;
39997ec681f3Smrg         break;
40007ec681f3Smrg      case GL_INDEX_ARRAY_BUFFER_BINDING:
40017ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_COLOR_INDEX].BufferObj;
40027ec681f3Smrg         *param = buf ? buf->Name : 0;
40037ec681f3Smrg         break;
40047ec681f3Smrg      case GL_NORMAL_ARRAY_TYPE:
40057ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_NORMAL].Format.Type;
40067ec681f3Smrg         break;
40077ec681f3Smrg      case GL_NORMAL_ARRAY_STRIDE:
40087ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_NORMAL].Stride;
40097ec681f3Smrg         break;
40107ec681f3Smrg      case GL_NORMAL_ARRAY_BUFFER_BINDING:
40117ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_NORMAL].BufferObj;
40127ec681f3Smrg         *param = buf ? buf->Name : 0;
40137ec681f3Smrg         break;
40147ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_SIZE:
40157ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Format.Size;
40167ec681f3Smrg         break;
40177ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_TYPE:
40187ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Format.Type;
40197ec681f3Smrg         break;
40207ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_STRIDE:
40217ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Stride;
40227ec681f3Smrg         break;
40237ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
40247ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj;
40257ec681f3Smrg         *param = buf ? buf->Name : 0;
40267ec681f3Smrg         break;
40277ec681f3Smrg      case GL_FOG_COORD_ARRAY_TYPE:
40287ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_FOG].Format.Type;
40297ec681f3Smrg         break;
40307ec681f3Smrg      case GL_FOG_COORD_ARRAY_STRIDE:
40317ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_FOG].Stride;
40327ec681f3Smrg         break;
40337ec681f3Smrg      case GL_FOG_COORD_ARRAY_BUFFER_BINDING:
40347ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_FOG].BufferObj;
40357ec681f3Smrg         *param = buf ? buf->Name : 0;
40367ec681f3Smrg         break;
40377ec681f3Smrg      case GL_SECONDARY_COLOR_ARRAY_SIZE:
40387ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR1].Format.Size;
40397ec681f3Smrg         break;
40407ec681f3Smrg      case GL_SECONDARY_COLOR_ARRAY_TYPE:
40417ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR1].Format.Type;
40427ec681f3Smrg         break;
40437ec681f3Smrg      case GL_SECONDARY_COLOR_ARRAY_STRIDE:
40447ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_COLOR1].Stride;
40457ec681f3Smrg         break;
40467ec681f3Smrg      case GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING:
40477ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_COLOR1].BufferObj;
40487ec681f3Smrg         *param = buf ? buf->Name : 0;
40497ec681f3Smrg         break;
40507ec681f3Smrg
40517ec681f3Smrg      /* Tokens using IsEnabled */
40527ec681f3Smrg      case GL_VERTEX_ARRAY:
40537ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_POS);
40547ec681f3Smrg         break;
40557ec681f3Smrg      case GL_COLOR_ARRAY:
40567ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_COLOR0);
40577ec681f3Smrg         break;
40587ec681f3Smrg      case GL_EDGE_FLAG_ARRAY:
40597ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_EDGEFLAG);
40607ec681f3Smrg         break;
40617ec681f3Smrg      case GL_INDEX_ARRAY:
40627ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_COLOR_INDEX);
40637ec681f3Smrg         break;
40647ec681f3Smrg      case GL_NORMAL_ARRAY:
40657ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_NORMAL);
40667ec681f3Smrg         break;
40677ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY:
40687ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_TEX(ctx->Array.ActiveTexture));
40697ec681f3Smrg         break;
40707ec681f3Smrg      case GL_FOG_COORD_ARRAY:
40717ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_FOG);
40727ec681f3Smrg         break;
40737ec681f3Smrg      case GL_SECONDARY_COLOR_ARRAY:
40747ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_COLOR1);
40757ec681f3Smrg         break;
40767ec681f3Smrg
40777ec681f3Smrg      /* Tokens using GetPointerv */
40787ec681f3Smrg      case GL_VERTEX_ARRAY_POINTER:
40797ec681f3Smrg      case GL_COLOR_ARRAY_POINTER:
40807ec681f3Smrg      case GL_EDGE_FLAG_ARRAY_POINTER:
40817ec681f3Smrg      case GL_INDEX_ARRAY_POINTER:
40827ec681f3Smrg      case GL_NORMAL_ARRAY_POINTER:
40837ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_POINTER:
40847ec681f3Smrg      case GL_FOG_COORD_ARRAY_POINTER:
40857ec681f3Smrg      case GL_SECONDARY_COLOR_ARRAY_POINTER:
40867ec681f3Smrg         _get_vao_pointerv(pname, vao, &ptr, "glGetVertexArrayIntegervEXT");
40877ec681f3Smrg         *param = (int) ((intptr_t) ptr & 0xFFFFFFFF);
40887ec681f3Smrg         break;
40897ec681f3Smrg
40907ec681f3Smrg      default:
40917ec681f3Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayIntegervEXT(pname)");
40927ec681f3Smrg   }
40937ec681f3Smrg}
40947ec681f3Smrg
40957ec681f3Smrgvoid GLAPIENTRY
40967ec681f3Smrg_mesa_GetVertexArrayPointervEXT(GLuint vaobj, GLenum pname, GLvoid** param)
40977ec681f3Smrg{
40987ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
40997ec681f3Smrg   struct gl_vertex_array_object* vao;
41007ec681f3Smrg
41017ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, true,
41027ec681f3Smrg                              "glGetVertexArrayPointervEXT");
41037ec681f3Smrg   if (!vao)
41047ec681f3Smrg      return;
41057ec681f3Smrg
41067ec681f3Smrg   /* The EXT_direct_state_access spec says:
41077ec681f3Smrg    *
41087ec681f3Smrg    *     "For GetVertexArrayPointervEXT, pname must be a *_ARRAY_POINTER token from
41097ec681f3Smrg    *     tables 6.6, 6.7, and 6.8 excluding VERTEX_ATTRIB_ARRAY_POINT."
41107ec681f3Smrg    */
41117ec681f3Smrg   switch (pname) {
41127ec681f3Smrg      case GL_VERTEX_ARRAY_POINTER:
41137ec681f3Smrg      case GL_COLOR_ARRAY_POINTER:
41147ec681f3Smrg      case GL_EDGE_FLAG_ARRAY_POINTER:
41157ec681f3Smrg      case GL_INDEX_ARRAY_POINTER:
41167ec681f3Smrg      case GL_NORMAL_ARRAY_POINTER:
41177ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_POINTER:
41187ec681f3Smrg      case GL_FOG_COORD_ARRAY_POINTER:
41197ec681f3Smrg      case GL_SECONDARY_COLOR_ARRAY_POINTER:
41207ec681f3Smrg         break;
41217ec681f3Smrg
41227ec681f3Smrg      default:
41237ec681f3Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayPointervEXT(pname)");
41247ec681f3Smrg         return;
41257ec681f3Smrg   }
41267ec681f3Smrg
41277ec681f3Smrg   /* pname has been validated, we can now use the helper function */
41287ec681f3Smrg   _get_vao_pointerv(pname, vao, param, "glGetVertexArrayPointervEXT");
41297ec681f3Smrg}
41307ec681f3Smrg
41317ec681f3Smrgvoid GLAPIENTRY
41327ec681f3Smrg_mesa_GetVertexArrayIntegeri_vEXT(GLuint vaobj, GLuint index, GLenum pname, GLint *param)
41337ec681f3Smrg{
41347ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
41357ec681f3Smrg   struct gl_vertex_array_object* vao;
41367ec681f3Smrg   struct gl_buffer_object *buf;
41377ec681f3Smrg
41387ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, true,
41397ec681f3Smrg                              "glGetVertexArrayIntegeri_vEXT");
41407ec681f3Smrg   if (!vao)
41417ec681f3Smrg      return;
41427ec681f3Smrg
41437ec681f3Smrg
41447ec681f3Smrg   /* The EXT_direct_state_access spec says:
41457ec681f3Smrg    *
41467ec681f3Smrg    *    "For GetVertexArrayIntegeri_vEXT, pname must be one of the
41477ec681f3Smrg    *    "Get value" tokens in tables 6.8 and 6.9 that use GetVertexAttribiv
41487ec681f3Smrg    *    or GetVertexAttribPointerv (so allowing only the VERTEX_ATTRIB_*
41497ec681f3Smrg    *    tokens) or a token of the form TEXTURE_COORD_ARRAY (the enable) or
41507ec681f3Smrg    *    TEXTURE_COORD_ARRAY_*; index identifies the vertex attribute
41517ec681f3Smrg    *    array to query or texture coordinate set index respectively."
41527ec681f3Smrg    */
41537ec681f3Smrg
41547ec681f3Smrg   switch (pname) {
41557ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY:
41567ec681f3Smrg         *param = !!(vao->Enabled & VERT_BIT_TEX(index));
41577ec681f3Smrg         break;
41587ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_SIZE:
41597ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Format.Size;
41607ec681f3Smrg         break;
41617ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_TYPE:
41627ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Format.Type;
41637ec681f3Smrg         break;
41647ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_STRIDE:
41657ec681f3Smrg         *param = vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Stride;
41667ec681f3Smrg         break;
41677ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
41687ec681f3Smrg         buf = vao->BufferBinding[VERT_ATTRIB_TEX(index)].BufferObj;
41697ec681f3Smrg         *param = buf ? buf->Name : 0;
41707ec681f3Smrg         break;
41717ec681f3Smrg      default:
41727ec681f3Smrg         *param = get_vertex_array_attrib(ctx, vao, index, pname, "glGetVertexArrayIntegeri_vEXT");
41737ec681f3Smrg   }
41747ec681f3Smrg}
41757ec681f3Smrg
41767ec681f3Smrgvoid GLAPIENTRY
41777ec681f3Smrg_mesa_GetVertexArrayPointeri_vEXT(GLuint vaobj, GLuint index, GLenum pname, GLvoid** param)
41787ec681f3Smrg{
41797ec681f3Smrg   GET_CURRENT_CONTEXT(ctx);
41807ec681f3Smrg   struct gl_vertex_array_object* vao;
41817ec681f3Smrg
41827ec681f3Smrg   vao = _mesa_lookup_vao_err(ctx, vaobj, true,
41837ec681f3Smrg                              "glGetVertexArrayPointeri_vEXT");
41847ec681f3Smrg   if (!vao)
41857ec681f3Smrg      return;
41867ec681f3Smrg
41877ec681f3Smrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
41887ec681f3Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexArrayPointeri_vEXT(index)");
41897ec681f3Smrg      return;
41907ec681f3Smrg   }
41917ec681f3Smrg
41927ec681f3Smrg   /* The EXT_direct_state_access spec says:
41937ec681f3Smrg    *
41947ec681f3Smrg    *     "For GetVertexArrayPointeri_vEXT, pname must be VERTEX_ATTRIB_ARRAY_POINTER
41957ec681f3Smrg    *     or TEXTURE_COORD_ARRAY_POINTER with the index parameter indicating the vertex
41967ec681f3Smrg    *     attribute or texture coordindate set index."
41977ec681f3Smrg    */
41987ec681f3Smrg   switch(pname) {
41997ec681f3Smrg      case GL_VERTEX_ATTRIB_ARRAY_POINTER:
42007ec681f3Smrg         *param = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
42017ec681f3Smrg         break;
42027ec681f3Smrg      case GL_TEXTURE_COORD_ARRAY_POINTER:
42037ec681f3Smrg         *param = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_TEX(index)].Ptr;
42047ec681f3Smrg         break;
42057ec681f3Smrg      default:
42067ec681f3Smrg         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexArrayPointeri_vEXT(pname)");
42077ec681f3Smrg   }
42087ec681f3Smrg}
4209