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