varray.c revision af69d88d
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
27af69d88dSmrg#include <inttypes.h>  /* for PRId64 macro */
28af69d88dSmrg
297117f1b4Smrg#include "glheader.h"
307117f1b4Smrg#include "imports.h"
317117f1b4Smrg#include "bufferobj.h"
327117f1b4Smrg#include "context.h"
337117f1b4Smrg#include "enable.h"
347117f1b4Smrg#include "enums.h"
354a49301eSmrg#include "hash.h"
363464ebd5Sriastradh#include "image.h"
373464ebd5Sriastradh#include "macros.h"
387117f1b4Smrg#include "mtypes.h"
397117f1b4Smrg#include "varray.h"
407117f1b4Smrg#include "arrayobj.h"
41cdc920a0Smrg#include "main/dispatch.h"
427117f1b4Smrg
437117f1b4Smrg
443464ebd5Sriastradh/** Used to do error checking for GL_EXT_vertex_array_bgra */
453464ebd5Sriastradh#define BGRA_OR_4  5
463464ebd5Sriastradh
473464ebd5Sriastradh
483464ebd5Sriastradh/** Used to indicate which GL datatypes are accepted by each of the
493464ebd5Sriastradh * glVertex/Color/Attrib/EtcPointer() functions.
503464ebd5Sriastradh */
51af69d88dSmrg#define BOOL_BIT                          (1 << 0)
52af69d88dSmrg#define BYTE_BIT                          (1 << 1)
53af69d88dSmrg#define UNSIGNED_BYTE_BIT                 (1 << 2)
54af69d88dSmrg#define SHORT_BIT                         (1 << 3)
55af69d88dSmrg#define UNSIGNED_SHORT_BIT                (1 << 4)
56af69d88dSmrg#define INT_BIT                           (1 << 5)
57af69d88dSmrg#define UNSIGNED_INT_BIT                  (1 << 6)
58af69d88dSmrg#define HALF_BIT                          (1 << 7)
59af69d88dSmrg#define FLOAT_BIT                         (1 << 8)
60af69d88dSmrg#define DOUBLE_BIT                        (1 << 9)
61af69d88dSmrg#define FIXED_ES_BIT                      (1 << 10)
62af69d88dSmrg#define FIXED_GL_BIT                      (1 << 11)
63af69d88dSmrg#define UNSIGNED_INT_2_10_10_10_REV_BIT   (1 << 12)
64af69d88dSmrg#define INT_2_10_10_10_REV_BIT            (1 << 13)
65af69d88dSmrg#define UNSIGNED_INT_10F_11F_11F_REV_BIT  (1 << 14)
66af69d88dSmrg#define ALL_TYPE_BITS                    ((1 << 15) - 1)
673464ebd5Sriastradh
683464ebd5Sriastradh
693464ebd5Sriastradh/** Convert GL datatype enum into a <type>_BIT value seen above */
703464ebd5Sriastradhstatic GLbitfield
713464ebd5Sriastradhtype_to_bit(const struct gl_context *ctx, GLenum type)
723464ebd5Sriastradh{
733464ebd5Sriastradh   switch (type) {
743464ebd5Sriastradh   case GL_BOOL:
753464ebd5Sriastradh      return BOOL_BIT;
763464ebd5Sriastradh   case GL_BYTE:
773464ebd5Sriastradh      return BYTE_BIT;
783464ebd5Sriastradh   case GL_UNSIGNED_BYTE:
793464ebd5Sriastradh      return UNSIGNED_BYTE_BIT;
803464ebd5Sriastradh   case GL_SHORT:
813464ebd5Sriastradh      return SHORT_BIT;
823464ebd5Sriastradh   case GL_UNSIGNED_SHORT:
833464ebd5Sriastradh      return UNSIGNED_SHORT_BIT;
843464ebd5Sriastradh   case GL_INT:
853464ebd5Sriastradh      return INT_BIT;
863464ebd5Sriastradh   case GL_UNSIGNED_INT:
873464ebd5Sriastradh      return UNSIGNED_INT_BIT;
883464ebd5Sriastradh   case GL_HALF_FLOAT:
893464ebd5Sriastradh      if (ctx->Extensions.ARB_half_float_vertex)
903464ebd5Sriastradh         return HALF_BIT;
913464ebd5Sriastradh      else
923464ebd5Sriastradh         return 0x0;
933464ebd5Sriastradh   case GL_FLOAT:
943464ebd5Sriastradh      return FLOAT_BIT;
953464ebd5Sriastradh   case GL_DOUBLE:
963464ebd5Sriastradh      return DOUBLE_BIT;
973464ebd5Sriastradh   case GL_FIXED:
98af69d88dSmrg      return _mesa_is_desktop_gl(ctx) ? FIXED_GL_BIT : FIXED_ES_BIT;
99af69d88dSmrg   case GL_UNSIGNED_INT_2_10_10_10_REV:
100af69d88dSmrg      return UNSIGNED_INT_2_10_10_10_REV_BIT;
101af69d88dSmrg   case GL_INT_2_10_10_10_REV:
102af69d88dSmrg      return INT_2_10_10_10_REV_BIT;
103af69d88dSmrg   case GL_UNSIGNED_INT_10F_11F_11F_REV:
104af69d88dSmrg      return UNSIGNED_INT_10F_11F_11F_REV_BIT;
1053464ebd5Sriastradh   default:
1063464ebd5Sriastradh      return 0;
1073464ebd5Sriastradh   }
1083464ebd5Sriastradh}
1093464ebd5Sriastradh
1103464ebd5Sriastradh
1117117f1b4Smrg/**
112af69d88dSmrg * Sets the VertexBinding field in the vertex attribute given by attribIndex.
1137117f1b4Smrg */
1147117f1b4Smrgstatic void
115af69d88dSmrgvertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
116af69d88dSmrg                      GLuint bindingIndex)
117af69d88dSmrg{
118af69d88dSmrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
119af69d88dSmrg   struct gl_vertex_attrib_array *array = &vao->VertexAttrib[attribIndex];
120af69d88dSmrg
121af69d88dSmrg   if (array->VertexBinding != bindingIndex) {
122af69d88dSmrg      const GLbitfield64 array_bit = VERT_BIT(attribIndex);
123af69d88dSmrg
124af69d88dSmrg      FLUSH_VERTICES(ctx, _NEW_ARRAY);
125af69d88dSmrg
126af69d88dSmrg      vao->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit;
127af69d88dSmrg      vao->VertexBinding[bindingIndex]._BoundArrays |= array_bit;
128af69d88dSmrg
129af69d88dSmrg      array->VertexBinding = bindingIndex;
130af69d88dSmrg
131af69d88dSmrg      vao->NewArrays |= array_bit;
132af69d88dSmrg   }
133af69d88dSmrg}
134af69d88dSmrg
135af69d88dSmrg
136af69d88dSmrg/**
137af69d88dSmrg * Binds a buffer object to the vertex buffer binding point given by index,
138af69d88dSmrg * and sets the Offset and Stride fields.
139af69d88dSmrg */
140af69d88dSmrgstatic void
141af69d88dSmrgbind_vertex_buffer(struct gl_context *ctx, GLuint index,
142af69d88dSmrg                   struct gl_buffer_object *vbo,
143af69d88dSmrg                   GLintptr offset, GLsizei stride)
144af69d88dSmrg{
145af69d88dSmrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
146af69d88dSmrg   struct gl_vertex_buffer_binding *binding = &vao->VertexBinding[index];
147af69d88dSmrg
148af69d88dSmrg   if (binding->BufferObj != vbo ||
149af69d88dSmrg       binding->Offset != offset ||
150af69d88dSmrg       binding->Stride != stride) {
151af69d88dSmrg
152af69d88dSmrg      FLUSH_VERTICES(ctx, _NEW_ARRAY);
153af69d88dSmrg
154af69d88dSmrg      _mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo);
155af69d88dSmrg
156af69d88dSmrg      binding->Offset = offset;
157af69d88dSmrg      binding->Stride = stride;
158af69d88dSmrg
159af69d88dSmrg      vao->NewArrays |= binding->_BoundArrays;
160af69d88dSmrg   }
161af69d88dSmrg}
162af69d88dSmrg
163af69d88dSmrg
164af69d88dSmrg/**
165af69d88dSmrg * Sets the InstanceDivisor field in the vertex buffer binding point
166af69d88dSmrg * given by bindingIndex.
167af69d88dSmrg */
168af69d88dSmrgstatic void
169af69d88dSmrgvertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex,
170af69d88dSmrg                       GLuint divisor)
171af69d88dSmrg{
172af69d88dSmrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
173af69d88dSmrg   struct gl_vertex_buffer_binding *binding =
174af69d88dSmrg      &vao->VertexBinding[bindingIndex];
175af69d88dSmrg
176af69d88dSmrg   if (binding->InstanceDivisor != divisor) {
177af69d88dSmrg      FLUSH_VERTICES(ctx, _NEW_ARRAY);
178af69d88dSmrg      binding->InstanceDivisor = divisor;
179af69d88dSmrg      vao->NewArrays |= binding->_BoundArrays;
180af69d88dSmrg   }
181af69d88dSmrg}
182af69d88dSmrg
183af69d88dSmrg
184af69d88dSmrg/**
185af69d88dSmrg * Examine the API profile and extensions to determine which types are legal
186af69d88dSmrg * for vertex arrays.  This is called once from update_array_format().
187af69d88dSmrg */
188af69d88dSmrgstatic GLbitfield
189af69d88dSmrgget_legal_types_mask(const struct gl_context *ctx)
190af69d88dSmrg{
191af69d88dSmrg   GLbitfield legalTypesMask = ALL_TYPE_BITS;
192af69d88dSmrg
193af69d88dSmrg   if (_mesa_is_gles(ctx)) {
194af69d88dSmrg      legalTypesMask &= ~(FIXED_GL_BIT |
195af69d88dSmrg                          DOUBLE_BIT |
196af69d88dSmrg                          UNSIGNED_INT_10F_11F_11F_REV_BIT);
197af69d88dSmrg
198af69d88dSmrg      /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
199af69d88dSmrg       * 3.0.  The 2_10_10_10 types are added in OpenGL ES 3.0 or
200af69d88dSmrg       * GL_OES_vertex_type_10_10_10_2.  GL_HALF_FLOAT data is not allowed
201af69d88dSmrg       * until 3.0 or with the GL_OES_vertex_half float extension, which isn't
202af69d88dSmrg       * quite as trivial as we'd like because it uses a different enum value
203af69d88dSmrg       * for GL_HALF_FLOAT_OES.
204af69d88dSmrg       */
205af69d88dSmrg      if (ctx->Version < 30) {
206af69d88dSmrg         legalTypesMask &= ~(UNSIGNED_INT_BIT |
207af69d88dSmrg                             INT_BIT |
208af69d88dSmrg                             UNSIGNED_INT_2_10_10_10_REV_BIT |
209af69d88dSmrg                             INT_2_10_10_10_REV_BIT |
210af69d88dSmrg                             HALF_BIT);
211af69d88dSmrg      }
212af69d88dSmrg   }
213af69d88dSmrg   else {
214af69d88dSmrg      legalTypesMask &= ~FIXED_ES_BIT;
215af69d88dSmrg
216af69d88dSmrg      if (!ctx->Extensions.ARB_ES2_compatibility)
217af69d88dSmrg         legalTypesMask &= ~FIXED_GL_BIT;
218af69d88dSmrg
219af69d88dSmrg      if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
220af69d88dSmrg         legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
221af69d88dSmrg                             INT_2_10_10_10_REV_BIT);
222af69d88dSmrg
223af69d88dSmrg      if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev)
224af69d88dSmrg         legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT;
225af69d88dSmrg   }
226af69d88dSmrg
227af69d88dSmrg   return legalTypesMask;
228af69d88dSmrg}
229af69d88dSmrg
230af69d88dSmrg
231af69d88dSmrg/**
232af69d88dSmrg * Does error checking and updates the format in an attrib array.
233af69d88dSmrg *
234af69d88dSmrg * Called by update_array() and VertexAttrib*Format().
235af69d88dSmrg *
236af69d88dSmrg * \param func         Name of calling function used for error reporting
237af69d88dSmrg * \param attrib       The index of the attribute array
238af69d88dSmrg * \param legalTypes   Bitmask of *_BIT above indicating legal datatypes
239af69d88dSmrg * \param sizeMin      Min allowable size value
240af69d88dSmrg * \param sizeMax      Max allowable size value (may also be BGRA_OR_4)
241af69d88dSmrg * \param size         Components per element (1, 2, 3 or 4)
242af69d88dSmrg * \param type         Datatype of each component (GL_FLOAT, GL_INT, etc)
243af69d88dSmrg * \param normalized   Whether integer types are converted to floats in [-1, 1]
244af69d88dSmrg * \param integer      Integer-valued values (will not be normalized to [-1, 1])
245af69d88dSmrg * \param relativeOffset Offset of the first element relative to the binding offset.
246af69d88dSmrg */
247af69d88dSmrgstatic bool
248af69d88dSmrgupdate_array_format(struct gl_context *ctx,
249af69d88dSmrg                    const char *func,
250af69d88dSmrg                    GLuint attrib, GLbitfield legalTypesMask,
251af69d88dSmrg                    GLint sizeMin, GLint sizeMax,
252af69d88dSmrg                    GLint size, GLenum type,
253af69d88dSmrg                    GLboolean normalized, GLboolean integer,
254af69d88dSmrg                    GLuint relativeOffset)
2557117f1b4Smrg{
256af69d88dSmrg   struct gl_vertex_attrib_array *array;
2573464ebd5Sriastradh   GLbitfield typeBit;
258af69d88dSmrg   GLuint elementSize;
2593464ebd5Sriastradh   GLenum format = GL_RGBA;
2603464ebd5Sriastradh
261af69d88dSmrg   if (ctx->Array.LegalTypesMask == 0) {
262af69d88dSmrg      /* One-time initialization.  We can't do this in _mesa_init_varrays()
263af69d88dSmrg       * below because extensions are not yet enabled at that point.
264af69d88dSmrg       */
265af69d88dSmrg      ctx->Array.LegalTypesMask = get_legal_types_mask(ctx);
2663464ebd5Sriastradh   }
267af69d88dSmrg
268af69d88dSmrg   legalTypesMask &= ctx->Array.LegalTypesMask;
269af69d88dSmrg
270af69d88dSmrg   if (_mesa_is_gles(ctx) && sizeMax == BGRA_OR_4) {
271af69d88dSmrg      /* BGRA ordering is not supported in ES contexts.
272af69d88dSmrg       */
273af69d88dSmrg      sizeMax = 4;
2743464ebd5Sriastradh   }
2753464ebd5Sriastradh
2763464ebd5Sriastradh   typeBit = type_to_bit(ctx, type);
2773464ebd5Sriastradh   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
2783464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
2793464ebd5Sriastradh                  func, _mesa_lookup_enum_by_nr(type));
280af69d88dSmrg      return false;
2813464ebd5Sriastradh   }
2823464ebd5Sriastradh
2833464ebd5Sriastradh   /* Do size parameter checking.
2843464ebd5Sriastradh    * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and
2853464ebd5Sriastradh    * must be handled specially.
2863464ebd5Sriastradh    */
2873464ebd5Sriastradh   if (ctx->Extensions.EXT_vertex_array_bgra &&
2883464ebd5Sriastradh       sizeMax == BGRA_OR_4 &&
2893464ebd5Sriastradh       size == GL_BGRA) {
290af69d88dSmrg      /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
291af69d88dSmrg       *
292af69d88dSmrg       * "An INVALID_OPERATION error is generated under any of the following
293af69d88dSmrg       *  conditions:
294af69d88dSmrg       *    ...
295af69d88dSmrg       *    • size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV
296af69d88dSmrg       *      or UNSIGNED_INT_2_10_10_10_REV;
297af69d88dSmrg       *    ...
298af69d88dSmrg       *    • size is BGRA and normalized is FALSE;"
299af69d88dSmrg       */
300af69d88dSmrg      bool bgra_error = false;
301af69d88dSmrg
302af69d88dSmrg      if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
303af69d88dSmrg         if (type != GL_UNSIGNED_INT_2_10_10_10_REV &&
304af69d88dSmrg             type != GL_INT_2_10_10_10_REV &&
305af69d88dSmrg             type != GL_UNSIGNED_BYTE)
306af69d88dSmrg            bgra_error = true;
307af69d88dSmrg      } else if (type != GL_UNSIGNED_BYTE)
308af69d88dSmrg         bgra_error = true;
309af69d88dSmrg
310af69d88dSmrg      if (bgra_error) {
311af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)",
312af69d88dSmrg                     func, _mesa_lookup_enum_by_nr(type));
313af69d88dSmrg         return false;
314af69d88dSmrg      }
315af69d88dSmrg
316af69d88dSmrg      if (!normalized) {
317af69d88dSmrg         _mesa_error(ctx, GL_INVALID_OPERATION,
318af69d88dSmrg                     "%s(size=GL_BGRA and normalized=GL_FALSE)", func);
319af69d88dSmrg         return false;
3203464ebd5Sriastradh      }
321af69d88dSmrg
3223464ebd5Sriastradh      format = GL_BGRA;
3233464ebd5Sriastradh      size = 4;
3243464ebd5Sriastradh   }
3253464ebd5Sriastradh   else if (size < sizeMin || size > sizeMax || size > 4) {
3263464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
327af69d88dSmrg      return false;
328af69d88dSmrg   }
329af69d88dSmrg
330af69d88dSmrg   if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
331af69d88dSmrg       (type == GL_UNSIGNED_INT_2_10_10_10_REV ||
332af69d88dSmrg        type == GL_INT_2_10_10_10_REV) && size != 4) {
333af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
334af69d88dSmrg      return false;
335af69d88dSmrg   }
336af69d88dSmrg
337af69d88dSmrg   /* The ARB_vertex_attrib_binding_spec says:
338af69d88dSmrg    *
339af69d88dSmrg    *   An INVALID_VALUE error is generated if <relativeoffset> is larger than
340af69d88dSmrg    *   the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.
341af69d88dSmrg    */
342af69d88dSmrg   if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) {
343af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
344af69d88dSmrg                  "%s(relativeOffset=%d > "
345af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)",
346af69d88dSmrg                  func, relativeOffset);
347af69d88dSmrg      return false;
348af69d88dSmrg   }
349af69d88dSmrg
350af69d88dSmrg   if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev &&
351af69d88dSmrg         type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) {
352af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
353af69d88dSmrg      return false;
3543464ebd5Sriastradh   }
3553464ebd5Sriastradh
3563464ebd5Sriastradh   ASSERT(size <= 4);
3573464ebd5Sriastradh
358af69d88dSmrg   elementSize = _mesa_bytes_per_vertex_attrib(size, type);
359af69d88dSmrg   assert(elementSize != -1);
360af69d88dSmrg
361af69d88dSmrg   array = &ctx->Array.VAO->VertexAttrib[attrib];
362af69d88dSmrg   array->Size = size;
363af69d88dSmrg   array->Type = type;
364af69d88dSmrg   array->Format = format;
365af69d88dSmrg   array->Normalized = normalized;
366af69d88dSmrg   array->Integer = integer;
367af69d88dSmrg   array->RelativeOffset = relativeOffset;
368af69d88dSmrg   array->_ElementSize = elementSize;
369af69d88dSmrg
370af69d88dSmrg   ctx->Array.VAO->NewArrays |= VERT_BIT(attrib);
371af69d88dSmrg   ctx->NewState |= _NEW_ARRAY;
372af69d88dSmrg
373af69d88dSmrg   return true;
374af69d88dSmrg}
375af69d88dSmrg
376af69d88dSmrg
377af69d88dSmrg/**
378af69d88dSmrg * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
379af69d88dSmrg * functions.
380af69d88dSmrg *
381af69d88dSmrg * \param func  name of calling function used for error reporting
382af69d88dSmrg * \param attrib  the attribute array index to update
383af69d88dSmrg * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
384af69d88dSmrg * \param sizeMin  min allowable size value
385af69d88dSmrg * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
386af69d88dSmrg * \param size  components per element (1, 2, 3 or 4)
387af69d88dSmrg * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
388af69d88dSmrg * \param stride  stride between elements, in elements
389af69d88dSmrg * \param normalized  are integer types converted to floats in [-1, 1]?
390af69d88dSmrg * \param integer  integer-valued values (will not be normalized to [-1,1])
391af69d88dSmrg * \param ptr  the address (or offset inside VBO) of the array data
392af69d88dSmrg */
393af69d88dSmrgstatic void
394af69d88dSmrgupdate_array(struct gl_context *ctx,
395af69d88dSmrg             const char *func,
396af69d88dSmrg             GLuint attrib, GLbitfield legalTypesMask,
397af69d88dSmrg             GLint sizeMin, GLint sizeMax,
398af69d88dSmrg             GLint size, GLenum type, GLsizei stride,
399af69d88dSmrg             GLboolean normalized, GLboolean integer,
400af69d88dSmrg             const GLvoid *ptr)
401af69d88dSmrg{
402af69d88dSmrg   struct gl_vertex_attrib_array *array;
403af69d88dSmrg   GLsizei effectiveStride;
404af69d88dSmrg
405af69d88dSmrg   /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says:
406af69d88dSmrg    *
407af69d88dSmrg    *     "Client vertex arrays - all vertex array attribute pointers must
408af69d88dSmrg    *     refer to buffer objects (section 2.9.2). The default vertex array
409af69d88dSmrg    *     object (the name zero) is also deprecated. Calling
410af69d88dSmrg    *     VertexAttribPointer when no buffer object or no vertex array object
411af69d88dSmrg    *     is bound will generate an INVALID_OPERATION error..."
412af69d88dSmrg    *
413af69d88dSmrg    * The check for VBOs is handled below.
414af69d88dSmrg    */
415af69d88dSmrg   if (ctx->API == API_OPENGL_CORE
416af69d88dSmrg       && (ctx->Array.VAO == ctx->Array.DefaultVAO)) {
417af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)",
418af69d88dSmrg                  func);
419af69d88dSmrg      return;
420af69d88dSmrg   }
421af69d88dSmrg
4223464ebd5Sriastradh   if (stride < 0) {
4233464ebd5Sriastradh      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
4243464ebd5Sriastradh      return;
4253464ebd5Sriastradh   }
4264a49301eSmrg
427af69d88dSmrg   /* Page 29 (page 44 of the PDF) of the OpenGL 3.3 spec says:
428af69d88dSmrg    *
429af69d88dSmrg    *     "An INVALID_OPERATION error is generated under any of the following
430af69d88dSmrg    *     conditions:
431af69d88dSmrg    *
432af69d88dSmrg    *     ...
433af69d88dSmrg    *
434af69d88dSmrg    *     * any of the *Pointer commands specifying the location and
435af69d88dSmrg    *       organization of vertex array data are called while zero is bound
436af69d88dSmrg    *       to the ARRAY_BUFFER buffer object binding point (see section
437af69d88dSmrg    *       2.9.6), and the pointer argument is not NULL."
438af69d88dSmrg    */
439af69d88dSmrg   if (ptr != NULL && ctx->Array.VAO->ARBsemantics &&
440af69d88dSmrg       !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) {
4413464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
4424a49301eSmrg      return;
4434a49301eSmrg   }
4444a49301eSmrg
445af69d88dSmrg   if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin,
446af69d88dSmrg                            sizeMax, size, type, normalized, integer, 0)) {
447af69d88dSmrg      return;
448af69d88dSmrg   }
4493464ebd5Sriastradh
450af69d88dSmrg   /* Reset the vertex attrib binding */
451af69d88dSmrg   vertex_attrib_binding(ctx, attrib, attrib);
4524a49301eSmrg
453af69d88dSmrg   /* The Stride and Ptr fields are not set by update_array_format() */
454af69d88dSmrg   array = &ctx->Array.VAO->VertexAttrib[attrib];
455af69d88dSmrg   array->Stride = stride;
456af69d88dSmrg   array->Ptr = (const GLvoid *) ptr;
457c1f859d4Smrg
458af69d88dSmrg   /* Update the vertex buffer binding */
459af69d88dSmrg   effectiveStride = stride != 0 ? stride : array->_ElementSize;
460af69d88dSmrg   bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj,
461af69d88dSmrg                      (GLintptr) ptr, effectiveStride);
4627117f1b4Smrg}
4637117f1b4Smrg
4647117f1b4Smrg
4657117f1b4Smrgvoid GLAPIENTRY
4667117f1b4Smrg_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
4677117f1b4Smrg{
4687117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
469af69d88dSmrg   GLbitfield legalTypes = (ctx->API == API_OPENGLES)
470af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
471af69d88dSmrg      : (SHORT_BIT | INT_BIT | FLOAT_BIT |
472af69d88dSmrg         DOUBLE_BIT | HALF_BIT |
473af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
474af69d88dSmrg         INT_2_10_10_10_REV_BIT);
4757117f1b4Smrg
476af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
4777117f1b4Smrg
478af69d88dSmrg   update_array(ctx, "glVertexPointer", VERT_ATTRIB_POS,
4793464ebd5Sriastradh                legalTypes, 2, 4,
4803464ebd5Sriastradh                size, type, stride, GL_FALSE, GL_FALSE, ptr);
4817117f1b4Smrg}
4827117f1b4Smrg
4837117f1b4Smrg
4847117f1b4Smrgvoid GLAPIENTRY
4857117f1b4Smrg_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
4867117f1b4Smrg{
4877117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
488af69d88dSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
489af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
490af69d88dSmrg      : (BYTE_BIT | SHORT_BIT | INT_BIT |
491af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
492af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
493af69d88dSmrg         INT_2_10_10_10_REV_BIT);
494af69d88dSmrg
495af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
4967117f1b4Smrg
497af69d88dSmrg   update_array(ctx, "glNormalPointer", VERT_ATTRIB_NORMAL,
4983464ebd5Sriastradh                legalTypes, 3, 3,
4993464ebd5Sriastradh                3, type, stride, GL_TRUE, GL_FALSE, ptr);
5007117f1b4Smrg}
5017117f1b4Smrg
5027117f1b4Smrg
5037117f1b4Smrgvoid GLAPIENTRY
5047117f1b4Smrg_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
5057117f1b4Smrg{
5067117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
507af69d88dSmrg   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
508af69d88dSmrg      ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT)
509af69d88dSmrg      : (BYTE_BIT | UNSIGNED_BYTE_BIT |
510af69d88dSmrg         SHORT_BIT | UNSIGNED_SHORT_BIT |
511af69d88dSmrg         INT_BIT | UNSIGNED_INT_BIT |
512af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
513af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
514af69d88dSmrg         INT_2_10_10_10_REV_BIT);
515af69d88dSmrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3;
516af69d88dSmrg
517af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
518af69d88dSmrg
519af69d88dSmrg   update_array(ctx, "glColorPointer", VERT_ATTRIB_COLOR0,
520af69d88dSmrg                legalTypes, sizeMin, BGRA_OR_4,
5213464ebd5Sriastradh                size, type, stride, GL_TRUE, GL_FALSE, ptr);
5227117f1b4Smrg}
5237117f1b4Smrg
5247117f1b4Smrg
5257117f1b4Smrgvoid GLAPIENTRY
526af69d88dSmrg_mesa_FogCoordPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
5277117f1b4Smrg{
5283464ebd5Sriastradh   const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
5297117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
5307117f1b4Smrg
531af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
532af69d88dSmrg
533af69d88dSmrg   update_array(ctx, "glFogCoordPointer", VERT_ATTRIB_FOG,
5343464ebd5Sriastradh                legalTypes, 1, 1,
5353464ebd5Sriastradh                1, type, stride, GL_FALSE, GL_FALSE, ptr);
5367117f1b4Smrg}
5377117f1b4Smrg
5387117f1b4Smrg
5397117f1b4Smrgvoid GLAPIENTRY
5407117f1b4Smrg_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
5417117f1b4Smrg{
5423464ebd5Sriastradh   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT |
5433464ebd5Sriastradh                                  FLOAT_BIT | DOUBLE_BIT);
5447117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
5457117f1b4Smrg
546af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
547af69d88dSmrg
548af69d88dSmrg   update_array(ctx, "glIndexPointer", VERT_ATTRIB_COLOR_INDEX,
5493464ebd5Sriastradh                legalTypes, 1, 1,
5503464ebd5Sriastradh                1, type, stride, GL_FALSE, GL_FALSE, ptr);
5517117f1b4Smrg}
5527117f1b4Smrg
5537117f1b4Smrg
5547117f1b4Smrgvoid GLAPIENTRY
555af69d88dSmrg_mesa_SecondaryColorPointer(GLint size, GLenum type,
5567117f1b4Smrg			       GLsizei stride, const GLvoid *ptr)
5577117f1b4Smrg{
5583464ebd5Sriastradh   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
5593464ebd5Sriastradh                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
5603464ebd5Sriastradh                                  INT_BIT | UNSIGNED_INT_BIT |
561af69d88dSmrg                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
562af69d88dSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
563af69d88dSmrg                                  INT_2_10_10_10_REV_BIT);
5647117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
5657117f1b4Smrg
566af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
567af69d88dSmrg
568af69d88dSmrg   update_array(ctx, "glSecondaryColorPointer", VERT_ATTRIB_COLOR1,
5693464ebd5Sriastradh                legalTypes, 3, BGRA_OR_4,
5703464ebd5Sriastradh                size, type, stride, GL_TRUE, GL_FALSE, ptr);
5717117f1b4Smrg}
5727117f1b4Smrg
5737117f1b4Smrg
5747117f1b4Smrgvoid GLAPIENTRY
5757117f1b4Smrg_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
5767117f1b4Smrg                      const GLvoid *ptr)
5777117f1b4Smrg{
5787117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
579af69d88dSmrg   GLbitfield legalTypes = (ctx->API == API_OPENGLES)
580af69d88dSmrg      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
581af69d88dSmrg      : (SHORT_BIT | INT_BIT |
582af69d88dSmrg         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
583af69d88dSmrg         UNSIGNED_INT_2_10_10_10_REV_BIT |
584af69d88dSmrg         INT_2_10_10_10_REV_BIT);
585af69d88dSmrg   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1;
5867117f1b4Smrg   const GLuint unit = ctx->Array.ActiveTexture;
5877117f1b4Smrg
588af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
589cdc920a0Smrg
590af69d88dSmrg   update_array(ctx, "glTexCoordPointer", VERT_ATTRIB_TEX(unit),
591af69d88dSmrg                legalTypes, sizeMin, 4,
5923464ebd5Sriastradh                size, type, stride, GL_FALSE, GL_FALSE,
5933464ebd5Sriastradh                ptr);
5947117f1b4Smrg}
5957117f1b4Smrg
5967117f1b4Smrg
5977117f1b4Smrgvoid GLAPIENTRY
5987117f1b4Smrg_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
5997117f1b4Smrg{
6003464ebd5Sriastradh   const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
601af69d88dSmrg   /* this is the same type that glEdgeFlag uses */
602af69d88dSmrg   const GLboolean integer = GL_FALSE;
6037117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
6047117f1b4Smrg
605af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
606af69d88dSmrg
607af69d88dSmrg   update_array(ctx, "glEdgeFlagPointer", VERT_ATTRIB_EDGEFLAG,
6083464ebd5Sriastradh                legalTypes, 1, 1,
6093464ebd5Sriastradh                1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, ptr);
6107117f1b4Smrg}
6117117f1b4Smrg
6127117f1b4Smrg
613c1f859d4Smrgvoid GLAPIENTRY
614af69d88dSmrg_mesa_PointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *ptr)
615c1f859d4Smrg{
6163464ebd5Sriastradh   const GLbitfield legalTypes = (FLOAT_BIT | FIXED_ES_BIT);
617c1f859d4Smrg   GET_CURRENT_CONTEXT(ctx);
618af69d88dSmrg
619af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
620c1f859d4Smrg
6213464ebd5Sriastradh   if (ctx->API != API_OPENGLES) {
6223464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION,
6233464ebd5Sriastradh                  "glPointSizePointer(ES 1.x only)");
624c1f859d4Smrg      return;
625c1f859d4Smrg   }
6263464ebd5Sriastradh
627af69d88dSmrg   update_array(ctx, "glPointSizePointer", VERT_ATTRIB_POINT_SIZE,
6283464ebd5Sriastradh                legalTypes, 1, 1,
6293464ebd5Sriastradh                1, type, stride, GL_FALSE, GL_FALSE, ptr);
630c1f859d4Smrg}
631c1f859d4Smrg
632c1f859d4Smrg
6334a49301eSmrg/**
6344a49301eSmrg * Set a generic vertex attribute array.
6354a49301eSmrg * Note that these arrays DO NOT alias the conventional GL vertex arrays
6364a49301eSmrg * (position, normal, color, fog, texcoord, etc).
6374a49301eSmrg */
6387117f1b4Smrgvoid GLAPIENTRY
639af69d88dSmrg_mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type,
6407117f1b4Smrg                             GLboolean normalized,
6417117f1b4Smrg                             GLsizei stride, const GLvoid *ptr)
6427117f1b4Smrg{
6433464ebd5Sriastradh   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
6443464ebd5Sriastradh                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
6453464ebd5Sriastradh                                  INT_BIT | UNSIGNED_INT_BIT |
6463464ebd5Sriastradh                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
647af69d88dSmrg                                  FIXED_ES_BIT | FIXED_GL_BIT |
648af69d88dSmrg                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
649af69d88dSmrg                                  INT_2_10_10_10_REV_BIT |
650af69d88dSmrg                                  UNSIGNED_INT_10F_11F_11F_REV_BIT);
6517117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
6527117f1b4Smrg
653af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
6547117f1b4Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
6557117f1b4Smrg      return;
6567117f1b4Smrg   }
6577117f1b4Smrg
658af69d88dSmrg   update_array(ctx, "glVertexAttribPointer", VERT_ATTRIB_GENERIC(index),
6593464ebd5Sriastradh                legalTypes, 1, BGRA_OR_4,
6603464ebd5Sriastradh                size, type, stride, normalized, GL_FALSE, ptr);
6613464ebd5Sriastradh}
6623464ebd5Sriastradh
6633464ebd5Sriastradh
6643464ebd5Sriastradh/**
6653464ebd5Sriastradh * GL_EXT_gpu_shader4 / GL 3.0.
6663464ebd5Sriastradh * Set an integer-valued vertex attribute array.
6673464ebd5Sriastradh * Note that these arrays DO NOT alias the conventional GL vertex arrays
6683464ebd5Sriastradh * (position, normal, color, fog, texcoord, etc).
6693464ebd5Sriastradh */
6703464ebd5Sriastradhvoid GLAPIENTRY
6713464ebd5Sriastradh_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
6723464ebd5Sriastradh                           GLsizei stride, const GLvoid *ptr)
6733464ebd5Sriastradh{
6743464ebd5Sriastradh   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
6753464ebd5Sriastradh                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
6763464ebd5Sriastradh                                  INT_BIT | UNSIGNED_INT_BIT);
6773464ebd5Sriastradh   const GLboolean normalized = GL_FALSE;
6783464ebd5Sriastradh   const GLboolean integer = GL_TRUE;
6793464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
6803464ebd5Sriastradh
681af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
6823464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)");
6833464ebd5Sriastradh      return;
6847117f1b4Smrg   }
6857117f1b4Smrg
686af69d88dSmrg   update_array(ctx, "glVertexAttribIPointer", VERT_ATTRIB_GENERIC(index),
6873464ebd5Sriastradh                legalTypes, 1, 4,
6883464ebd5Sriastradh                size, type, stride, normalized, integer, ptr);
6893464ebd5Sriastradh}
6903464ebd5Sriastradh
6913464ebd5Sriastradh
6923464ebd5Sriastradh
6933464ebd5Sriastradhvoid GLAPIENTRY
694af69d88dSmrg_mesa_EnableVertexAttribArray(GLuint index)
6953464ebd5Sriastradh{
696af69d88dSmrg   struct gl_vertex_array_object *vao;
6973464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
6983464ebd5Sriastradh
699af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
7003464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE,
7013464ebd5Sriastradh                  "glEnableVertexAttribArrayARB(index)");
7027117f1b4Smrg      return;
7037117f1b4Smrg   }
7047117f1b4Smrg
705af69d88dSmrg   vao = ctx->Array.VAO;
706af69d88dSmrg
707af69d88dSmrg   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->_VertexAttrib));
7083464ebd5Sriastradh
709af69d88dSmrg   if (!vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
710af69d88dSmrg      /* was disabled, now being enabled */
711af69d88dSmrg      FLUSH_VERTICES(ctx, _NEW_ARRAY);
712af69d88dSmrg      vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE;
713af69d88dSmrg      vao->_Enabled |= VERT_BIT_GENERIC(index);
714af69d88dSmrg      vao->NewArrays |= VERT_BIT_GENERIC(index);
715af69d88dSmrg   }
7163464ebd5Sriastradh}
7173464ebd5Sriastradh
7183464ebd5Sriastradh
7193464ebd5Sriastradhvoid GLAPIENTRY
720af69d88dSmrg_mesa_DisableVertexAttribArray(GLuint index)
7213464ebd5Sriastradh{
722af69d88dSmrg   struct gl_vertex_array_object *vao;
7233464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
7243464ebd5Sriastradh
725af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
7263464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE,
7273464ebd5Sriastradh                  "glDisableVertexAttribArrayARB(index)");
7283464ebd5Sriastradh      return;
7293464ebd5Sriastradh   }
7303464ebd5Sriastradh
731af69d88dSmrg   vao = ctx->Array.VAO;
7323464ebd5Sriastradh
733af69d88dSmrg   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->_VertexAttrib));
734af69d88dSmrg
735af69d88dSmrg   if (vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
736af69d88dSmrg      /* was enabled, now being disabled */
737af69d88dSmrg      FLUSH_VERTICES(ctx, _NEW_ARRAY);
738af69d88dSmrg      vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
739af69d88dSmrg      vao->_Enabled &= ~VERT_BIT_GENERIC(index);
740af69d88dSmrg      vao->NewArrays |= VERT_BIT_GENERIC(index);
741af69d88dSmrg   }
7423464ebd5Sriastradh}
7433464ebd5Sriastradh
7443464ebd5Sriastradh
7453464ebd5Sriastradh/**
7463464ebd5Sriastradh * Return info for a vertex attribute array (no alias with legacy
7473464ebd5Sriastradh * vertex attributes (pos, normal, color, etc)).  This function does
7483464ebd5Sriastradh * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
7493464ebd5Sriastradh */
7503464ebd5Sriastradhstatic GLuint
7513464ebd5Sriastradhget_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
7523464ebd5Sriastradh                  const char *caller)
7533464ebd5Sriastradh{
754af69d88dSmrg   const struct gl_vertex_array_object *vao = ctx->Array.VAO;
755af69d88dSmrg   const struct gl_vertex_attrib_array *array;
7563464ebd5Sriastradh
757af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
7583464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
7593464ebd5Sriastradh      return 0;
7603464ebd5Sriastradh   }
7613464ebd5Sriastradh
762af69d88dSmrg   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(vao->VertexAttrib));
7633464ebd5Sriastradh
764af69d88dSmrg   array = &vao->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
7653464ebd5Sriastradh
7663464ebd5Sriastradh   switch (pname) {
7673464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
7683464ebd5Sriastradh      return array->Enabled;
7693464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
770af69d88dSmrg      return (array->Format == GL_BGRA) ? GL_BGRA : array->Size;
7713464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
7723464ebd5Sriastradh      return array->Stride;
7733464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
7743464ebd5Sriastradh      return array->Type;
7753464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
7763464ebd5Sriastradh      return array->Normalized;
7773464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
778af69d88dSmrg      return vao->VertexBinding[array->VertexBinding].BufferObj->Name;
7793464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
780af69d88dSmrg      if ((_mesa_is_desktop_gl(ctx)
781af69d88dSmrg           && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4))
782af69d88dSmrg          || _mesa_is_gles3(ctx)) {
7833464ebd5Sriastradh         return array->Integer;
7844a49301eSmrg      }
7853464ebd5Sriastradh      goto error;
7863464ebd5Sriastradh   case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
787af69d88dSmrg      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
788af69d88dSmrg          || _mesa_is_gles3(ctx)) {
789af69d88dSmrg         return vao->VertexBinding[array->VertexBinding].InstanceDivisor;
790af69d88dSmrg      }
791af69d88dSmrg      goto error;
792af69d88dSmrg   case GL_VERTEX_ATTRIB_BINDING:
793af69d88dSmrg      if (_mesa_is_desktop_gl(ctx)) {
794af69d88dSmrg         return array->VertexBinding - VERT_ATTRIB_GENERIC0;
795af69d88dSmrg      }
796af69d88dSmrg      goto error;
797af69d88dSmrg   case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
798af69d88dSmrg      if (_mesa_is_desktop_gl(ctx)) {
799af69d88dSmrg         return array->RelativeOffset;
8004a49301eSmrg      }
8013464ebd5Sriastradh      goto error;
8023464ebd5Sriastradh   default:
8033464ebd5Sriastradh      ; /* fall-through */
8043464ebd5Sriastradh   }
8054a49301eSmrg
8063464ebd5Sriastradherror:
8073464ebd5Sriastradh   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname);
8083464ebd5Sriastradh   return 0;
8093464ebd5Sriastradh}
8103464ebd5Sriastradh
8113464ebd5Sriastradh
8123464ebd5Sriastradhstatic const GLfloat *
8133464ebd5Sriastradhget_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
8143464ebd5Sriastradh{
8153464ebd5Sriastradh   if (index == 0) {
816af69d88dSmrg      if (_mesa_attr_zero_aliases_vertex(ctx)) {
8173464ebd5Sriastradh	 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
8183464ebd5Sriastradh	 return NULL;
8193464ebd5Sriastradh      }
8203464ebd5Sriastradh   }
821af69d88dSmrg   else if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
8223464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE,
8233464ebd5Sriastradh		  "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function);
8243464ebd5Sriastradh      return NULL;
8253464ebd5Sriastradh   }
8263464ebd5Sriastradh
827af69d88dSmrg   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.VAO->_VertexAttrib));
828af69d88dSmrg
8293464ebd5Sriastradh   FLUSH_CURRENT(ctx, 0);
830af69d88dSmrg   return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)];
8313464ebd5Sriastradh}
8323464ebd5Sriastradh
8333464ebd5Sriastradhvoid GLAPIENTRY
834af69d88dSmrg_mesa_GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
8353464ebd5Sriastradh{
8363464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
8373464ebd5Sriastradh
8383464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
8393464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv");
8403464ebd5Sriastradh      if (v != NULL) {
8413464ebd5Sriastradh         COPY_4V(params, v);
8423464ebd5Sriastradh      }
8434a49301eSmrg   }
8444a49301eSmrg   else {
8453464ebd5Sriastradh      params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname,
8463464ebd5Sriastradh                                                    "glGetVertexAttribfv");
8474a49301eSmrg   }
8483464ebd5Sriastradh}
8494a49301eSmrg
8503464ebd5Sriastradh
8513464ebd5Sriastradhvoid GLAPIENTRY
852af69d88dSmrg_mesa_GetVertexAttribdv(GLuint index, GLenum pname, GLdouble *params)
8533464ebd5Sriastradh{
8543464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
8553464ebd5Sriastradh
8563464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
8573464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv");
8583464ebd5Sriastradh      if (v != NULL) {
8593464ebd5Sriastradh         params[0] = (GLdouble) v[0];
8603464ebd5Sriastradh         params[1] = (GLdouble) v[1];
8613464ebd5Sriastradh         params[2] = (GLdouble) v[2];
8623464ebd5Sriastradh         params[3] = (GLdouble) v[3];
8633464ebd5Sriastradh      }
8643464ebd5Sriastradh   }
8653464ebd5Sriastradh   else {
8663464ebd5Sriastradh      params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname,
8673464ebd5Sriastradh                                                     "glGetVertexAttribdv");
8687117f1b4Smrg   }
8693464ebd5Sriastradh}
8707117f1b4Smrg
8713464ebd5Sriastradh
8723464ebd5Sriastradhvoid GLAPIENTRY
873af69d88dSmrg_mesa_GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
8743464ebd5Sriastradh{
8753464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
8763464ebd5Sriastradh
8773464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
8783464ebd5Sriastradh      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv");
8793464ebd5Sriastradh      if (v != NULL) {
8803464ebd5Sriastradh         /* XXX should floats in[0,1] be scaled to full int range? */
8813464ebd5Sriastradh         params[0] = (GLint) v[0];
8823464ebd5Sriastradh         params[1] = (GLint) v[1];
8833464ebd5Sriastradh         params[2] = (GLint) v[2];
8843464ebd5Sriastradh         params[3] = (GLint) v[3];
8853464ebd5Sriastradh      }
8863464ebd5Sriastradh   }
8873464ebd5Sriastradh   else {
8883464ebd5Sriastradh      params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
8893464ebd5Sriastradh                                                  "glGetVertexAttribiv");
8903464ebd5Sriastradh   }
8913464ebd5Sriastradh}
8923464ebd5Sriastradh
8933464ebd5Sriastradh
8943464ebd5Sriastradh/** GL 3.0 */
8953464ebd5Sriastradhvoid GLAPIENTRY
8963464ebd5Sriastradh_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
8973464ebd5Sriastradh{
8983464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
8993464ebd5Sriastradh
9003464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
901af69d88dSmrg      const GLint *v = (const GLint *)
9023464ebd5Sriastradh	 get_current_attrib(ctx, index, "glGetVertexAttribIiv");
9033464ebd5Sriastradh      if (v != NULL) {
904af69d88dSmrg         COPY_4V(params, v);
9053464ebd5Sriastradh      }
9063464ebd5Sriastradh   }
9073464ebd5Sriastradh   else {
9083464ebd5Sriastradh      params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
9093464ebd5Sriastradh                                                  "glGetVertexAttribIiv");
9103464ebd5Sriastradh   }
9113464ebd5Sriastradh}
9123464ebd5Sriastradh
9133464ebd5Sriastradh
9143464ebd5Sriastradh/** GL 3.0 */
9153464ebd5Sriastradhvoid GLAPIENTRY
9163464ebd5Sriastradh_mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
9173464ebd5Sriastradh{
9183464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
9193464ebd5Sriastradh
9203464ebd5Sriastradh   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
921af69d88dSmrg      const GLuint *v = (const GLuint *)
9223464ebd5Sriastradh	 get_current_attrib(ctx, index, "glGetVertexAttribIuiv");
9233464ebd5Sriastradh      if (v != NULL) {
924af69d88dSmrg         COPY_4V(params, v);
9253464ebd5Sriastradh      }
9263464ebd5Sriastradh   }
9273464ebd5Sriastradh   else {
9283464ebd5Sriastradh      params[0] = get_vertex_array_attrib(ctx, index, pname,
9293464ebd5Sriastradh                                          "glGetVertexAttribIuiv");
9303464ebd5Sriastradh   }
9313464ebd5Sriastradh}
9323464ebd5Sriastradh
9333464ebd5Sriastradh
9343464ebd5Sriastradhvoid GLAPIENTRY
935af69d88dSmrg_mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
9363464ebd5Sriastradh{
9373464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
9383464ebd5Sriastradh
939af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
9403464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
9413464ebd5Sriastradh      return;
9423464ebd5Sriastradh   }
9433464ebd5Sriastradh
9443464ebd5Sriastradh   if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
9453464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
9463464ebd5Sriastradh      return;
9473464ebd5Sriastradh   }
9483464ebd5Sriastradh
949af69d88dSmrg   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.VAO->_VertexAttrib));
9503464ebd5Sriastradh
951af69d88dSmrg   *pointer = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
9527117f1b4Smrg}
9537117f1b4Smrg
9547117f1b4Smrg
9557117f1b4Smrgvoid GLAPIENTRY
9567117f1b4Smrg_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
9577117f1b4Smrg                       GLsizei count, const GLvoid *ptr)
9587117f1b4Smrg{
9597117f1b4Smrg   (void) count;
9607117f1b4Smrg   _mesa_VertexPointer(size, type, stride, ptr);
9617117f1b4Smrg}
9627117f1b4Smrg
9637117f1b4Smrg
9647117f1b4Smrgvoid GLAPIENTRY
9657117f1b4Smrg_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
9667117f1b4Smrg                       const GLvoid *ptr)
9677117f1b4Smrg{
9687117f1b4Smrg   (void) count;
9697117f1b4Smrg   _mesa_NormalPointer(type, stride, ptr);
9707117f1b4Smrg}
9717117f1b4Smrg
9727117f1b4Smrg
9737117f1b4Smrgvoid GLAPIENTRY
9747117f1b4Smrg_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
9757117f1b4Smrg                      const GLvoid *ptr)
9767117f1b4Smrg{
9777117f1b4Smrg   (void) count;
9787117f1b4Smrg   _mesa_ColorPointer(size, type, stride, ptr);
9797117f1b4Smrg}
9807117f1b4Smrg
9817117f1b4Smrg
9827117f1b4Smrgvoid GLAPIENTRY
9837117f1b4Smrg_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
9847117f1b4Smrg                      const GLvoid *ptr)
9857117f1b4Smrg{
9867117f1b4Smrg   (void) count;
9877117f1b4Smrg   _mesa_IndexPointer(type, stride, ptr);
9887117f1b4Smrg}
9897117f1b4Smrg
9907117f1b4Smrg
9917117f1b4Smrgvoid GLAPIENTRY
9927117f1b4Smrg_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
9937117f1b4Smrg                         GLsizei count, const GLvoid *ptr)
9947117f1b4Smrg{
9957117f1b4Smrg   (void) count;
9967117f1b4Smrg   _mesa_TexCoordPointer(size, type, stride, ptr);
9977117f1b4Smrg}
9987117f1b4Smrg
9997117f1b4Smrg
10007117f1b4Smrgvoid GLAPIENTRY
10017117f1b4Smrg_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
10027117f1b4Smrg{
10037117f1b4Smrg   (void) count;
10047117f1b4Smrg   _mesa_EdgeFlagPointer(stride, ptr);
10057117f1b4Smrg}
10067117f1b4Smrg
10077117f1b4Smrg
10087117f1b4Smrgvoid GLAPIENTRY
10097117f1b4Smrg_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
10107117f1b4Smrg{
10117117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
10127117f1b4Smrg   GLboolean tflag, cflag, nflag;  /* enable/disable flags */
10137117f1b4Smrg   GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
10147117f1b4Smrg   GLenum ctype = 0;               /* color type */
10157117f1b4Smrg   GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
10167117f1b4Smrg   const GLint toffset = 0;        /* always zero */
10177117f1b4Smrg   GLint defstride;                /* default stride */
10187117f1b4Smrg   GLint c, f;
10197117f1b4Smrg
1020af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
10217117f1b4Smrg
10227117f1b4Smrg   f = sizeof(GLfloat);
10237117f1b4Smrg   c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
10247117f1b4Smrg
10257117f1b4Smrg   if (stride < 0) {
10267117f1b4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
10277117f1b4Smrg      return;
10287117f1b4Smrg   }
10297117f1b4Smrg
10307117f1b4Smrg   switch (format) {
10317117f1b4Smrg      case GL_V2F:
10327117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
10337117f1b4Smrg         tcomps = 0;  ccomps = 0;  vcomps = 2;
10347117f1b4Smrg         voffset = 0;
10357117f1b4Smrg         defstride = 2*f;
10367117f1b4Smrg         break;
10377117f1b4Smrg      case GL_V3F:
10387117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
10397117f1b4Smrg         tcomps = 0;  ccomps = 0;  vcomps = 3;
10407117f1b4Smrg         voffset = 0;
10417117f1b4Smrg         defstride = 3*f;
10427117f1b4Smrg         break;
10437117f1b4Smrg      case GL_C4UB_V2F:
10447117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
10457117f1b4Smrg         tcomps = 0;  ccomps = 4;  vcomps = 2;
10467117f1b4Smrg         ctype = GL_UNSIGNED_BYTE;
10477117f1b4Smrg         coffset = 0;
10487117f1b4Smrg         voffset = c;
10497117f1b4Smrg         defstride = c + 2*f;
10507117f1b4Smrg         break;
10517117f1b4Smrg      case GL_C4UB_V3F:
10527117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
10537117f1b4Smrg         tcomps = 0;  ccomps = 4;  vcomps = 3;
10547117f1b4Smrg         ctype = GL_UNSIGNED_BYTE;
10557117f1b4Smrg         coffset = 0;
10567117f1b4Smrg         voffset = c;
10577117f1b4Smrg         defstride = c + 3*f;
10587117f1b4Smrg         break;
10597117f1b4Smrg      case GL_C3F_V3F:
10607117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
10617117f1b4Smrg         tcomps = 0;  ccomps = 3;  vcomps = 3;
10627117f1b4Smrg         ctype = GL_FLOAT;
10637117f1b4Smrg         coffset = 0;
10647117f1b4Smrg         voffset = 3*f;
10657117f1b4Smrg         defstride = 6*f;
10667117f1b4Smrg         break;
10677117f1b4Smrg      case GL_N3F_V3F:
10687117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
10697117f1b4Smrg         tcomps = 0;  ccomps = 0;  vcomps = 3;
10707117f1b4Smrg         noffset = 0;
10717117f1b4Smrg         voffset = 3*f;
10727117f1b4Smrg         defstride = 6*f;
10737117f1b4Smrg         break;
10747117f1b4Smrg      case GL_C4F_N3F_V3F:
10757117f1b4Smrg         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
10767117f1b4Smrg         tcomps = 0;  ccomps = 4;  vcomps = 3;
10777117f1b4Smrg         ctype = GL_FLOAT;
10787117f1b4Smrg         coffset = 0;
10797117f1b4Smrg         noffset = 4*f;
10807117f1b4Smrg         voffset = 7*f;
10817117f1b4Smrg         defstride = 10*f;
10827117f1b4Smrg         break;
10837117f1b4Smrg      case GL_T2F_V3F:
10847117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
10857117f1b4Smrg         tcomps = 2;  ccomps = 0;  vcomps = 3;
10867117f1b4Smrg         voffset = 2*f;
10877117f1b4Smrg         defstride = 5*f;
10887117f1b4Smrg         break;
10897117f1b4Smrg      case GL_T4F_V4F:
10907117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
10917117f1b4Smrg         tcomps = 4;  ccomps = 0;  vcomps = 4;
10927117f1b4Smrg         voffset = 4*f;
10937117f1b4Smrg         defstride = 8*f;
10947117f1b4Smrg         break;
10957117f1b4Smrg      case GL_T2F_C4UB_V3F:
10967117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
10977117f1b4Smrg         tcomps = 2;  ccomps = 4;  vcomps = 3;
10987117f1b4Smrg         ctype = GL_UNSIGNED_BYTE;
10997117f1b4Smrg         coffset = 2*f;
11007117f1b4Smrg         voffset = c+2*f;
11017117f1b4Smrg         defstride = c+5*f;
11027117f1b4Smrg         break;
11037117f1b4Smrg      case GL_T2F_C3F_V3F:
11047117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
11057117f1b4Smrg         tcomps = 2;  ccomps = 3;  vcomps = 3;
11067117f1b4Smrg         ctype = GL_FLOAT;
11077117f1b4Smrg         coffset = 2*f;
11087117f1b4Smrg         voffset = 5*f;
11097117f1b4Smrg         defstride = 8*f;
11107117f1b4Smrg         break;
11117117f1b4Smrg      case GL_T2F_N3F_V3F:
11127117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
11137117f1b4Smrg         tcomps = 2;  ccomps = 0;  vcomps = 3;
11147117f1b4Smrg         noffset = 2*f;
11157117f1b4Smrg         voffset = 5*f;
11167117f1b4Smrg         defstride = 8*f;
11177117f1b4Smrg         break;
11187117f1b4Smrg      case GL_T2F_C4F_N3F_V3F:
11197117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
11207117f1b4Smrg         tcomps = 2;  ccomps = 4;  vcomps = 3;
11217117f1b4Smrg         ctype = GL_FLOAT;
11227117f1b4Smrg         coffset = 2*f;
11237117f1b4Smrg         noffset = 6*f;
11247117f1b4Smrg         voffset = 9*f;
11257117f1b4Smrg         defstride = 12*f;
11267117f1b4Smrg         break;
11277117f1b4Smrg      case GL_T4F_C4F_N3F_V4F:
11287117f1b4Smrg         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
11297117f1b4Smrg         tcomps = 4;  ccomps = 4;  vcomps = 4;
11307117f1b4Smrg         ctype = GL_FLOAT;
11317117f1b4Smrg         coffset = 4*f;
11327117f1b4Smrg         noffset = 8*f;
11337117f1b4Smrg         voffset = 11*f;
11347117f1b4Smrg         defstride = 15*f;
11357117f1b4Smrg         break;
11367117f1b4Smrg      default:
11377117f1b4Smrg         _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
11387117f1b4Smrg         return;
11397117f1b4Smrg   }
11407117f1b4Smrg
11417117f1b4Smrg   if (stride==0) {
11427117f1b4Smrg      stride = defstride;
11437117f1b4Smrg   }
11447117f1b4Smrg
11457117f1b4Smrg   _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
11467117f1b4Smrg   _mesa_DisableClientState( GL_INDEX_ARRAY );
11477117f1b4Smrg   /* XXX also disable secondary color and generic arrays? */
11487117f1b4Smrg
11497117f1b4Smrg   /* Texcoords */
11507117f1b4Smrg   if (tflag) {
11517117f1b4Smrg      _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
11527117f1b4Smrg      _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
11537117f1b4Smrg                             (GLubyte *) pointer + toffset );
11547117f1b4Smrg   }
11557117f1b4Smrg   else {
11567117f1b4Smrg      _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
11577117f1b4Smrg   }
11587117f1b4Smrg
11597117f1b4Smrg   /* Color */
11607117f1b4Smrg   if (cflag) {
11617117f1b4Smrg      _mesa_EnableClientState( GL_COLOR_ARRAY );
11627117f1b4Smrg      _mesa_ColorPointer( ccomps, ctype, stride,
11637117f1b4Smrg			  (GLubyte *) pointer + coffset );
11647117f1b4Smrg   }
11657117f1b4Smrg   else {
11667117f1b4Smrg      _mesa_DisableClientState( GL_COLOR_ARRAY );
11677117f1b4Smrg   }
11687117f1b4Smrg
11697117f1b4Smrg
11707117f1b4Smrg   /* Normals */
11717117f1b4Smrg   if (nflag) {
11727117f1b4Smrg      _mesa_EnableClientState( GL_NORMAL_ARRAY );
11737117f1b4Smrg      _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
11747117f1b4Smrg   }
11757117f1b4Smrg   else {
11767117f1b4Smrg      _mesa_DisableClientState( GL_NORMAL_ARRAY );
11777117f1b4Smrg   }
11787117f1b4Smrg
11797117f1b4Smrg   /* Vertices */
11807117f1b4Smrg   _mesa_EnableClientState( GL_VERTEX_ARRAY );
11817117f1b4Smrg   _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
11827117f1b4Smrg			(GLubyte *) pointer + voffset );
11837117f1b4Smrg}
11847117f1b4Smrg
11857117f1b4Smrg
11867117f1b4Smrgvoid GLAPIENTRY
11877117f1b4Smrg_mesa_LockArraysEXT(GLint first, GLsizei count)
11887117f1b4Smrg{
11897117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1190af69d88dSmrg
1191af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
11927117f1b4Smrg
11937117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
11947117f1b4Smrg      _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
11957117f1b4Smrg
1196c1f859d4Smrg   if (first < 0) {
1197c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
1198c1f859d4Smrg      return;
11997117f1b4Smrg   }
1200c1f859d4Smrg   if (count <= 0) {
1201c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
1202c1f859d4Smrg      return;
1203c1f859d4Smrg   }
1204c1f859d4Smrg   if (ctx->Array.LockCount != 0) {
1205c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
1206c1f859d4Smrg      return;
12077117f1b4Smrg   }
12087117f1b4Smrg
1209c1f859d4Smrg   ctx->Array.LockFirst = first;
1210c1f859d4Smrg   ctx->Array.LockCount = count;
1211c1f859d4Smrg
12127117f1b4Smrg   ctx->NewState |= _NEW_ARRAY;
12137117f1b4Smrg}
12147117f1b4Smrg
12157117f1b4Smrg
12167117f1b4Smrgvoid GLAPIENTRY
12177117f1b4Smrg_mesa_UnlockArraysEXT( void )
12187117f1b4Smrg{
12197117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
1220af69d88dSmrg
1221af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
12227117f1b4Smrg
12237117f1b4Smrg   if (MESA_VERBOSE & VERBOSE_API)
12247117f1b4Smrg      _mesa_debug(ctx, "glUnlockArrays\n");
12257117f1b4Smrg
1226c1f859d4Smrg   if (ctx->Array.LockCount == 0) {
1227c1f859d4Smrg      _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
1228c1f859d4Smrg      return;
1229c1f859d4Smrg   }
1230c1f859d4Smrg
12317117f1b4Smrg   ctx->Array.LockFirst = 0;
12327117f1b4Smrg   ctx->Array.LockCount = 0;
12337117f1b4Smrg   ctx->NewState |= _NEW_ARRAY;
12347117f1b4Smrg}
12357117f1b4Smrg
12367117f1b4Smrg
12377117f1b4Smrg/* GL_EXT_multi_draw_arrays */
12387117f1b4Smrgvoid GLAPIENTRY
1239af69d88dSmrg_mesa_MultiDrawArrays( GLenum mode, const GLint *first,
12403464ebd5Sriastradh                          const GLsizei *count, GLsizei primcount )
12417117f1b4Smrg{
12427117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
12437117f1b4Smrg   GLint i;
12447117f1b4Smrg
1245af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
12467117f1b4Smrg
12477117f1b4Smrg   for (i = 0; i < primcount; i++) {
12487117f1b4Smrg      if (count[i] > 0) {
1249af69d88dSmrg         CALL_DrawArrays(ctx->CurrentDispatch, (mode, first[i], count[i]));
12507117f1b4Smrg      }
12517117f1b4Smrg   }
12527117f1b4Smrg}
12537117f1b4Smrg
12547117f1b4Smrg
12557117f1b4Smrg/* GL_IBM_multimode_draw_arrays */
12567117f1b4Smrgvoid GLAPIENTRY
12577117f1b4Smrg_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
12587117f1b4Smrg			      const GLsizei * count,
12597117f1b4Smrg			      GLsizei primcount, GLint modestride )
12607117f1b4Smrg{
12617117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
12627117f1b4Smrg   GLint i;
12637117f1b4Smrg
1264af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
12657117f1b4Smrg
12667117f1b4Smrg   for ( i = 0 ; i < primcount ; i++ ) {
12677117f1b4Smrg      if ( count[i] > 0 ) {
12687117f1b4Smrg         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1269af69d88dSmrg	 CALL_DrawArrays(ctx->CurrentDispatch, ( m, first[i], count[i] ));
12707117f1b4Smrg      }
12717117f1b4Smrg   }
12727117f1b4Smrg}
12737117f1b4Smrg
12747117f1b4Smrg
12757117f1b4Smrg/* GL_IBM_multimode_draw_arrays */
12767117f1b4Smrgvoid GLAPIENTRY
12777117f1b4Smrg_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
12787117f1b4Smrg				GLenum type, const GLvoid * const * indices,
12797117f1b4Smrg				GLsizei primcount, GLint modestride )
12807117f1b4Smrg{
12817117f1b4Smrg   GET_CURRENT_CONTEXT(ctx);
12827117f1b4Smrg   GLint i;
12837117f1b4Smrg
1284af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
12857117f1b4Smrg
12867117f1b4Smrg   /* XXX not sure about ARB_vertex_buffer_object handling here */
12877117f1b4Smrg
12887117f1b4Smrg   for ( i = 0 ; i < primcount ; i++ ) {
12897117f1b4Smrg      if ( count[i] > 0 ) {
12907117f1b4Smrg         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1291af69d88dSmrg	 CALL_DrawElements(ctx->CurrentDispatch, ( m, count[i], type,
1292af69d88dSmrg                                                   indices[i] ));
12937117f1b4Smrg      }
12947117f1b4Smrg   }
12957117f1b4Smrg}
12967117f1b4Smrg
12977117f1b4Smrg
12983464ebd5Sriastradh/**
12993464ebd5Sriastradh * GL_NV_primitive_restart and GL 3.1
13003464ebd5Sriastradh */
13013464ebd5Sriastradhvoid GLAPIENTRY
13023464ebd5Sriastradh_mesa_PrimitiveRestartIndex(GLuint index)
13033464ebd5Sriastradh{
13043464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
13053464ebd5Sriastradh
1306af69d88dSmrg   if (!ctx->Extensions.NV_primitive_restart && ctx->Version < 31) {
13073464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()");
13083464ebd5Sriastradh      return;
13093464ebd5Sriastradh   }
13103464ebd5Sriastradh
1311af69d88dSmrg   if (ctx->Array.RestartIndex != index) {
1312af69d88dSmrg      FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
1313af69d88dSmrg      ctx->Array.RestartIndex = index;
1314af69d88dSmrg   }
13153464ebd5Sriastradh}
13163464ebd5Sriastradh
13173464ebd5Sriastradh
13183464ebd5Sriastradh/**
13193464ebd5Sriastradh * See GL_ARB_instanced_arrays.
13203464ebd5Sriastradh * Note that the instance divisor only applies to generic arrays, not
13213464ebd5Sriastradh * the legacy vertex arrays.
13223464ebd5Sriastradh */
13233464ebd5Sriastradhvoid GLAPIENTRY
13243464ebd5Sriastradh_mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
13253464ebd5Sriastradh{
13263464ebd5Sriastradh   GET_CURRENT_CONTEXT(ctx);
1327af69d88dSmrg
1328af69d88dSmrg   const GLuint genericIndex = VERT_ATTRIB_GENERIC(index);
13293464ebd5Sriastradh
13303464ebd5Sriastradh   if (!ctx->Extensions.ARB_instanced_arrays) {
13313464ebd5Sriastradh      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
13323464ebd5Sriastradh      return;
13333464ebd5Sriastradh   }
13343464ebd5Sriastradh
1335af69d88dSmrg   if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
1336af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribDivisor(index = %u)",
13373464ebd5Sriastradh                  index);
13383464ebd5Sriastradh      return;
13393464ebd5Sriastradh   }
13403464ebd5Sriastradh
1341af69d88dSmrg   ASSERT(genericIndex < Elements(ctx->Array.VAO->VertexAttrib));
1342af69d88dSmrg
1343af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1344af69d88dSmrg    *
1345af69d88dSmrg    *    "The command
1346af69d88dSmrg    *
1347af69d88dSmrg    *       void VertexAttribDivisor(uint index, uint divisor);
1348af69d88dSmrg    *
1349af69d88dSmrg    *     is equivalent to (assuming no errors are generated):
1350af69d88dSmrg    *
1351af69d88dSmrg    *       VertexAttribBinding(index, index);
1352af69d88dSmrg    *       VertexBindingDivisor(index, divisor);"
1353af69d88dSmrg    */
1354af69d88dSmrg   vertex_attrib_binding(ctx, genericIndex, genericIndex);
1355af69d88dSmrg   vertex_binding_divisor(ctx, genericIndex, divisor);
13563464ebd5Sriastradh}
13573464ebd5Sriastradh
13583464ebd5Sriastradh
1359af69d88dSmrgunsigned
1360af69d88dSmrg_mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type)
1361af69d88dSmrg{
1362af69d88dSmrg   /* From the OpenGL 4.3 core specification, page 302:
1363af69d88dSmrg    * "If both PRIMITIVE_RESTART and PRIMITIVE_RESTART_FIXED_INDEX are
1364af69d88dSmrg    *  enabled, the index value determined by PRIMITIVE_RESTART_FIXED_INDEX
1365af69d88dSmrg    *  is used."
1366af69d88dSmrg    */
1367af69d88dSmrg   if (ctx->Array.PrimitiveRestartFixedIndex) {
1368af69d88dSmrg      switch (ib_type) {
1369af69d88dSmrg      case GL_UNSIGNED_BYTE:
1370af69d88dSmrg         return 0xff;
1371af69d88dSmrg      case GL_UNSIGNED_SHORT:
1372af69d88dSmrg         return 0xffff;
1373af69d88dSmrg      case GL_UNSIGNED_INT:
1374af69d88dSmrg         return 0xffffffff;
1375af69d88dSmrg      default:
1376af69d88dSmrg         assert(!"_mesa_primitive_restart_index: Invalid index buffer type.");
1377af69d88dSmrg      }
1378af69d88dSmrg   }
1379af69d88dSmrg
1380af69d88dSmrg   return ctx->Array.RestartIndex;
1381af69d88dSmrg}
1382af69d88dSmrg
1383af69d88dSmrg
1384af69d88dSmrg/**
1385af69d88dSmrg * GL_ARB_vertex_attrib_binding
1386af69d88dSmrg */
1387af69d88dSmrgvoid GLAPIENTRY
1388af69d88dSmrg_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
1389af69d88dSmrg                       GLsizei stride)
1390af69d88dSmrg{
1391af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1392af69d88dSmrg   const struct gl_vertex_array_object *vao = ctx->Array.VAO;
1393af69d88dSmrg   struct gl_buffer_object *vbo;
1394af69d88dSmrg
1395af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1396af69d88dSmrg
1397af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1398af69d88dSmrg    *
1399af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
1400af69d88dSmrg    *     is bound."
1401af69d88dSmrg    */
1402af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
1403af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
1404af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1405af69d88dSmrg                  "glBindVertexBuffer(No array object bound)");
1406af69d88dSmrg      return;
1407af69d88dSmrg   }
1408af69d88dSmrg
1409af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1410af69d88dSmrg    *
1411af69d88dSmrg    *    "An INVALID_VALUE error is generated if <bindingindex> is greater than
1412af69d88dSmrg    *     the value of MAX_VERTEX_ATTRIB_BINDINGS."
1413af69d88dSmrg    */
1414af69d88dSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
1415af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1416af69d88dSmrg                  "glBindVertexBuffer(bindingindex=%u > "
1417af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
1418af69d88dSmrg                  bindingIndex);
1419af69d88dSmrg      return;
1420af69d88dSmrg   }
1421af69d88dSmrg
1422af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1423af69d88dSmrg    *
1424af69d88dSmrg    *    "The error INVALID_VALUE is generated if <stride> or <offset>
1425af69d88dSmrg    *     are negative."
1426af69d88dSmrg    */
1427af69d88dSmrg   if (offset < 0) {
1428af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1429af69d88dSmrg                  "glBindVertexBuffer(offset=%" PRId64 " < 0)",
1430af69d88dSmrg                  (int64_t) offset);
1431af69d88dSmrg      return;
1432af69d88dSmrg   }
1433af69d88dSmrg
1434af69d88dSmrg   if (stride < 0) {
1435af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1436af69d88dSmrg                  "glBindVertexBuffer(stride=%d < 0)", stride);
1437af69d88dSmrg      return;
1438af69d88dSmrg   }
1439af69d88dSmrg
1440af69d88dSmrg   if (buffer == vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) {
1441af69d88dSmrg      vbo = vao->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj;
1442af69d88dSmrg   } else if (buffer != 0) {
1443af69d88dSmrg      vbo = _mesa_lookup_bufferobj(ctx, buffer);
1444af69d88dSmrg
1445af69d88dSmrg      /* From the GL_ARB_vertex_attrib_array spec:
1446af69d88dSmrg       *
1447af69d88dSmrg       *   "[Core profile only:]
1448af69d88dSmrg       *    An INVALID_OPERATION error is generated if buffer is not zero or a
1449af69d88dSmrg       *    name returned from a previous call to GenBuffers, or if such a name
1450af69d88dSmrg       *    has since been deleted with DeleteBuffers.
1451af69d88dSmrg       *
1452af69d88dSmrg       * Otherwise, we fall back to the same compat profile behavior as other
1453af69d88dSmrg       * object references (automatically gen it).
1454af69d88dSmrg       */
1455af69d88dSmrg      if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer,
1456af69d88dSmrg                                        &vbo, "glBindVertexBuffer"))
1457af69d88dSmrg         return;
1458af69d88dSmrg   } else {
1459af69d88dSmrg      /* The ARB_vertex_attrib_binding spec says:
1460af69d88dSmrg       *
1461af69d88dSmrg       *    "If <buffer> is zero, any buffer object attached to this
1462af69d88dSmrg       *     bindpoint is detached."
1463af69d88dSmrg       */
1464af69d88dSmrg      vbo = ctx->Shared->NullBufferObj;
1465af69d88dSmrg   }
1466af69d88dSmrg
1467af69d88dSmrg   bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex),
1468af69d88dSmrg                      vbo, offset, stride);
1469af69d88dSmrg}
1470af69d88dSmrg
1471af69d88dSmrg
1472af69d88dSmrgvoid GLAPIENTRY
1473af69d88dSmrg_mesa_BindVertexBuffers(GLuint first, GLsizei count, const GLuint *buffers,
1474af69d88dSmrg                        const GLintptr *offsets, const GLsizei *strides)
1475af69d88dSmrg{
1476af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1477af69d88dSmrg   struct gl_vertex_array_object * const vao = ctx->Array.VAO;
1478af69d88dSmrg   GLuint i;
1479af69d88dSmrg
1480af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1481af69d88dSmrg
1482af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1483af69d88dSmrg    *
1484af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no
1485af69d88dSmrg    *     vertex array object is bound."
1486af69d88dSmrg    */
1487af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
1488af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
1489af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1490af69d88dSmrg                  "glBindVertexBuffers(No array object bound)");
1491af69d88dSmrg      return;
1492af69d88dSmrg   }
1493af69d88dSmrg
1494af69d88dSmrg   /* The ARB_multi_bind spec says:
1495af69d88dSmrg    *
1496af69d88dSmrg    *    "An INVALID_OPERATION error is generated if <first> + <count>
1497af69d88dSmrg    *     is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS."
1498af69d88dSmrg    */
1499af69d88dSmrg   if (first + count > ctx->Const.MaxVertexAttribBindings) {
1500af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1501af69d88dSmrg                  "glBindVertexBuffers(first=%u + count=%d > the value of "
1502af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS=%u)",
1503af69d88dSmrg                  first, count, ctx->Const.MaxVertexAttribBindings);
1504af69d88dSmrg      return;
1505af69d88dSmrg   }
1506af69d88dSmrg
1507af69d88dSmrg   if (!buffers) {
1508af69d88dSmrg      /**
1509af69d88dSmrg       * The ARB_multi_bind spec says:
1510af69d88dSmrg       *
1511af69d88dSmrg       *    "If <buffers> is NULL, each affected vertex buffer binding point
1512af69d88dSmrg       *     from <first> through <first>+<count>-1 will be reset to have no
1513af69d88dSmrg       *     bound buffer object.  In this case, the offsets and strides
1514af69d88dSmrg       *     associated with the binding points are set to default values,
1515af69d88dSmrg       *     ignoring <offsets> and <strides>."
1516af69d88dSmrg       */
1517af69d88dSmrg      struct gl_buffer_object *vbo = ctx->Shared->NullBufferObj;
1518af69d88dSmrg
1519af69d88dSmrg      for (i = 0; i < count; i++)
1520af69d88dSmrg         bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo, 0, 16);
1521af69d88dSmrg
1522af69d88dSmrg      return;
1523af69d88dSmrg   }
1524af69d88dSmrg
1525af69d88dSmrg   /* Note that the error semantics for multi-bind commands differ from
1526af69d88dSmrg    * those of other GL commands.
1527af69d88dSmrg    *
1528af69d88dSmrg    * The Issues section in the ARB_multi_bind spec says:
1529af69d88dSmrg    *
1530af69d88dSmrg    *    "(11) Typically, OpenGL specifies that if an error is generated by
1531af69d88dSmrg    *          a command, that command has no effect.  This is somewhat
1532af69d88dSmrg    *          unfortunate for multi-bind commands, because it would require
1533af69d88dSmrg    *          a first pass to scan the entire list of bound objects for
1534af69d88dSmrg    *          errors and then a second pass to actually perform the
1535af69d88dSmrg    *          bindings.  Should we have different error semantics?
1536af69d88dSmrg    *
1537af69d88dSmrg    *       RESOLVED:  Yes.  In this specification, when the parameters for
1538af69d88dSmrg    *       one of the <count> binding points are invalid, that binding
1539af69d88dSmrg    *       point is not updated and an error will be generated.  However,
1540af69d88dSmrg    *       other binding points in the same command will be updated if
1541af69d88dSmrg    *       their parameters are valid and no other error occurs."
1542af69d88dSmrg    */
1543af69d88dSmrg
1544af69d88dSmrg   _mesa_begin_bufferobj_lookups(ctx);
1545af69d88dSmrg
1546af69d88dSmrg   for (i = 0; i < count; i++) {
1547af69d88dSmrg      struct gl_buffer_object *vbo;
1548af69d88dSmrg
1549af69d88dSmrg      /* The ARB_multi_bind spec says:
1550af69d88dSmrg       *
1551af69d88dSmrg       *    "An INVALID_VALUE error is generated if any value in
1552af69d88dSmrg       *     <offsets> or <strides> is negative (per binding)."
1553af69d88dSmrg       */
1554af69d88dSmrg      if (offsets[i] < 0) {
1555af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
1556af69d88dSmrg                     "glBindVertexBuffers(offsets[%u]=%" PRId64 " < 0)",
1557af69d88dSmrg                     i, (int64_t) offsets[i]);
1558af69d88dSmrg         continue;
1559af69d88dSmrg      }
1560af69d88dSmrg
1561af69d88dSmrg      if (strides[i] < 0) {
1562af69d88dSmrg         _mesa_error(ctx, GL_INVALID_VALUE,
1563af69d88dSmrg                     "glBindVertexBuffers(strides[%u]=%d < 0)",
1564af69d88dSmrg                     i, strides[i]);
1565af69d88dSmrg         continue;
1566af69d88dSmrg      }
1567af69d88dSmrg
1568af69d88dSmrg      if (buffers[i]) {
1569af69d88dSmrg         struct gl_vertex_buffer_binding *binding =
1570af69d88dSmrg            &vao->VertexBinding[VERT_ATTRIB_GENERIC(first + i)];
1571af69d88dSmrg
1572af69d88dSmrg         if (buffers[i] == binding->BufferObj->Name)
1573af69d88dSmrg            vbo = binding->BufferObj;
1574af69d88dSmrg         else
1575af69d88dSmrg            vbo = _mesa_multi_bind_lookup_bufferobj(ctx, buffers, i,
1576af69d88dSmrg                                                    "glBindVertexBuffers");
1577af69d88dSmrg
1578af69d88dSmrg         if (!vbo)
1579af69d88dSmrg            continue;
1580af69d88dSmrg      } else {
1581af69d88dSmrg         vbo = ctx->Shared->NullBufferObj;
1582af69d88dSmrg      }
1583af69d88dSmrg
1584af69d88dSmrg      bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(first + i), vbo,
1585af69d88dSmrg                         offsets[i], strides[i]);
1586af69d88dSmrg   }
1587af69d88dSmrg
1588af69d88dSmrg   _mesa_end_bufferobj_lookups(ctx);
1589af69d88dSmrg}
1590af69d88dSmrg
1591af69d88dSmrg
1592af69d88dSmrgvoid GLAPIENTRY
1593af69d88dSmrg_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
1594af69d88dSmrg                         GLboolean normalized, GLuint relativeOffset)
1595af69d88dSmrg{
1596af69d88dSmrg    const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
1597af69d88dSmrg                                   SHORT_BIT | UNSIGNED_SHORT_BIT |
1598af69d88dSmrg                                   INT_BIT | UNSIGNED_INT_BIT |
1599af69d88dSmrg                                   HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
1600af69d88dSmrg                                   FIXED_GL_BIT |
1601af69d88dSmrg                                   UNSIGNED_INT_2_10_10_10_REV_BIT |
1602af69d88dSmrg                                   INT_2_10_10_10_REV_BIT |
1603af69d88dSmrg                                   UNSIGNED_INT_10F_11F_11F_REV_BIT);
1604af69d88dSmrg
1605af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1606af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1607af69d88dSmrg
1608af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1609af69d88dSmrg    *
1610af69d88dSmrg    *    "An INVALID_OPERATION error is generated under any of the following
1611af69d88dSmrg    *     conditions:
1612af69d88dSmrg    *     - if no vertex array object is currently bound (see section 2.10);
1613af69d88dSmrg    *     - ..."
1614af69d88dSmrg    */
1615af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
1616af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
1617af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1618af69d88dSmrg                  "glVertexAttribFormat(No array object bound)");
1619af69d88dSmrg      return;
1620af69d88dSmrg   }
1621af69d88dSmrg
1622af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1623af69d88dSmrg    *
1624af69d88dSmrg    *   "The error INVALID_VALUE is generated if index is greater than or equal
1625af69d88dSmrg    *     to the value of MAX_VERTEX_ATTRIBS."
1626af69d88dSmrg    */
1627af69d88dSmrg   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
1628af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1629af69d88dSmrg                  "glVertexAttribFormat(attribindex=%u > "
1630af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIBS)",
1631af69d88dSmrg                  attribIndex);
1632af69d88dSmrg      return;
1633af69d88dSmrg   }
1634af69d88dSmrg
1635af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
1636af69d88dSmrg
1637af69d88dSmrg   update_array_format(ctx, "glVertexAttribFormat",
1638af69d88dSmrg                       VERT_ATTRIB_GENERIC(attribIndex),
1639af69d88dSmrg                       legalTypes, 1, BGRA_OR_4, size, type, normalized,
1640af69d88dSmrg                       GL_FALSE, relativeOffset);
1641af69d88dSmrg}
1642af69d88dSmrg
1643af69d88dSmrg
1644af69d88dSmrgvoid GLAPIENTRY
1645af69d88dSmrg_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
1646af69d88dSmrg                          GLuint relativeOffset)
1647af69d88dSmrg{
1648af69d88dSmrg   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
1649af69d88dSmrg                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
1650af69d88dSmrg                                  INT_BIT | UNSIGNED_INT_BIT);
1651af69d88dSmrg
1652af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1653af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1654af69d88dSmrg
1655af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1656af69d88dSmrg    *
1657af69d88dSmrg    *    "An INVALID_OPERATION error is generated under any of the following
1658af69d88dSmrg    *     conditions:
1659af69d88dSmrg    *     - if no vertex array object is currently bound (see section 2.10);
1660af69d88dSmrg    *     - ..."
1661af69d88dSmrg    */
1662af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
1663af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
1664af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1665af69d88dSmrg                  "glVertexAttribIFormat(No array object bound)");
1666af69d88dSmrg      return;
1667af69d88dSmrg   }
1668af69d88dSmrg
1669af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1670af69d88dSmrg    *
1671af69d88dSmrg    *   "The error INVALID_VALUE is generated if index is greater than
1672af69d88dSmrg    *    or equal to the value of MAX_VERTEX_ATTRIBS."
1673af69d88dSmrg    */
1674af69d88dSmrg   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
1675af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1676af69d88dSmrg                  "glVertexAttribIFormat(attribindex=%u > "
1677af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIBS)",
1678af69d88dSmrg                  attribIndex);
1679af69d88dSmrg      return;
1680af69d88dSmrg   }
1681af69d88dSmrg
1682af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
1683af69d88dSmrg
1684af69d88dSmrg   update_array_format(ctx, "glVertexAttribIFormat",
1685af69d88dSmrg                       VERT_ATTRIB_GENERIC(attribIndex),
1686af69d88dSmrg                       legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE,
1687af69d88dSmrg                       relativeOffset);
1688af69d88dSmrg}
1689af69d88dSmrg
1690af69d88dSmrg
1691af69d88dSmrgvoid GLAPIENTRY
1692af69d88dSmrg_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
1693af69d88dSmrg                          GLuint relativeOffset)
1694af69d88dSmrg{
1695af69d88dSmrg   const GLbitfield legalTypes = DOUBLE_BIT;
1696af69d88dSmrg
1697af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1698af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1699af69d88dSmrg
1700af69d88dSmrg   /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
1701af69d88dSmrg    *
1702af69d88dSmrg    *    "An INVALID_OPERATION error is generated under any of the following
1703af69d88dSmrg    *     conditions:
1704af69d88dSmrg    *     • if no vertex array object is currently bound (see section 10.4);
1705af69d88dSmrg    *     • ..."
1706af69d88dSmrg    *
1707af69d88dSmrg    * This language is missing from the extension spec, but we assume
1708af69d88dSmrg    * that this is an oversight.
1709af69d88dSmrg    */
1710af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
1711af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
1712af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1713af69d88dSmrg                  "glVertexAttribLFormat(No array object bound)");
1714af69d88dSmrg      return;
1715af69d88dSmrg   }
1716af69d88dSmrg
1717af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1718af69d88dSmrg    *
1719af69d88dSmrg    *   "The error INVALID_VALUE is generated if <attribindex> is greater than
1720af69d88dSmrg    *    or equal to the value of MAX_VERTEX_ATTRIBS."
1721af69d88dSmrg    */
1722af69d88dSmrg   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
1723af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1724af69d88dSmrg                  "glVertexAttribLFormat(attribindex=%u > "
1725af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIBS)",
1726af69d88dSmrg                  attribIndex);
1727af69d88dSmrg      return;
1728af69d88dSmrg   }
1729af69d88dSmrg
1730af69d88dSmrg   FLUSH_VERTICES(ctx, 0);
1731af69d88dSmrg
1732af69d88dSmrg   update_array_format(ctx, "glVertexAttribLFormat",
1733af69d88dSmrg                       VERT_ATTRIB_GENERIC(attribIndex),
1734af69d88dSmrg                       legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE,
1735af69d88dSmrg                       relativeOffset);
1736af69d88dSmrg}
1737af69d88dSmrg
1738af69d88dSmrg
1739af69d88dSmrgvoid GLAPIENTRY
1740af69d88dSmrg_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
1741af69d88dSmrg{
1742af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1743af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1744af69d88dSmrg
1745af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1746af69d88dSmrg    *
1747af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
1748af69d88dSmrg    *     is bound."
1749af69d88dSmrg    */
1750af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
1751af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
1752af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1753af69d88dSmrg                  "glVertexAttribBinding(No array object bound)");
1754af69d88dSmrg      return;
1755af69d88dSmrg   }
1756af69d88dSmrg
1757af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1758af69d88dSmrg    *
1759af69d88dSmrg    *    "<attribindex> must be less than the value of MAX_VERTEX_ATTRIBS and
1760af69d88dSmrg    *     <bindingindex> must be less than the value of
1761af69d88dSmrg    *     MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE
1762af69d88dSmrg    *     is generated."
1763af69d88dSmrg    */
1764af69d88dSmrg   if (attribIndex >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs) {
1765af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1766af69d88dSmrg                  "glVertexAttribBinding(attribindex=%u >= "
1767af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIBS)",
1768af69d88dSmrg                  attribIndex);
1769af69d88dSmrg      return;
1770af69d88dSmrg   }
1771af69d88dSmrg
1772af69d88dSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
1773af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1774af69d88dSmrg                  "glVertexAttribBinding(bindingindex=%u >= "
1775af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
1776af69d88dSmrg                  bindingIndex);
1777af69d88dSmrg      return;
1778af69d88dSmrg   }
1779af69d88dSmrg
1780af69d88dSmrg   ASSERT(VERT_ATTRIB_GENERIC(attribIndex) <
1781af69d88dSmrg          Elements(ctx->Array.VAO->VertexAttrib));
1782af69d88dSmrg
1783af69d88dSmrg   vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex),
1784af69d88dSmrg                         VERT_ATTRIB_GENERIC(bindingIndex));
1785af69d88dSmrg}
1786af69d88dSmrg
1787af69d88dSmrg
1788af69d88dSmrgvoid GLAPIENTRY
1789af69d88dSmrg_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
1790af69d88dSmrg{
1791af69d88dSmrg   GET_CURRENT_CONTEXT(ctx);
1792af69d88dSmrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
1793af69d88dSmrg
1794af69d88dSmrg   if (!ctx->Extensions.ARB_instanced_arrays) {
1795af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()");
1796af69d88dSmrg      return;
1797af69d88dSmrg   }
1798af69d88dSmrg
1799af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1800af69d88dSmrg    *
1801af69d88dSmrg    *    "An INVALID_OPERATION error is generated if no vertex array object
1802af69d88dSmrg    *     is bound."
1803af69d88dSmrg    */
1804af69d88dSmrg   if (ctx->API == API_OPENGL_CORE &&
1805af69d88dSmrg       ctx->Array.VAO == ctx->Array.DefaultVAO) {
1806af69d88dSmrg      _mesa_error(ctx, GL_INVALID_OPERATION,
1807af69d88dSmrg                  "glVertexBindingDivisor(No array object bound)");
1808af69d88dSmrg      return;
1809af69d88dSmrg   }
1810af69d88dSmrg
1811af69d88dSmrg   /* The ARB_vertex_attrib_binding spec says:
1812af69d88dSmrg    *
1813af69d88dSmrg    *    "An INVALID_VALUE error is generated if <bindingindex> is greater
1814af69d88dSmrg    *     than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS."
1815af69d88dSmrg    */
1816af69d88dSmrg   if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
1817af69d88dSmrg      _mesa_error(ctx, GL_INVALID_VALUE,
1818af69d88dSmrg                  "glVertexBindingDivisor(bindingindex=%u > "
1819af69d88dSmrg                  "GL_MAX_VERTEX_ATTRIB_BINDINGS)",
1820af69d88dSmrg                  bindingIndex);
1821af69d88dSmrg      return;
1822af69d88dSmrg   }
1823af69d88dSmrg
1824af69d88dSmrg   vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
1825af69d88dSmrg}
1826af69d88dSmrg
18273464ebd5Sriastradh
18284a49301eSmrg/**
18294a49301eSmrg * Copy one client vertex array to another.
18304a49301eSmrg */
18314a49301eSmrgvoid
18323464ebd5Sriastradh_mesa_copy_client_array(struct gl_context *ctx,
18334a49301eSmrg                        struct gl_client_array *dst,
18344a49301eSmrg                        struct gl_client_array *src)
18354a49301eSmrg{
18364a49301eSmrg   dst->Size = src->Size;
18374a49301eSmrg   dst->Type = src->Type;
18384a49301eSmrg   dst->Format = src->Format;
18394a49301eSmrg   dst->Stride = src->Stride;
18404a49301eSmrg   dst->StrideB = src->StrideB;
18414a49301eSmrg   dst->Ptr = src->Ptr;
18424a49301eSmrg   dst->Enabled = src->Enabled;
18434a49301eSmrg   dst->Normalized = src->Normalized;
18443464ebd5Sriastradh   dst->Integer = src->Integer;
18453464ebd5Sriastradh   dst->InstanceDivisor = src->InstanceDivisor;
18464a49301eSmrg   dst->_ElementSize = src->_ElementSize;
18474a49301eSmrg   _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
18484a49301eSmrg   dst->_MaxElement = src->_MaxElement;
18494a49301eSmrg}
18504a49301eSmrg
1851af69d88dSmrgvoid
1852af69d88dSmrg_mesa_copy_vertex_attrib_array(struct gl_context *ctx,
1853af69d88dSmrg                               struct gl_vertex_attrib_array *dst,
1854af69d88dSmrg                               const struct gl_vertex_attrib_array *src)
1855af69d88dSmrg{
1856af69d88dSmrg   dst->Size           = src->Size;
1857af69d88dSmrg   dst->Type           = src->Type;
1858af69d88dSmrg   dst->Format         = src->Format;
1859af69d88dSmrg   dst->VertexBinding  = src->VertexBinding;
1860af69d88dSmrg   dst->RelativeOffset = src->RelativeOffset;
1861af69d88dSmrg   dst->Format         = src->Format;
1862af69d88dSmrg   dst->Integer        = src->Integer;
1863af69d88dSmrg   dst->Normalized     = src->Normalized;
1864af69d88dSmrg   dst->Ptr            = src->Ptr;
1865af69d88dSmrg   dst->Enabled        = src->Enabled;
1866af69d88dSmrg   dst->_ElementSize   = src->_ElementSize;
1867af69d88dSmrg}
1868af69d88dSmrg
1869af69d88dSmrgvoid
1870af69d88dSmrg_mesa_copy_vertex_buffer_binding(struct gl_context *ctx,
1871af69d88dSmrg                                 struct gl_vertex_buffer_binding *dst,
1872af69d88dSmrg                                 const struct gl_vertex_buffer_binding *src)
1873af69d88dSmrg{
1874af69d88dSmrg   dst->Offset          = src->Offset;
1875af69d88dSmrg   dst->Stride          = src->Stride;
1876af69d88dSmrg   dst->InstanceDivisor = src->InstanceDivisor;
1877af69d88dSmrg   dst->_BoundArrays    = src->_BoundArrays;
18784a49301eSmrg
1879af69d88dSmrg   _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1880af69d88dSmrg}
18814a49301eSmrg
18824a49301eSmrg/**
18834a49301eSmrg * Print vertex array's fields.
18844a49301eSmrg */
18854a49301eSmrgstatic void
18864a49301eSmrgprint_array(const char *name, GLint index, const struct gl_client_array *array)
18874a49301eSmrg{
18884a49301eSmrg   if (index >= 0)
1889cdc920a0Smrg      printf("  %s[%d]: ", name, index);
18904a49301eSmrg   else
1891cdc920a0Smrg      printf("  %s: ", name);
18923464ebd5Sriastradh   printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu), MaxElem=%u\n",
1893cdc920a0Smrg	  array->Ptr, array->Type, array->Size,
1894cdc920a0Smrg	  array->_ElementSize, array->StrideB,
18953464ebd5Sriastradh	  array->BufferObj->Name, (unsigned long) array->BufferObj->Size,
1896cdc920a0Smrg	  array->_MaxElement);
18974a49301eSmrg}
18984a49301eSmrg
18994a49301eSmrg
19004a49301eSmrg/**
19014a49301eSmrg * Print current vertex object/array info.  For debug.
19024a49301eSmrg */
19034a49301eSmrgvoid
19043464ebd5Sriastradh_mesa_print_arrays(struct gl_context *ctx)
19054a49301eSmrg{
1906af69d88dSmrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
19074a49301eSmrg   GLuint i;
19084a49301eSmrg
1909af69d88dSmrg   _mesa_update_vao_max_element(ctx, vao);
1910af69d88dSmrg
1911af69d88dSmrg   printf("Array Object %u\n", vao->Name);
1912af69d88dSmrg   if (vao->_VertexAttrib[VERT_ATTRIB_POS].Enabled)
1913af69d88dSmrg      print_array("Vertex", -1, &vao->_VertexAttrib[VERT_ATTRIB_POS]);
1914af69d88dSmrg   if (vao->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled)
1915af69d88dSmrg      print_array("Normal", -1, &vao->_VertexAttrib[VERT_ATTRIB_NORMAL]);
1916af69d88dSmrg   if (vao->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled)
1917af69d88dSmrg      print_array("Color", -1, &vao->_VertexAttrib[VERT_ATTRIB_COLOR0]);
1918af69d88dSmrg   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
1919af69d88dSmrg      if (vao->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled)
1920af69d88dSmrg         print_array("TexCoord", i, &vao->_VertexAttrib[VERT_ATTRIB_TEX(i)]);
1921af69d88dSmrg   for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++)
1922af69d88dSmrg      if (vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
1923af69d88dSmrg         print_array("Attrib", i, &vao->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
1924af69d88dSmrg   printf("  _MaxElement = %u\n", vao->_MaxElement);
19254a49301eSmrg}
19264a49301eSmrg
19274a49301eSmrg
19287117f1b4Smrg/**
19297117f1b4Smrg * Initialize vertex array state for given context.
19307117f1b4Smrg */
19317117f1b4Smrgvoid
19323464ebd5Sriastradh_mesa_init_varray(struct gl_context *ctx)
19337117f1b4Smrg{
1934af69d88dSmrg   ctx->Array.DefaultVAO = ctx->Driver.NewArrayObject(ctx, 0);
1935af69d88dSmrg   _mesa_reference_vao(ctx, &ctx->Array.VAO, ctx->Array.DefaultVAO);
19367117f1b4Smrg   ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
19374a49301eSmrg
19384a49301eSmrg   ctx->Array.Objects = _mesa_NewHashTable();
19394a49301eSmrg}
19404a49301eSmrg
19414a49301eSmrg
19424a49301eSmrg/**
19434a49301eSmrg * Callback for deleting an array object.  Called by _mesa_HashDeleteAll().
19444a49301eSmrg */
19454a49301eSmrgstatic void
19464a49301eSmrgdelete_arrayobj_cb(GLuint id, void *data, void *userData)
19474a49301eSmrg{
1948af69d88dSmrg   struct gl_vertex_array_object *vao = (struct gl_vertex_array_object *) data;
19493464ebd5Sriastradh   struct gl_context *ctx = (struct gl_context *) userData;
1950af69d88dSmrg   _mesa_delete_vao(ctx, vao);
19514a49301eSmrg}
19524a49301eSmrg
19534a49301eSmrg
19544a49301eSmrg/**
19554a49301eSmrg * Free vertex array state for given context.
19564a49301eSmrg */
19574a49301eSmrgvoid
19583464ebd5Sriastradh_mesa_free_varray_data(struct gl_context *ctx)
19594a49301eSmrg{
19604a49301eSmrg   _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
19614a49301eSmrg   _mesa_DeleteHashTable(ctx->Array.Objects);
19627117f1b4Smrg}
1963