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