varray.c revision 4a49301e
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 "mtypes.h"
35#include "varray.h"
36#include "arrayobj.h"
37#include "glapi/dispatch.h"
38
39
40/**
41 * Set the fields of a vertex array.
42 * Also do an error check for GL_ARB_vertex_array_object: check that
43 * all arrays reside in VBOs when using a vertex array object.
44 *
45 * \param array  the array to update
46 * \param dirtyBit  which bit to set in ctx->Array.NewState for this array
47 * \param elementSize  size of each array element, in bytes
48 * \param size  components per element (1, 2, 3 or 4)
49 * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
50 * \param format  either GL_RGBA or GL_BGRA
51 * \param stride  stride between elements, in elements
52 * \param normalized  are integer types converted to floats in [-1, 1]?
53 * \param ptr  the address (or offset inside VBO) of the array data
54 */
55static void
56update_array(GLcontext *ctx, struct gl_client_array *array,
57             GLbitfield dirtyBit, GLsizei elementSize,
58             GLint size, GLenum type, GLenum format,
59             GLsizei stride, GLboolean normalized, const GLvoid *ptr)
60{
61   ASSERT(format == GL_RGBA || format == GL_BGRA);
62
63   if (ctx->Array.ArrayObj->VBOonly &&
64       ctx->Array.ArrayBufferObj->Name == 0) {
65      /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
66       * Generate GL_INVALID_OPERATION if that's not true.
67       */
68      _mesa_error(ctx, GL_INVALID_OPERATION,
69                  "glVertex/Normal/EtcPointer(non-VBO array)");
70      return;
71   }
72
73   array->Size = size;
74   array->Type = type;
75   array->Format = format;
76   array->Stride = stride;
77   array->StrideB = stride ? stride : elementSize;
78   array->Normalized = normalized;
79   array->Ptr = (const GLubyte *) ptr;
80   array->_ElementSize = elementSize;
81
82   _mesa_reference_buffer_object(ctx, &array->BufferObj,
83                                 ctx->Array.ArrayBufferObj);
84
85   ctx->NewState |= _NEW_ARRAY;
86   ctx->Array.NewState |= dirtyBit;
87}
88
89
90void GLAPIENTRY
91_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
92{
93   GLsizei elementSize;
94   GET_CURRENT_CONTEXT(ctx);
95   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
96
97   if (size < 2 || size > 4) {
98      _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
99      return;
100   }
101   if (stride < 0) {
102      _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
103      return;
104   }
105
106   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
107      _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size,
108                  _mesa_lookup_enum_by_nr( type ), stride);
109
110   /* always need to check that <type> is legal */
111   switch (type) {
112      case GL_SHORT:
113         elementSize = size * sizeof(GLshort);
114         break;
115      case GL_INT:
116         elementSize = size * sizeof(GLint);
117         break;
118      case GL_FLOAT:
119         elementSize = size * sizeof(GLfloat);
120         break;
121      case GL_DOUBLE:
122         elementSize = size * sizeof(GLdouble);
123         break;
124#if FEATURE_fixedpt
125      case GL_FIXED:
126         elementSize = size * sizeof(GLfixed);
127         break;
128#endif
129#if FEATURE_vertex_array_byte
130      case GL_BYTE:
131         elementSize = size * sizeof(GLbyte);
132         break;
133#endif
134      default:
135         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
136                      _mesa_lookup_enum_by_nr(type));
137         return;
138   }
139
140   update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
141                elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
142}
143
144
145void GLAPIENTRY
146_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
147{
148   GLsizei elementSize;
149   GET_CURRENT_CONTEXT(ctx);
150   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
151
152   if (stride < 0) {
153      _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
154      return;
155   }
156
157   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
158      _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
159                  _mesa_lookup_enum_by_nr( type ), stride);
160
161   switch (type) {
162      case GL_BYTE:
163         elementSize = 3 * sizeof(GLbyte);
164         break;
165      case GL_SHORT:
166         elementSize = 3 * sizeof(GLshort);
167         break;
168      case GL_INT:
169         elementSize = 3 * sizeof(GLint);
170         break;
171      case GL_FLOAT:
172         elementSize = 3 * sizeof(GLfloat);
173         break;
174      case GL_DOUBLE:
175         elementSize = 3 * sizeof(GLdouble);
176         break;
177#if FEATURE_fixedpt
178      case GL_FIXED:
179         elementSize = 3 * sizeof(GLfixed);
180         break;
181#endif
182      default:
183         _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
184                      _mesa_lookup_enum_by_nr(type));
185         return;
186   }
187
188   update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
189                elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr);
190}
191
192
193void GLAPIENTRY
194_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
195{
196   GLsizei elementSize;
197   GLenum format;
198   GET_CURRENT_CONTEXT(ctx);
199   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
200
201   if (size < 3 || size > 4) {
202      if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
203         _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(size)");
204         return;
205      }
206   }
207   if (stride < 0) {
208      _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
209      return;
210   }
211
212   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
213      _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
214                  _mesa_lookup_enum_by_nr( type ), stride);
215
216   if (size == GL_BGRA) {
217      if (type != GL_UNSIGNED_BYTE) {
218         _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
219         return;
220      }
221      format = GL_BGRA;
222      size = 4;
223   }
224   else {
225      format = GL_RGBA;
226   }
227
228   switch (type) {
229      case GL_BYTE:
230         elementSize = size * sizeof(GLbyte);
231         break;
232      case GL_UNSIGNED_BYTE:
233         elementSize = size * sizeof(GLubyte);
234         break;
235      case GL_SHORT:
236         elementSize = size * sizeof(GLshort);
237         break;
238      case GL_UNSIGNED_SHORT:
239         elementSize = size * sizeof(GLushort);
240         break;
241      case GL_INT:
242         elementSize = size * sizeof(GLint);
243         break;
244      case GL_UNSIGNED_INT:
245         elementSize = size * sizeof(GLuint);
246         break;
247      case GL_FLOAT:
248         elementSize = size * sizeof(GLfloat);
249         break;
250      case GL_DOUBLE:
251         elementSize = size * sizeof(GLdouble);
252         break;
253#if FEATURE_fixedpt
254      case GL_FIXED:
255         elementSize = size * sizeof(GLfixed);
256         break;
257#endif
258      default:
259         _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
260                      _mesa_lookup_enum_by_nr(type));
261         return;
262   }
263
264   update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
265                elementSize, size, type, format, stride, GL_TRUE, ptr);
266}
267
268
269void GLAPIENTRY
270_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
271{
272   GLint elementSize;
273   GET_CURRENT_CONTEXT(ctx);
274   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
275
276   if (stride < 0) {
277      _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
278      return;
279   }
280
281   switch (type) {
282      case GL_FLOAT:
283         elementSize = sizeof(GLfloat);
284         break;
285      case GL_DOUBLE:
286         elementSize = sizeof(GLdouble);
287         break;
288      default:
289         _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
290         return;
291   }
292
293   update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
294                elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
295}
296
297
298void GLAPIENTRY
299_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
300{
301   GLsizei elementSize;
302   GET_CURRENT_CONTEXT(ctx);
303   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
304
305   if (stride < 0) {
306      _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
307      return;
308   }
309
310   switch (type) {
311      case GL_UNSIGNED_BYTE:
312         elementSize = sizeof(GLubyte);
313         break;
314      case GL_SHORT:
315         elementSize = sizeof(GLshort);
316         break;
317      case GL_INT:
318         elementSize = sizeof(GLint);
319         break;
320      case GL_FLOAT:
321         elementSize = sizeof(GLfloat);
322         break;
323      case GL_DOUBLE:
324         elementSize = sizeof(GLdouble);
325         break;
326      default:
327         _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
328         return;
329   }
330
331   update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
332                elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
333}
334
335
336void GLAPIENTRY
337_mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
338			       GLsizei stride, const GLvoid *ptr)
339{
340   GLsizei elementSize;
341   GLenum format;
342   GET_CURRENT_CONTEXT(ctx);
343   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
344
345   if (size != 3 && size != 4) {
346      if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
347         _mesa_error(ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)");
348         return;
349      }
350   }
351   if (stride < 0) {
352      _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
353      return;
354   }
355
356   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
357      _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
358                  size, _mesa_lookup_enum_by_nr( type ), stride);
359
360   if (size == GL_BGRA) {
361      if (type != GL_UNSIGNED_BYTE) {
362         _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
363         return;
364      }
365      format = GL_BGRA;
366      size = 4;
367   }
368   else {
369      format = GL_RGBA;
370   }
371
372   switch (type) {
373      case GL_BYTE:
374         elementSize = size * sizeof(GLbyte);
375         break;
376      case GL_UNSIGNED_BYTE:
377         elementSize = size * sizeof(GLubyte);
378         break;
379      case GL_SHORT:
380         elementSize = size * sizeof(GLshort);
381         break;
382      case GL_UNSIGNED_SHORT:
383         elementSize = size * sizeof(GLushort);
384         break;
385      case GL_INT:
386         elementSize = size * sizeof(GLint);
387         break;
388      case GL_UNSIGNED_INT:
389         elementSize = size * sizeof(GLuint);
390         break;
391      case GL_FLOAT:
392         elementSize = size * sizeof(GLfloat);
393         break;
394      case GL_DOUBLE:
395         elementSize = size * sizeof(GLdouble);
396         break;
397      default:
398         _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
399                      _mesa_lookup_enum_by_nr(type));
400         return;
401   }
402
403   update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
404                elementSize, size, type, format, stride, GL_TRUE, ptr);
405}
406
407
408void GLAPIENTRY
409_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
410                      const GLvoid *ptr)
411{
412   GLint elementSize;
413   GET_CURRENT_CONTEXT(ctx);
414   const GLuint unit = ctx->Array.ActiveTexture;
415   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
416
417   if (size < 1 || size > 4) {
418      _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
419      return;
420   }
421   if (stride < 0) {
422      _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
423      return;
424   }
425
426   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
427      _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
428                  unit, size, _mesa_lookup_enum_by_nr( type ), stride);
429
430   /* always need to check that <type> is legal */
431   switch (type) {
432      case GL_SHORT:
433         elementSize = size * sizeof(GLshort);
434         break;
435      case GL_INT:
436         elementSize = size * sizeof(GLint);
437         break;
438      case GL_FLOAT:
439         elementSize = size * sizeof(GLfloat);
440         break;
441      case GL_DOUBLE:
442         elementSize = size * sizeof(GLdouble);
443         break;
444#if FEATURE_fixedpt
445      case GL_FIXED:
446         elementSize = size * sizeof(GLfixed);
447         break;
448#endif
449#if FEATURE_vertex_array_byte
450      case GL_BYTE:
451         elementSize = size * sizeof(GLbyte);
452         break;
453#endif
454      default:
455         _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
456                      _mesa_lookup_enum_by_nr(type));
457         return;
458   }
459
460   update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
461                _NEW_ARRAY_TEXCOORD(unit),
462                elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
463}
464
465
466void GLAPIENTRY
467_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
468{
469   GET_CURRENT_CONTEXT(ctx);
470   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
471
472   if (stride < 0) {
473      _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
474      return;
475   }
476
477   update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
478                sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
479                stride, GL_FALSE, ptr);
480}
481
482
483void GLAPIENTRY
484_mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
485{
486   GLsizei elementSize;
487   GET_CURRENT_CONTEXT(ctx);
488   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
489
490   if (stride < 0) {
491      _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
492      return;
493   }
494
495   switch (type) {
496      case GL_FLOAT:
497         elementSize = sizeof(GLfloat);
498         break;
499#if FEATURE_fixedpt
500      case GL_FIXED:
501         elementSize = sizeof(GLfixed);
502         break;
503#endif
504      default:
505         _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
506         return;
507   }
508
509   update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
510                elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
511}
512
513
514#if FEATURE_NV_vertex_program
515/**
516 * Set a vertex attribute array.
517 * Note that these arrays DO alias the conventional GL vertex arrays
518 * (position, normal, color, fog, texcoord, etc).
519 * The generic attribute slots at #16 and above are not touched.
520 */
521void GLAPIENTRY
522_mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
523                            GLsizei stride, const GLvoid *ptr)
524{
525   GLboolean normalized = GL_FALSE;
526   GLsizei elementSize;
527   GLenum format;
528   GET_CURRENT_CONTEXT(ctx);
529   ASSERT_OUTSIDE_BEGIN_END(ctx);
530
531   if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
532      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
533      return;
534   }
535
536   if (size < 1 || size > 4) {
537      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
538      return;
539   }
540
541   if (stride < 0) {
542      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
543      return;
544   }
545
546   if (type == GL_UNSIGNED_BYTE && size != 4) {
547      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
548      return;
549   }
550
551   if (size == GL_BGRA) {
552      if (type != GL_UNSIGNED_BYTE) {
553         _mesa_error(ctx, GL_INVALID_VALUE,
554                     "glVertexAttribPointerNV(GL_BGRA/type)");
555         return;
556      }
557
558      format = GL_BGRA;
559      size = 4;
560      normalized = GL_TRUE;
561   }
562   else {
563      format = GL_RGBA;
564   }
565
566   /* check for valid 'type' and compute StrideB right away */
567   switch (type) {
568      case GL_UNSIGNED_BYTE:
569         normalized = GL_TRUE;
570         elementSize = size * sizeof(GLubyte);
571         break;
572      case GL_SHORT:
573         elementSize = size * sizeof(GLshort);
574         break;
575      case GL_FLOAT:
576         elementSize = size * sizeof(GLfloat);
577         break;
578      case GL_DOUBLE:
579         elementSize = size * sizeof(GLdouble);
580         break;
581      default:
582         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
583                      _mesa_lookup_enum_by_nr(type));
584         return;
585   }
586
587   update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
588                _NEW_ARRAY_ATTRIB(index),
589                elementSize, size, type, format, stride, normalized, ptr);
590}
591#endif
592
593
594#if FEATURE_ARB_vertex_program
595/**
596 * Set a generic vertex attribute array.
597 * Note that these arrays DO NOT alias the conventional GL vertex arrays
598 * (position, normal, color, fog, texcoord, etc).
599 */
600void GLAPIENTRY
601_mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
602                             GLboolean normalized,
603                             GLsizei stride, const GLvoid *ptr)
604{
605   GLsizei elementSize;
606   GLenum format;
607   GET_CURRENT_CONTEXT(ctx);
608   ASSERT_OUTSIDE_BEGIN_END(ctx);
609
610   if (index >= ctx->Const.VertexProgram.MaxAttribs) {
611      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
612      return;
613   }
614
615   if (size < 1 || size > 4) {
616      if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
617         _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
618         return;
619      }
620   }
621
622   if (stride < 0) {
623      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
624      return;
625   }
626
627   if (size == GL_BGRA) {
628      if (type != GL_UNSIGNED_BYTE) {
629         _mesa_error(ctx, GL_INVALID_VALUE,
630                     "glVertexAttribPointerARB(GL_BGRA/type)");
631         return;
632      }
633      if (normalized != GL_TRUE) {
634         _mesa_error(ctx, GL_INVALID_VALUE,
635                     "glVertexAttribPointerARB(GL_BGRA/normalized)");
636         return;
637      }
638
639      format = GL_BGRA;
640      size = 4;
641   }
642   else {
643      format = GL_RGBA;
644   }
645
646   /* check for valid 'type' and compute StrideB right away */
647   /* NOTE: more types are supported here than in the NV extension */
648   switch (type) {
649      case GL_BYTE:
650         elementSize = size * sizeof(GLbyte);
651         break;
652      case GL_UNSIGNED_BYTE:
653         elementSize = size * sizeof(GLubyte);
654         break;
655      case GL_SHORT:
656         elementSize = size * sizeof(GLshort);
657         break;
658      case GL_UNSIGNED_SHORT:
659         elementSize = size * sizeof(GLushort);
660         break;
661      case GL_INT:
662         elementSize = size * sizeof(GLint);
663         break;
664      case GL_UNSIGNED_INT:
665         elementSize = size * sizeof(GLuint);
666         break;
667      case GL_FLOAT:
668         elementSize = size * sizeof(GLfloat);
669         break;
670      case GL_DOUBLE:
671         elementSize = size * sizeof(GLdouble);
672         break;
673#if FEATURE_fixedpt
674      case GL_FIXED:
675         elementSize = size * sizeof(GLfixed);
676         break;
677#endif
678      default:
679         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
680         return;
681   }
682
683   update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
684                _NEW_ARRAY_ATTRIB(index),
685                elementSize, size, type, format, stride, normalized, ptr);
686}
687#endif
688
689
690void GLAPIENTRY
691_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
692                       GLsizei count, const GLvoid *ptr)
693{
694   (void) count;
695   _mesa_VertexPointer(size, type, stride, ptr);
696}
697
698
699void GLAPIENTRY
700_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
701                       const GLvoid *ptr)
702{
703   (void) count;
704   _mesa_NormalPointer(type, stride, ptr);
705}
706
707
708void GLAPIENTRY
709_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
710                      const GLvoid *ptr)
711{
712   (void) count;
713   _mesa_ColorPointer(size, type, stride, ptr);
714}
715
716
717void GLAPIENTRY
718_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
719                      const GLvoid *ptr)
720{
721   (void) count;
722   _mesa_IndexPointer(type, stride, ptr);
723}
724
725
726void GLAPIENTRY
727_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
728                         GLsizei count, const GLvoid *ptr)
729{
730   (void) count;
731   _mesa_TexCoordPointer(size, type, stride, ptr);
732}
733
734
735void GLAPIENTRY
736_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
737{
738   (void) count;
739   _mesa_EdgeFlagPointer(stride, ptr);
740}
741
742
743void GLAPIENTRY
744_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
745{
746   GET_CURRENT_CONTEXT(ctx);
747   GLboolean tflag, cflag, nflag;  /* enable/disable flags */
748   GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
749   GLenum ctype = 0;               /* color type */
750   GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
751   const GLint toffset = 0;        /* always zero */
752   GLint defstride;                /* default stride */
753   GLint c, f;
754
755   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
756
757   f = sizeof(GLfloat);
758   c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
759
760   if (stride < 0) {
761      _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
762      return;
763   }
764
765   switch (format) {
766      case GL_V2F:
767         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
768         tcomps = 0;  ccomps = 0;  vcomps = 2;
769         voffset = 0;
770         defstride = 2*f;
771         break;
772      case GL_V3F:
773         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
774         tcomps = 0;  ccomps = 0;  vcomps = 3;
775         voffset = 0;
776         defstride = 3*f;
777         break;
778      case GL_C4UB_V2F:
779         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
780         tcomps = 0;  ccomps = 4;  vcomps = 2;
781         ctype = GL_UNSIGNED_BYTE;
782         coffset = 0;
783         voffset = c;
784         defstride = c + 2*f;
785         break;
786      case GL_C4UB_V3F:
787         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
788         tcomps = 0;  ccomps = 4;  vcomps = 3;
789         ctype = GL_UNSIGNED_BYTE;
790         coffset = 0;
791         voffset = c;
792         defstride = c + 3*f;
793         break;
794      case GL_C3F_V3F:
795         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
796         tcomps = 0;  ccomps = 3;  vcomps = 3;
797         ctype = GL_FLOAT;
798         coffset = 0;
799         voffset = 3*f;
800         defstride = 6*f;
801         break;
802      case GL_N3F_V3F:
803         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
804         tcomps = 0;  ccomps = 0;  vcomps = 3;
805         noffset = 0;
806         voffset = 3*f;
807         defstride = 6*f;
808         break;
809      case GL_C4F_N3F_V3F:
810         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
811         tcomps = 0;  ccomps = 4;  vcomps = 3;
812         ctype = GL_FLOAT;
813         coffset = 0;
814         noffset = 4*f;
815         voffset = 7*f;
816         defstride = 10*f;
817         break;
818      case GL_T2F_V3F:
819         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
820         tcomps = 2;  ccomps = 0;  vcomps = 3;
821         voffset = 2*f;
822         defstride = 5*f;
823         break;
824      case GL_T4F_V4F:
825         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
826         tcomps = 4;  ccomps = 0;  vcomps = 4;
827         voffset = 4*f;
828         defstride = 8*f;
829         break;
830      case GL_T2F_C4UB_V3F:
831         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
832         tcomps = 2;  ccomps = 4;  vcomps = 3;
833         ctype = GL_UNSIGNED_BYTE;
834         coffset = 2*f;
835         voffset = c+2*f;
836         defstride = c+5*f;
837         break;
838      case GL_T2F_C3F_V3F:
839         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
840         tcomps = 2;  ccomps = 3;  vcomps = 3;
841         ctype = GL_FLOAT;
842         coffset = 2*f;
843         voffset = 5*f;
844         defstride = 8*f;
845         break;
846      case GL_T2F_N3F_V3F:
847         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
848         tcomps = 2;  ccomps = 0;  vcomps = 3;
849         noffset = 2*f;
850         voffset = 5*f;
851         defstride = 8*f;
852         break;
853      case GL_T2F_C4F_N3F_V3F:
854         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
855         tcomps = 2;  ccomps = 4;  vcomps = 3;
856         ctype = GL_FLOAT;
857         coffset = 2*f;
858         noffset = 6*f;
859         voffset = 9*f;
860         defstride = 12*f;
861         break;
862      case GL_T4F_C4F_N3F_V4F:
863         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
864         tcomps = 4;  ccomps = 4;  vcomps = 4;
865         ctype = GL_FLOAT;
866         coffset = 4*f;
867         noffset = 8*f;
868         voffset = 11*f;
869         defstride = 15*f;
870         break;
871      default:
872         _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
873         return;
874   }
875
876   if (stride==0) {
877      stride = defstride;
878   }
879
880   _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
881   _mesa_DisableClientState( GL_INDEX_ARRAY );
882   /* XXX also disable secondary color and generic arrays? */
883
884   /* Texcoords */
885   if (tflag) {
886      _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
887      _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
888                             (GLubyte *) pointer + toffset );
889   }
890   else {
891      _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
892   }
893
894   /* Color */
895   if (cflag) {
896      _mesa_EnableClientState( GL_COLOR_ARRAY );
897      _mesa_ColorPointer( ccomps, ctype, stride,
898			  (GLubyte *) pointer + coffset );
899   }
900   else {
901      _mesa_DisableClientState( GL_COLOR_ARRAY );
902   }
903
904
905   /* Normals */
906   if (nflag) {
907      _mesa_EnableClientState( GL_NORMAL_ARRAY );
908      _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
909   }
910   else {
911      _mesa_DisableClientState( GL_NORMAL_ARRAY );
912   }
913
914   /* Vertices */
915   _mesa_EnableClientState( GL_VERTEX_ARRAY );
916   _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
917			(GLubyte *) pointer + voffset );
918}
919
920
921void GLAPIENTRY
922_mesa_LockArraysEXT(GLint first, GLsizei count)
923{
924   GET_CURRENT_CONTEXT(ctx);
925   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
926
927   if (MESA_VERBOSE & VERBOSE_API)
928      _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
929
930   if (first < 0) {
931      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
932      return;
933   }
934   if (count <= 0) {
935      _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
936      return;
937   }
938   if (ctx->Array.LockCount != 0) {
939      _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
940      return;
941   }
942
943   ctx->Array.LockFirst = first;
944   ctx->Array.LockCount = count;
945
946   ctx->NewState |= _NEW_ARRAY;
947   ctx->Array.NewState |= _NEW_ARRAY_ALL;
948}
949
950
951void GLAPIENTRY
952_mesa_UnlockArraysEXT( void )
953{
954   GET_CURRENT_CONTEXT(ctx);
955   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
956
957   if (MESA_VERBOSE & VERBOSE_API)
958      _mesa_debug(ctx, "glUnlockArrays\n");
959
960   if (ctx->Array.LockCount == 0) {
961      _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
962      return;
963   }
964
965   ctx->Array.LockFirst = 0;
966   ctx->Array.LockCount = 0;
967   ctx->NewState |= _NEW_ARRAY;
968   ctx->Array.NewState |= _NEW_ARRAY_ALL;
969}
970
971
972/* GL_EXT_multi_draw_arrays */
973/* Somebody forgot to spec the first and count parameters as const! <sigh> */
974void GLAPIENTRY
975_mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
976                          GLsizei *count, GLsizei primcount )
977{
978   GET_CURRENT_CONTEXT(ctx);
979   GLint i;
980
981   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
982
983   for (i = 0; i < primcount; i++) {
984      if (count[i] > 0) {
985         CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
986      }
987   }
988}
989
990
991/* GL_IBM_multimode_draw_arrays */
992void GLAPIENTRY
993_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
994			      const GLsizei * count,
995			      GLsizei primcount, GLint modestride )
996{
997   GET_CURRENT_CONTEXT(ctx);
998   GLint i;
999
1000   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1001
1002   for ( i = 0 ; i < primcount ; i++ ) {
1003      if ( count[i] > 0 ) {
1004         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1005	 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1006      }
1007   }
1008}
1009
1010
1011/* GL_IBM_multimode_draw_arrays */
1012void GLAPIENTRY
1013_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1014				GLenum type, const GLvoid * const * indices,
1015				GLsizei primcount, GLint modestride )
1016{
1017   GET_CURRENT_CONTEXT(ctx);
1018   GLint i;
1019
1020   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1021
1022   /* XXX not sure about ARB_vertex_buffer_object handling here */
1023
1024   for ( i = 0 ; i < primcount ; i++ ) {
1025      if ( count[i] > 0 ) {
1026         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1027	 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1028      }
1029   }
1030}
1031
1032
1033/**
1034 * Copy one client vertex array to another.
1035 */
1036void
1037_mesa_copy_client_array(GLcontext *ctx,
1038                        struct gl_client_array *dst,
1039                        struct gl_client_array *src)
1040{
1041   dst->Size = src->Size;
1042   dst->Type = src->Type;
1043   dst->Format = src->Format;
1044   dst->Stride = src->Stride;
1045   dst->StrideB = src->StrideB;
1046   dst->Ptr = src->Ptr;
1047   dst->Enabled = src->Enabled;
1048   dst->Normalized = src->Normalized;
1049   dst->_ElementSize = src->_ElementSize;
1050   _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1051   dst->_MaxElement = src->_MaxElement;
1052}
1053
1054
1055
1056/**
1057 * Print vertex array's fields.
1058 */
1059static void
1060print_array(const char *name, GLint index, const struct gl_client_array *array)
1061{
1062   if (index >= 0)
1063      _mesa_printf("  %s[%d]: ", name, index);
1064   else
1065      _mesa_printf("  %s: ", name);
1066   _mesa_printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %u), MaxElem=%u\n",
1067                array->Ptr, array->Type, array->Size,
1068                array->_ElementSize, array->StrideB,
1069                array->BufferObj->Name, array->BufferObj->Size,
1070                array->_MaxElement);
1071}
1072
1073
1074/**
1075 * Print current vertex object/array info.  For debug.
1076 */
1077void
1078_mesa_print_arrays(GLcontext *ctx)
1079{
1080   struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1081   GLuint i;
1082
1083   _mesa_update_array_object_max_element(ctx, arrayObj);
1084
1085   _mesa_printf("Array Object %u\n", arrayObj->Name);
1086   if (arrayObj->Vertex.Enabled)
1087      print_array("Vertex", -1, &arrayObj->Vertex);
1088   if (arrayObj->Normal.Enabled)
1089      print_array("Normal", -1, &arrayObj->Normal);
1090   if (arrayObj->Color.Enabled)
1091      print_array("Color", -1, &arrayObj->Color);
1092   for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1093      if (arrayObj->TexCoord[i].Enabled)
1094         print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1095   for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1096      if (arrayObj->VertexAttrib[i].Enabled)
1097         print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1098   _mesa_printf("  _MaxElement = %u\n", arrayObj->_MaxElement);
1099}
1100
1101
1102/**
1103 * Initialize vertex array state for given context.
1104 */
1105void
1106_mesa_init_varray(GLcontext *ctx)
1107{
1108   ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1109   _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1110                                ctx->Array.DefaultArrayObj);
1111   ctx->Array.ActiveTexture = 0;   /* GL_ARB_multitexture */
1112
1113   ctx->Array.Objects = _mesa_NewHashTable();
1114}
1115
1116
1117/**
1118 * Callback for deleting an array object.  Called by _mesa_HashDeleteAll().
1119 */
1120static void
1121delete_arrayobj_cb(GLuint id, void *data, void *userData)
1122{
1123   struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1124   GLcontext *ctx = (GLcontext *) userData;
1125   _mesa_delete_array_object(ctx, arrayObj);
1126}
1127
1128
1129/**
1130 * Free vertex array state for given context.
1131 */
1132void
1133_mesa_free_varray_data(GLcontext *ctx)
1134{
1135   _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1136   _mesa_DeleteHashTable(ctx->Array.Objects);
1137}
1138