varray.c revision a8f475d8f6b56ddec36634437d007e06b48ff1cd
1/*
2 * Mesa 3-D graphics library
3 * Version:  7.6
4 *
5 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6 * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27#include "glheader.h"
28#include "imports.h"
29#include "bufferobj.h"
30#include "context.h"
31#include "enable.h"
32#include "enums.h"
33#include "hash.h"
34#include "image.h"
35#include "macros.h"
36#include "mfeatures.h"
37#include "mtypes.h"
38#include "varray.h"
39#include "arrayobj.h"
40#include "main/dispatch.h"
41
42
43/** Used to do error checking for GL_EXT_vertex_array_bgra */
44#define BGRA_OR_4  5
45
46
47/** Used to indicate which GL datatypes are accepted by each of the
48 * glVertex/Color/Attrib/EtcPointer() functions.
49 */
50#define BOOL_BIT             0x1
51#define BYTE_BIT             0x2
52#define UNSIGNED_BYTE_BIT    0x4
53#define SHORT_BIT            0x8
54#define UNSIGNED_SHORT_BIT   0x10
55#define INT_BIT              0x20
56#define UNSIGNED_INT_BIT     0x40
57#define HALF_BIT             0x80
58#define FLOAT_BIT            0x100
59#define DOUBLE_BIT           0x200
60#define FIXED_ES_BIT         0x400
61#define FIXED_GL_BIT         0x800
62#define UNSIGNED_INT_2_10_10_10_REV_BIT 0x1000
63#define INT_2_10_10_10_REV_BIT 0x2000
64
65
66/** Convert GL datatype enum into a <type>_BIT value seen above */
67static GLbitfield
68type_to_bit(const struct gl_context *ctx, GLenum type)
69{
70   switch (type) {
71   case GL_BOOL:
72      return BOOL_BIT;
73   case GL_BYTE:
74      return BYTE_BIT;
75   case GL_UNSIGNED_BYTE:
76      return UNSIGNED_BYTE_BIT;
77   case GL_SHORT:
78      return SHORT_BIT;
79   case GL_UNSIGNED_SHORT:
80      return UNSIGNED_SHORT_BIT;
81   case GL_INT:
82      return INT_BIT;
83   case GL_UNSIGNED_INT:
84      return UNSIGNED_INT_BIT;
85   case GL_HALF_FLOAT:
86      if (ctx->Extensions.ARB_half_float_vertex)
87         return HALF_BIT;
88      else
89         return 0x0;
90   case GL_FLOAT:
91      return FLOAT_BIT;
92   case GL_DOUBLE:
93      return DOUBLE_BIT;
94   case GL_FIXED:
95      return _mesa_is_desktop_gl(ctx) ? FIXED_GL_BIT : FIXED_ES_BIT;
96   case GL_UNSIGNED_INT_2_10_10_10_REV:
97      return UNSIGNED_INT_2_10_10_10_REV_BIT;
98   case GL_INT_2_10_10_10_REV:
99      return INT_2_10_10_10_REV_BIT;
100   default:
101      return 0;
102   }
103}
104
105
106/**
107 * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
108 * functions.
109 *
110 * \param func  name of calling function used for error reporting
111 * \param attrib  the attribute array index to update
112 * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
113 * \param sizeMin  min allowable size value
114 * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
115 * \param size  components per element (1, 2, 3 or 4)
116 * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
117 * \param stride  stride between elements, in elements
118 * \param normalized  are integer types converted to floats in [-1, 1]?
119 * \param integer  integer-valued values (will not be normalized to [-1,1])
120 * \param ptr  the address (or offset inside VBO) of the array data
121 */
122static void
123update_array(struct gl_context *ctx,
124             const char *func,
125             GLuint attrib, GLbitfield legalTypesMask,
126             GLint sizeMin, GLint sizeMax,
127             GLint size, GLenum type, GLsizei stride,
128             GLboolean normalized, GLboolean integer,
129             const GLvoid *ptr)
130{
131   struct gl_client_array *array;
132   GLbitfield typeBit;
133   GLsizei elementSize;
134   GLenum format = GL_RGBA;
135
136   if (_mesa_is_gles(ctx)) {
137      /* Once Mesa gets support for GL_OES_vertex_half_float this mask will
138       * change.  Adding support for this extension isn't quite as trivial as
139       * we'd like because ES uses a different enum value for GL_HALF_FLOAT.
140       */
141      legalTypesMask &= ~(FIXED_GL_BIT | HALF_BIT | DOUBLE_BIT);
142
143      /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
144       * 3.0.  The 2_10_10_10 types are added in OpenGL ES 3.0 or
145       * GL_OES_vertex_type_10_10_10_2.
146       */
147      if (ctx->Version < 30) {
148         legalTypesMask &= ~(UNSIGNED_INT_BIT
149                             | INT_BIT
150                             | UNSIGNED_INT_2_10_10_10_REV_BIT
151                             | INT_2_10_10_10_REV_BIT);
152      }
153
154      /* BGRA ordering is not supported in ES contexts.
155       */
156      if (sizeMax == BGRA_OR_4)
157         sizeMax = 4;
158   } else {
159      legalTypesMask &= ~FIXED_ES_BIT;
160
161      if (!ctx->Extensions.ARB_ES2_compatibility)
162         legalTypesMask &= ~FIXED_GL_BIT;
163
164      if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
165         legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
166                             INT_2_10_10_10_REV_BIT);
167   }
168
169   typeBit = type_to_bit(ctx, type);
170   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
171      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
172                  func, _mesa_lookup_enum_by_nr(type));
173      return;
174   }
175
176   /* Do size parameter checking.
177    * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and
178    * must be handled specially.
179    */
180   if (ctx->Extensions.EXT_vertex_array_bgra &&
181       sizeMax == BGRA_OR_4 &&
182       size == GL_BGRA) {
183      GLboolean bgra_error = GL_FALSE;
184
185      if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
186         if (type != GL_UNSIGNED_INT_2_10_10_10_REV &&
187             type != GL_INT_2_10_10_10_REV &&
188             type != GL_UNSIGNED_BYTE)
189            bgra_error = GL_TRUE;
190      } else if (type != GL_UNSIGNED_BYTE)
191         bgra_error = GL_TRUE;
192
193      if (bgra_error) {
194         _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func);
195         return;
196      }
197      format = GL_BGRA;
198      size = 4;
199   }
200   else if (size < sizeMin || size > sizeMax || size > 4) {
201      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
202      return;
203   }
204
205   if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
206       (type == GL_UNSIGNED_INT_2_10_10_10_REV ||
207        type == GL_INT_2_10_10_10_REV) && size != 4) {
208      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
209      return;
210   }
211
212   ASSERT(size <= 4);
213
214   if (stride < 0) {
215      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
216      return;
217   }
218
219   if (ctx->Array.ArrayObj->ARBsemantics &&
220       !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) {
221      /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
222       * Generate GL_INVALID_OPERATION if that's not true.
223       */
224      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
225      return;
226   }
227
228   elementSize = _mesa_sizeof_type(type) * size;
229
230   array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
231   array->Size = size;
232   array->Type = type;
233   array->Format = format;
234   array->Stride = stride;
235   array->StrideB = stride ? stride : elementSize;
236   array->Normalized = normalized;
237   array->Integer = integer;
238   array->Ptr = (const GLubyte *) ptr;
239   array->_ElementSize = elementSize;
240
241   _mesa_reference_buffer_object(ctx, &array->BufferObj,
242                                 ctx->Array.ArrayBufferObj);
243
244   ctx->NewState |= _NEW_ARRAY;
245   ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib);
246}
247
248
249void GLAPIENTRY
250_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
251{
252   GLbitfield legalTypes = (SHORT_BIT | INT_BIT | FLOAT_BIT |
253                            DOUBLE_BIT | HALF_BIT | FIXED_ES_BIT |
254                            UNSIGNED_INT_2_10_10_10_REV_BIT |
255                            INT_2_10_10_10_REV_BIT);
256   GET_CURRENT_CONTEXT(ctx);
257   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
258
259   if (ctx->API == API_OPENGLES)
260      legalTypes |= BYTE_BIT;
261
262   update_array(ctx, "glVertexPointer", VERT_ATTRIB_POS,
263                legalTypes, 2, 4,
264                size, type, stride, GL_FALSE, GL_FALSE, ptr);
265}
266
267
268void GLAPIENTRY
269_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
270{
271   GET_CURRENT_CONTEXT(ctx);
272   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
273      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
274      : (BYTE_BIT | SHORT_BIT | INT_BIT |
275         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
276         UNSIGNED_INT_2_10_10_10_REV_BIT |
277         INT_2_10_10_10_REV_BIT);
278   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
279
280   update_array(ctx, "glNormalPointer", VERT_ATTRIB_NORMAL,
281                legalTypes, 3, 3,
282                3, type, stride, GL_TRUE, GL_FALSE, ptr);
283}
284
285
286void GLAPIENTRY
287_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
288{
289   GET_CURRENT_CONTEXT(ctx);
290   const GLbitfield legalTypes = (ctx->API == API_OPENGLES)
291      ? (UNSIGNED_BYTE_BIT | HALF_BIT | FLOAT_BIT | FIXED_ES_BIT)
292      : (BYTE_BIT | UNSIGNED_BYTE_BIT |
293         SHORT_BIT | UNSIGNED_SHORT_BIT |
294         INT_BIT | UNSIGNED_INT_BIT |
295         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
296         UNSIGNED_INT_2_10_10_10_REV_BIT |
297         INT_2_10_10_10_REV_BIT);
298   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 4 : 3;
299   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
300
301   update_array(ctx, "glColorPointer", VERT_ATTRIB_COLOR0,
302                legalTypes, sizeMin, BGRA_OR_4,
303                size, type, stride, GL_TRUE, GL_FALSE, ptr);
304}
305
306
307void GLAPIENTRY
308_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
309{
310   const GLbitfield legalTypes = (HALF_BIT | FLOAT_BIT | DOUBLE_BIT);
311   GET_CURRENT_CONTEXT(ctx);
312   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
313
314   update_array(ctx, "glFogCoordPointer", VERT_ATTRIB_FOG,
315                legalTypes, 1, 1,
316                1, type, stride, GL_FALSE, GL_FALSE, ptr);
317}
318
319
320void GLAPIENTRY
321_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
322{
323   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT | INT_BIT |
324                                  FLOAT_BIT | DOUBLE_BIT);
325   GET_CURRENT_CONTEXT(ctx);
326   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
327
328   update_array(ctx, "glIndexPointer", VERT_ATTRIB_COLOR_INDEX,
329                legalTypes, 1, 1,
330                1, type, stride, GL_FALSE, GL_FALSE, ptr);
331}
332
333
334void GLAPIENTRY
335_mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
336			       GLsizei stride, const GLvoid *ptr)
337{
338   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
339                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
340                                  INT_BIT | UNSIGNED_INT_BIT |
341                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
342                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
343                                  INT_2_10_10_10_REV_BIT);
344   GET_CURRENT_CONTEXT(ctx);
345   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
346
347   update_array(ctx, "glSecondaryColorPointer", VERT_ATTRIB_COLOR1,
348                legalTypes, 3, BGRA_OR_4,
349                size, type, stride, GL_TRUE, GL_FALSE, ptr);
350}
351
352
353void GLAPIENTRY
354_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
355                      const GLvoid *ptr)
356{
357   GET_CURRENT_CONTEXT(ctx);
358   GLbitfield legalTypes = (ctx->API == API_OPENGLES)
359      ? (BYTE_BIT | SHORT_BIT | FLOAT_BIT | FIXED_ES_BIT)
360      : (SHORT_BIT | INT_BIT |
361         HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
362         UNSIGNED_INT_2_10_10_10_REV_BIT |
363         INT_2_10_10_10_REV_BIT);
364   const GLint sizeMin = (ctx->API == API_OPENGLES) ? 2 : 1;
365   const GLuint unit = ctx->Array.ActiveTexture;
366   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
367
368   update_array(ctx, "glTexCoordPointer", VERT_ATTRIB_TEX(unit),
369                legalTypes, sizeMin, 4,
370                size, type, stride, GL_FALSE, GL_FALSE,
371                ptr);
372}
373
374
375void GLAPIENTRY
376_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
377{
378   const GLbitfield legalTypes = UNSIGNED_BYTE_BIT;
379   /* see table 2.4 edits in GL_EXT_gpu_shader4 spec: */
380   const GLboolean integer = GL_TRUE;
381   GET_CURRENT_CONTEXT(ctx);
382   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
383
384   update_array(ctx, "glEdgeFlagPointer", VERT_ATTRIB_EDGEFLAG,
385                legalTypes, 1, 1,
386                1, GL_UNSIGNED_BYTE, stride, GL_FALSE, integer, ptr);
387}
388
389
390void GLAPIENTRY
391_mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
392{
393   const GLbitfield legalTypes = (FLOAT_BIT | FIXED_ES_BIT);
394   GET_CURRENT_CONTEXT(ctx);
395   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
396
397   if (ctx->API != API_OPENGLES) {
398      _mesa_error(ctx, GL_INVALID_OPERATION,
399                  "glPointSizePointer(ES 1.x only)");
400      return;
401   }
402
403   update_array(ctx, "glPointSizePointer", VERT_ATTRIB_POINT_SIZE,
404                legalTypes, 1, 1,
405                1, type, stride, GL_FALSE, GL_FALSE, ptr);
406}
407
408
409#if FEATURE_NV_vertex_program
410/**
411 * Set a vertex attribute array.
412 * Note that these arrays DO alias the conventional GL vertex arrays
413 * (position, normal, color, fog, texcoord, etc).
414 * The generic attribute slots at #16 and above are not touched.
415 */
416void GLAPIENTRY
417_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
418                            GLsizei stride, const GLvoid *ptr)
419{
420   const GLbitfield legalTypes = (UNSIGNED_BYTE_BIT | SHORT_BIT |
421                                  FLOAT_BIT | DOUBLE_BIT);
422   GLboolean normalized = GL_FALSE;
423   GET_CURRENT_CONTEXT(ctx);
424   ASSERT_OUTSIDE_BEGIN_END(ctx);
425
426   if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
427      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
428      return;
429   }
430
431   if (type == GL_UNSIGNED_BYTE && size != 4) {
432      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
433      return;
434   }
435
436   update_array(ctx, "glVertexAttribPointerNV", VERT_ATTRIB_GENERIC(index),
437                legalTypes, 1, BGRA_OR_4,
438                size, type, stride, normalized, GL_FALSE, ptr);
439}
440#endif
441
442
443#if FEATURE_ARB_vertex_program
444/**
445 * Set a generic vertex attribute array.
446 * Note that these arrays DO NOT alias the conventional GL vertex arrays
447 * (position, normal, color, fog, texcoord, etc).
448 */
449void GLAPIENTRY
450_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
451                             GLboolean normalized,
452                             GLsizei stride, const GLvoid *ptr)
453{
454   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
455                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
456                                  INT_BIT | UNSIGNED_INT_BIT |
457                                  HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
458                                  FIXED_ES_BIT | FIXED_GL_BIT |
459                                  UNSIGNED_INT_2_10_10_10_REV_BIT |
460                                  INT_2_10_10_10_REV_BIT);
461   GET_CURRENT_CONTEXT(ctx);
462   ASSERT_OUTSIDE_BEGIN_END(ctx);
463
464   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
465      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
466      return;
467   }
468
469   update_array(ctx, "glVertexAttribPointer", VERT_ATTRIB_GENERIC(index),
470                legalTypes, 1, BGRA_OR_4,
471                size, type, stride, normalized, GL_FALSE, ptr);
472}
473#endif
474
475
476/**
477 * GL_EXT_gpu_shader4 / GL 3.0.
478 * Set an integer-valued vertex attribute array.
479 * Note that these arrays DO NOT alias the conventional GL vertex arrays
480 * (position, normal, color, fog, texcoord, etc).
481 */
482void GLAPIENTRY
483_mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
484                           GLsizei stride, const GLvoid *ptr)
485{
486   const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
487                                  SHORT_BIT | UNSIGNED_SHORT_BIT |
488                                  INT_BIT | UNSIGNED_INT_BIT);
489   const GLboolean normalized = GL_FALSE;
490   const GLboolean integer = GL_TRUE;
491   GET_CURRENT_CONTEXT(ctx);
492   ASSERT_OUTSIDE_BEGIN_END(ctx);
493
494   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
495      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribIPointer(index)");
496      return;
497   }
498
499   update_array(ctx, "glVertexAttribIPointer", VERT_ATTRIB_GENERIC(index),
500                legalTypes, 1, 4,
501                size, type, stride, normalized, integer, ptr);
502}
503
504
505
506void GLAPIENTRY
507_mesa_EnableVertexAttribArrayARB(GLuint index)
508{
509   struct gl_array_object *arrayObj;
510   GET_CURRENT_CONTEXT(ctx);
511   ASSERT_OUTSIDE_BEGIN_END(ctx);
512
513   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
514      _mesa_error(ctx, GL_INVALID_VALUE,
515                  "glEnableVertexAttribArrayARB(index)");
516      return;
517   }
518
519   arrayObj = ctx->Array.ArrayObj;
520
521   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib));
522
523   if (!arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
524      /* was disabled, now being enabled */
525      FLUSH_VERTICES(ctx, _NEW_ARRAY);
526      arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE;
527      arrayObj->_Enabled |= VERT_BIT_GENERIC(index);
528      arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
529   }
530}
531
532
533void GLAPIENTRY
534_mesa_DisableVertexAttribArrayARB(GLuint index)
535{
536   struct gl_array_object *arrayObj;
537   GET_CURRENT_CONTEXT(ctx);
538   ASSERT_OUTSIDE_BEGIN_END(ctx);
539
540   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
541      _mesa_error(ctx, GL_INVALID_VALUE,
542                  "glDisableVertexAttribArrayARB(index)");
543      return;
544   }
545
546   arrayObj = ctx->Array.ArrayObj;
547
548   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib));
549
550   if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
551      /* was enabled, now being disabled */
552      FLUSH_VERTICES(ctx, _NEW_ARRAY);
553      arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
554      arrayObj->_Enabled &= ~VERT_BIT_GENERIC(index);
555      arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
556   }
557}
558
559
560/**
561 * Return info for a vertex attribute array (no alias with legacy
562 * vertex attributes (pos, normal, color, etc)).  This function does
563 * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
564 */
565static GLuint
566get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
567                  const char *caller)
568{
569   const struct gl_client_array *array;
570
571   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
572      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
573      return 0;
574   }
575
576   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib));
577
578   array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
579
580   switch (pname) {
581   case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
582      return array->Enabled;
583   case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
584      return array->Size;
585   case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
586      return array->Stride;
587   case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
588      return array->Type;
589   case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
590      return array->Normalized;
591   case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
592      return array->BufferObj->Name;
593   case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
594      if (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4) {
595         return array->Integer;
596      }
597      goto error;
598   case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
599      if (ctx->Extensions.ARB_instanced_arrays) {
600         return array->InstanceDivisor;
601      }
602      goto error;
603   default:
604      ; /* fall-through */
605   }
606
607error:
608   _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname);
609   return 0;
610}
611
612
613static const GLfloat *
614get_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
615{
616   if (index == 0) {
617      if (ctx->API != API_OPENGLES2) {
618	 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(index==0)", function);
619	 return NULL;
620      }
621   }
622   else if (index >= ctx->Const.VertexProgram.MaxAttribs) {
623      _mesa_error(ctx, GL_INVALID_VALUE,
624		  "%s(index>=GL_MAX_VERTEX_ATTRIBS)", function);
625      return NULL;
626   }
627
628   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib));
629
630   FLUSH_CURRENT(ctx, 0);
631   return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)];
632}
633
634void GLAPIENTRY
635_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
636{
637   GET_CURRENT_CONTEXT(ctx);
638   ASSERT_OUTSIDE_BEGIN_END(ctx);
639
640   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
641      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribfv");
642      if (v != NULL) {
643         COPY_4V(params, v);
644      }
645   }
646   else {
647      params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname,
648                                                    "glGetVertexAttribfv");
649   }
650}
651
652
653void GLAPIENTRY
654_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
655{
656   GET_CURRENT_CONTEXT(ctx);
657   ASSERT_OUTSIDE_BEGIN_END(ctx);
658
659   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
660      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribdv");
661      if (v != NULL) {
662         params[0] = (GLdouble) v[0];
663         params[1] = (GLdouble) v[1];
664         params[2] = (GLdouble) v[2];
665         params[3] = (GLdouble) v[3];
666      }
667   }
668   else {
669      params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname,
670                                                     "glGetVertexAttribdv");
671   }
672}
673
674
675void GLAPIENTRY
676_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
677{
678   GET_CURRENT_CONTEXT(ctx);
679   ASSERT_OUTSIDE_BEGIN_END(ctx);
680
681   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
682      const GLfloat *v = get_current_attrib(ctx, index, "glGetVertexAttribiv");
683      if (v != NULL) {
684         /* XXX should floats in[0,1] be scaled to full int range? */
685         params[0] = (GLint) v[0];
686         params[1] = (GLint) v[1];
687         params[2] = (GLint) v[2];
688         params[3] = (GLint) v[3];
689      }
690   }
691   else {
692      params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
693                                                  "glGetVertexAttribiv");
694   }
695}
696
697
698/** GL 3.0 */
699void GLAPIENTRY
700_mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
701{
702   GET_CURRENT_CONTEXT(ctx);
703   ASSERT_OUTSIDE_BEGIN_END(ctx);
704
705   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
706      const GLfloat *v =
707	 get_current_attrib(ctx, index, "glGetVertexAttribIiv");
708      if (v != NULL) {
709         /* XXX we don't have true integer-valued vertex attribs yet */
710         params[0] = (GLint) v[0];
711         params[1] = (GLint) v[1];
712         params[2] = (GLint) v[2];
713         params[3] = (GLint) v[3];
714      }
715   }
716   else {
717      params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
718                                                  "glGetVertexAttribIiv");
719   }
720}
721
722
723/** GL 3.0 */
724void GLAPIENTRY
725_mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
726{
727   GET_CURRENT_CONTEXT(ctx);
728   ASSERT_OUTSIDE_BEGIN_END(ctx);
729
730   if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
731      const GLfloat *v =
732	 get_current_attrib(ctx, index, "glGetVertexAttribIuiv");
733      if (v != NULL) {
734         /* XXX we don't have true integer-valued vertex attribs yet */
735         params[0] = (GLuint) v[0];
736         params[1] = (GLuint) v[1];
737         params[2] = (GLuint) v[2];
738         params[3] = (GLuint) v[3];
739      }
740   }
741   else {
742      params[0] = get_vertex_array_attrib(ctx, index, pname,
743                                          "glGetVertexAttribIuiv");
744   }
745}
746
747
748void GLAPIENTRY
749_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
750{
751   GET_CURRENT_CONTEXT(ctx);
752   ASSERT_OUTSIDE_BEGIN_END(ctx);
753
754   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
755      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
756      return;
757   }
758
759   if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
760      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
761      return;
762   }
763
764   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib));
765
766   *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
767}
768
769
770void GLAPIENTRY
771_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
772                       GLsizei count, const GLvoid *ptr)
773{
774   (void) count;
775   _mesa_VertexPointer(size, type, stride, ptr);
776}
777
778
779void GLAPIENTRY
780_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
781                       const GLvoid *ptr)
782{
783   (void) count;
784   _mesa_NormalPointer(type, stride, ptr);
785}
786
787
788void GLAPIENTRY
789_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
790                      const GLvoid *ptr)
791{
792   (void) count;
793   _mesa_ColorPointer(size, type, stride, ptr);
794}
795
796
797void GLAPIENTRY
798_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
799                      const GLvoid *ptr)
800{
801   (void) count;
802   _mesa_IndexPointer(type, stride, ptr);
803}
804
805
806void GLAPIENTRY
807_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
808                         GLsizei count, const GLvoid *ptr)
809{
810   (void) count;
811   _mesa_TexCoordPointer(size, type, stride, ptr);
812}
813
814
815void GLAPIENTRY
816_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
817{
818   (void) count;
819   _mesa_EdgeFlagPointer(stride, ptr);
820}
821
822
823void GLAPIENTRY
824_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
825{
826   GET_CURRENT_CONTEXT(ctx);
827   GLboolean tflag, cflag, nflag;  /* enable/disable flags */
828   GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
829   GLenum ctype = 0;               /* color type */
830   GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
831   const GLint toffset = 0;        /* always zero */
832   GLint defstride;                /* default stride */
833   GLint c, f;
834
835   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
836
837   f = sizeof(GLfloat);
838   c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
839
840   if (stride < 0) {
841      _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
842      return;
843   }
844
845   switch (format) {
846      case GL_V2F:
847         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
848         tcomps = 0;  ccomps = 0;  vcomps = 2;
849         voffset = 0;
850         defstride = 2*f;
851         break;
852      case GL_V3F:
853         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
854         tcomps = 0;  ccomps = 0;  vcomps = 3;
855         voffset = 0;
856         defstride = 3*f;
857         break;
858      case GL_C4UB_V2F:
859         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
860         tcomps = 0;  ccomps = 4;  vcomps = 2;
861         ctype = GL_UNSIGNED_BYTE;
862         coffset = 0;
863         voffset = c;
864         defstride = c + 2*f;
865         break;
866      case GL_C4UB_V3F:
867         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
868         tcomps = 0;  ccomps = 4;  vcomps = 3;
869         ctype = GL_UNSIGNED_BYTE;
870         coffset = 0;
871         voffset = c;
872         defstride = c + 3*f;
873         break;
874      case GL_C3F_V3F:
875         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
876         tcomps = 0;  ccomps = 3;  vcomps = 3;
877         ctype = GL_FLOAT;
878         coffset = 0;
879         voffset = 3*f;
880         defstride = 6*f;
881         break;
882      case GL_N3F_V3F:
883         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
884         tcomps = 0;  ccomps = 0;  vcomps = 3;
885         noffset = 0;
886         voffset = 3*f;
887         defstride = 6*f;
888         break;
889      case GL_C4F_N3F_V3F:
890         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
891         tcomps = 0;  ccomps = 4;  vcomps = 3;
892         ctype = GL_FLOAT;
893         coffset = 0;
894         noffset = 4*f;
895         voffset = 7*f;
896         defstride = 10*f;
897         break;
898      case GL_T2F_V3F:
899         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
900         tcomps = 2;  ccomps = 0;  vcomps = 3;
901         voffset = 2*f;
902         defstride = 5*f;
903         break;
904      case GL_T4F_V4F:
905         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
906         tcomps = 4;  ccomps = 0;  vcomps = 4;
907         voffset = 4*f;
908         defstride = 8*f;
909         break;
910      case GL_T2F_C4UB_V3F:
911         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
912         tcomps = 2;  ccomps = 4;  vcomps = 3;
913         ctype = GL_UNSIGNED_BYTE;
914         coffset = 2*f;
915         voffset = c+2*f;
916         defstride = c+5*f;
917         break;
918      case GL_T2F_C3F_V3F:
919         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
920         tcomps = 2;  ccomps = 3;  vcomps = 3;
921         ctype = GL_FLOAT;
922         coffset = 2*f;
923         voffset = 5*f;
924         defstride = 8*f;
925         break;
926      case GL_T2F_N3F_V3F:
927         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
928         tcomps = 2;  ccomps = 0;  vcomps = 3;
929         noffset = 2*f;
930         voffset = 5*f;
931         defstride = 8*f;
932         break;
933      case GL_T2F_C4F_N3F_V3F:
934         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
935         tcomps = 2;  ccomps = 4;  vcomps = 3;
936         ctype = GL_FLOAT;
937         coffset = 2*f;
938         noffset = 6*f;
939         voffset = 9*f;
940         defstride = 12*f;
941         break;
942      case GL_T4F_C4F_N3F_V4F:
943         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
944         tcomps = 4;  ccomps = 4;  vcomps = 4;
945         ctype = GL_FLOAT;
946         coffset = 4*f;
947         noffset = 8*f;
948         voffset = 11*f;
949         defstride = 15*f;
950         break;
951      default:
952         _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
953         return;
954   }
955
956   if (stride==0) {
957      stride = defstride;
958   }
959
960   _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
961   _mesa_DisableClientState( GL_INDEX_ARRAY );
962   /* XXX also disable secondary color and generic arrays? */
963
964   /* Texcoords */
965   if (tflag) {
966      _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
967      _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
968                             (GLubyte *) pointer + toffset );
969   }
970   else {
971      _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
972   }
973
974   /* Color */
975   if (cflag) {
976      _mesa_EnableClientState( GL_COLOR_ARRAY );
977      _mesa_ColorPointer( ccomps, ctype, stride,
978			  (GLubyte *) pointer + coffset );
979   }
980   else {
981      _mesa_DisableClientState( GL_COLOR_ARRAY );
982   }
983
984
985   /* Normals */
986   if (nflag) {
987      _mesa_EnableClientState( GL_NORMAL_ARRAY );
988      _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
989   }
990   else {
991      _mesa_DisableClientState( GL_NORMAL_ARRAY );
992   }
993
994   /* Vertices */
995   _mesa_EnableClientState( GL_VERTEX_ARRAY );
996   _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
997			(GLubyte *) pointer + voffset );
998}
999
1000
1001void GLAPIENTRY
1002_mesa_LockArraysEXT(GLint first, GLsizei count)
1003{
1004   GET_CURRENT_CONTEXT(ctx);
1005   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1006
1007   if (MESA_VERBOSE & VERBOSE_API)
1008      _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
1009
1010   if (first < 0) {
1011      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
1012      return;
1013   }
1014   if (count <= 0) {
1015      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
1016      return;
1017   }
1018   if (ctx->Array.LockCount != 0) {
1019      _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
1020      return;
1021   }
1022
1023   ctx->Array.LockFirst = first;
1024   ctx->Array.LockCount = count;
1025
1026   ctx->NewState |= _NEW_ARRAY;
1027}
1028
1029
1030void GLAPIENTRY
1031_mesa_UnlockArraysEXT( void )
1032{
1033   GET_CURRENT_CONTEXT(ctx);
1034   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1035
1036   if (MESA_VERBOSE & VERBOSE_API)
1037      _mesa_debug(ctx, "glUnlockArrays\n");
1038
1039   if (ctx->Array.LockCount == 0) {
1040      _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
1041      return;
1042   }
1043
1044   ctx->Array.LockFirst = 0;
1045   ctx->Array.LockCount = 0;
1046   ctx->NewState |= _NEW_ARRAY;
1047}
1048
1049
1050/* GL_EXT_multi_draw_arrays */
1051void GLAPIENTRY
1052_mesa_MultiDrawArraysEXT( GLenum mode, const GLint *first,
1053                          const GLsizei *count, GLsizei primcount )
1054{
1055   GET_CURRENT_CONTEXT(ctx);
1056   GLint i;
1057
1058   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1059
1060   for (i = 0; i < primcount; i++) {
1061      if (count[i] > 0) {
1062         CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
1063      }
1064   }
1065}
1066
1067
1068/* GL_IBM_multimode_draw_arrays */
1069void GLAPIENTRY
1070_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1071			      const GLsizei * count,
1072			      GLsizei primcount, GLint modestride )
1073{
1074   GET_CURRENT_CONTEXT(ctx);
1075   GLint i;
1076
1077   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1078
1079   for ( i = 0 ; i < primcount ; i++ ) {
1080      if ( count[i] > 0 ) {
1081         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1082	 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1083      }
1084   }
1085}
1086
1087
1088/* GL_IBM_multimode_draw_arrays */
1089void GLAPIENTRY
1090_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1091				GLenum type, const GLvoid * const * indices,
1092				GLsizei primcount, GLint modestride )
1093{
1094   GET_CURRENT_CONTEXT(ctx);
1095   GLint i;
1096
1097   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1098
1099   /* XXX not sure about ARB_vertex_buffer_object handling here */
1100
1101   for ( i = 0 ; i < primcount ; i++ ) {
1102      if ( count[i] > 0 ) {
1103         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1104	 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1105      }
1106   }
1107}
1108
1109
1110/**
1111 * GL_NV_primitive_restart and GL 3.1
1112 */
1113void GLAPIENTRY
1114_mesa_PrimitiveRestartIndex(GLuint index)
1115{
1116   GET_CURRENT_CONTEXT(ctx);
1117
1118   if (!ctx->Extensions.NV_primitive_restart && ctx->Version < 31) {
1119      _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndexNV()");
1120      return;
1121   }
1122
1123   ASSERT_OUTSIDE_BEGIN_END(ctx);
1124
1125   if (ctx->Array.RestartIndex != index) {
1126      FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
1127      ctx->Array.RestartIndex = index;
1128   }
1129}
1130
1131
1132/**
1133 * See GL_ARB_instanced_arrays.
1134 * Note that the instance divisor only applies to generic arrays, not
1135 * the legacy vertex arrays.
1136 */
1137void GLAPIENTRY
1138_mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
1139{
1140   struct gl_client_array *array;
1141   GET_CURRENT_CONTEXT(ctx);
1142   ASSERT_OUTSIDE_BEGIN_END(ctx);
1143
1144   if (!ctx->Extensions.ARB_instanced_arrays) {
1145      _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
1146      return;
1147   }
1148
1149   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
1150      _mesa_error(ctx, GL_INVALID_ENUM, "glVertexAttribDivisor(index = %u)",
1151                  index);
1152      return;
1153   }
1154
1155   ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib));
1156
1157   array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
1158   if (array->InstanceDivisor != divisor) {
1159      FLUSH_VERTICES(ctx, _NEW_ARRAY);
1160      array->InstanceDivisor = divisor;
1161      ctx->Array.ArrayObj->NewArrays |= VERT_BIT(VERT_ATTRIB_GENERIC(index));
1162   }
1163}
1164
1165
1166
1167/**
1168 * Copy one client vertex array to another.
1169 */
1170void
1171_mesa_copy_client_array(struct gl_context *ctx,
1172                        struct gl_client_array *dst,
1173                        struct gl_client_array *src)
1174{
1175   dst->Size = src->Size;
1176   dst->Type = src->Type;
1177   dst->Format = src->Format;
1178   dst->Stride = src->Stride;
1179   dst->StrideB = src->StrideB;
1180   dst->Ptr = src->Ptr;
1181   dst->Enabled = src->Enabled;
1182   dst->Normalized = src->Normalized;
1183   dst->Integer = src->Integer;
1184   dst->InstanceDivisor = src->InstanceDivisor;
1185   dst->_ElementSize = src->_ElementSize;
1186   _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1187   dst->_MaxElement = src->_MaxElement;
1188}
1189
1190
1191
1192/**
1193 * Print vertex array's fields.
1194 */
1195static void
1196print_array(const char *name, GLint index, const struct gl_client_array *array)
1197{
1198   if (index >= 0)
1199      printf("  %s[%d]: ", name, index);
1200   else
1201      printf("  %s: ", name);
1202   printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu), MaxElem=%u\n",
1203	  array->Ptr, array->Type, array->Size,
1204	  array->_ElementSize, array->StrideB,
1205	  array->BufferObj->Name, (unsigned long) array->BufferObj->Size,
1206	  array->_MaxElement);
1207}
1208
1209
1210/**
1211 * Print current vertex object/array info.  For debug.
1212 */
1213void
1214_mesa_print_arrays(struct gl_context *ctx)
1215{
1216   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1217   GLuint i;
1218
1219   _mesa_update_array_object_max_element(ctx, arrayObj);
1220
1221   printf("Array Object %u\n", arrayObj->Name);
1222   if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled)
1223      print_array("Vertex", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]);
1224   if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled)
1225      print_array("Normal", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]);
1226   if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled)
1227      print_array("Color", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]);
1228   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
1229      if (arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled)
1230         print_array("TexCoord", i, &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)]);
1231   for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++)
1232      if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
1233         print_array("Attrib", i, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
1234   printf("  _MaxElement = %u\n", arrayObj->_MaxElement);
1235}
1236
1237
1238/**
1239 * Initialize vertex array state for given context.
1240 */
1241void
1242_mesa_init_varray(struct gl_context *ctx)
1243{
1244   ctx->Array.DefaultArrayObj = ctx->Driver.NewArrayObject(ctx, 0);
1245   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1246                                ctx->Array.DefaultArrayObj);
1247   ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
1248
1249   ctx->Array.Objects = _mesa_NewHashTable();
1250}
1251
1252
1253/**
1254 * Callback for deleting an array object.  Called by _mesa_HashDeleteAll().
1255 */
1256static void
1257delete_arrayobj_cb(GLuint id, void *data, void *userData)
1258{
1259   struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1260   struct gl_context *ctx = (struct gl_context *) userData;
1261   _mesa_delete_array_object(ctx, arrayObj);
1262}
1263
1264
1265/**
1266 * Free vertex array state for given context.
1267 */
1268void
1269_mesa_free_varray_data(struct gl_context *ctx)
1270{
1271   _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1272   _mesa_DeleteHashTable(ctx->Array.Objects);
1273}
1274