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