varray.c revision 3c63452e64df7e10aa073c6c3b9492b1d7dabbb8
1/* $Id: varray.c,v 1.47 2002/10/24 23:57:21 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  4.1
6 *
7 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27#include "glheader.h"
28#include "context.h"
29#include "enable.h"
30#include "enums.h"
31#include "dlist.h"
32#include "light.h"
33#include "macros.h"
34#include "mmath.h"
35#include "state.h"
36#include "texstate.h"
37#include "mtypes.h"
38#include "varray.h"
39#include "math/m_translate.h"
40
41
42
43void
44_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
45{
46   GET_CURRENT_CONTEXT(ctx);
47   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
48
49   if (size < 2 || size > 4) {
50      _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
51      return;
52   }
53   if (stride < 0) {
54      _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
55      return;
56   }
57
58   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
59      _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size,
60                  _mesa_lookup_enum_by_nr( type ), stride);
61
62   /* always need to check that <type> is legal */
63   switch (type) {
64      case GL_SHORT:
65         ctx->Array.Vertex.StrideB = size * sizeof(GLshort);
66         break;
67      case GL_INT:
68         ctx->Array.Vertex.StrideB = size * sizeof(GLint);
69         break;
70      case GL_FLOAT:
71         ctx->Array.Vertex.StrideB = size * sizeof(GLfloat);
72         break;
73      case GL_DOUBLE:
74         ctx->Array.Vertex.StrideB = size * sizeof(GLdouble);
75         break;
76      default:
77         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
78         return;
79   }
80
81   if (stride)
82      ctx->Array.Vertex.StrideB = stride;
83
84   ctx->Array.Vertex.Size = size;
85   ctx->Array.Vertex.Type = type;
86   ctx->Array.Vertex.Stride = stride;
87   ctx->Array.Vertex.Ptr = (void *) ptr;
88   ctx->NewState |= _NEW_ARRAY;
89   ctx->Array.NewState |= _NEW_ARRAY_VERTEX;
90
91   if (ctx->Driver.VertexPointer)
92      ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
93}
94
95
96
97
98void
99_mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
100{
101   GET_CURRENT_CONTEXT(ctx);
102   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
103
104   if (stride < 0) {
105      _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
106      return;
107   }
108
109   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
110      _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
111                  _mesa_lookup_enum_by_nr( type ), stride);
112
113   switch (type) {
114      case GL_BYTE:
115         ctx->Array.Normal.StrideB = 3 * sizeof(GLbyte);
116         break;
117      case GL_SHORT:
118         ctx->Array.Normal.StrideB = 3 * sizeof(GLshort);
119         break;
120      case GL_INT:
121         ctx->Array.Normal.StrideB = 3 * sizeof(GLint);
122         break;
123      case GL_FLOAT:
124         ctx->Array.Normal.StrideB = 3 * sizeof(GLfloat);
125         break;
126      case GL_DOUBLE:
127         ctx->Array.Normal.StrideB = 3 * sizeof(GLdouble);
128         break;
129      default:
130         _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
131         return;
132   }
133   if (stride)
134      ctx->Array.Normal.StrideB = stride;
135
136   ctx->Array.Normal.Size = 3;
137   ctx->Array.Normal.Type = type;
138   ctx->Array.Normal.Stride = stride;
139   ctx->Array.Normal.Ptr = (void *) ptr;
140   ctx->NewState |= _NEW_ARRAY;
141   ctx->Array.NewState |= _NEW_ARRAY_NORMAL;
142
143   if (ctx->Driver.NormalPointer)
144      ctx->Driver.NormalPointer( ctx, type, stride, ptr );
145}
146
147
148
149void
150_mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
151{
152   GET_CURRENT_CONTEXT(ctx);
153   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
154
155   if (size < 3 || size > 4) {
156      _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
157      return;
158   }
159   if (stride<0) {
160      _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
161      return;
162   }
163
164   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
165      _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
166                  _mesa_lookup_enum_by_nr( type ), stride);
167
168   switch (type) {
169      case GL_BYTE:
170         ctx->Array.Color.StrideB = size * sizeof(GLbyte);
171         break;
172      case GL_UNSIGNED_BYTE:
173         ctx->Array.Color.StrideB = size * sizeof(GLubyte);
174         break;
175      case GL_SHORT:
176         ctx->Array.Color.StrideB = size * sizeof(GLshort);
177         break;
178      case GL_UNSIGNED_SHORT:
179         ctx->Array.Color.StrideB = size * sizeof(GLushort);
180         break;
181      case GL_INT:
182         ctx->Array.Color.StrideB = size * sizeof(GLint);
183         break;
184      case GL_UNSIGNED_INT:
185         ctx->Array.Color.StrideB = size * sizeof(GLuint);
186         break;
187      case GL_FLOAT:
188         ctx->Array.Color.StrideB = size * sizeof(GLfloat);
189         break;
190      case GL_DOUBLE:
191         ctx->Array.Color.StrideB = size * sizeof(GLdouble);
192         break;
193      default:
194         _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
195         return;
196   }
197
198   if (stride)
199      ctx->Array.Color.StrideB = stride;
200
201   ctx->Array.Color.Size = size;
202   ctx->Array.Color.Type = type;
203   ctx->Array.Color.Stride = stride;
204   ctx->Array.Color.Ptr = (void *) ptr;
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
213
214void
215_mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
216{
217   GET_CURRENT_CONTEXT(ctx);
218   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
219
220   if (stride < 0) {
221      _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
222      return;
223   }
224
225   switch (type) {
226      case GL_FLOAT:
227         ctx->Array.FogCoord.StrideB =  sizeof(GLfloat);
228         break;
229      case GL_DOUBLE:
230         ctx->Array.FogCoord.StrideB =  sizeof(GLdouble);
231         break;
232      default:
233         _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
234         return;
235   }
236
237   if (stride)
238      ctx->Array.FogCoord.StrideB = stride;
239
240   ctx->Array.FogCoord.Size = 1;
241   ctx->Array.FogCoord.Type = type;
242   ctx->Array.FogCoord.Stride = stride;
243   ctx->Array.FogCoord.Ptr = (void *) ptr;
244   ctx->NewState |= _NEW_ARRAY;
245   ctx->Array.NewState |= _NEW_ARRAY_FOGCOORD;
246
247   if (ctx->Driver.FogCoordPointer)
248      ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
249}
250
251
252void
253_mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
254{
255   GET_CURRENT_CONTEXT(ctx);
256   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
257
258   if (stride < 0) {
259      _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
260      return;
261   }
262
263   switch (type) {
264      case GL_UNSIGNED_BYTE:
265         ctx->Array.Index.StrideB =  sizeof(GLubyte);
266         break;
267      case GL_SHORT:
268         ctx->Array.Index.StrideB =  sizeof(GLshort);
269         break;
270      case GL_INT:
271         ctx->Array.Index.StrideB =  sizeof(GLint);
272         break;
273      case GL_FLOAT:
274         ctx->Array.Index.StrideB =  sizeof(GLfloat);
275         break;
276      case GL_DOUBLE:
277         ctx->Array.Index.StrideB =  sizeof(GLdouble);
278         break;
279      default:
280         _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
281         return;
282   }
283
284   if (stride)
285      ctx->Array.Index.StrideB = stride;
286
287   ctx->Array.Index.Size = 1;
288   ctx->Array.Index.Type = type;
289   ctx->Array.Index.Stride = stride;
290   ctx->Array.Index.Ptr = (void *) ptr;
291   ctx->NewState |= _NEW_ARRAY;
292   ctx->Array.NewState |= _NEW_ARRAY_INDEX;
293
294   if (ctx->Driver.IndexPointer)
295      ctx->Driver.IndexPointer( ctx, type, stride, ptr );
296}
297
298
299void
300_mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
301			       GLsizei stride, const GLvoid *ptr)
302{
303   GET_CURRENT_CONTEXT(ctx);
304   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
305
306   if (size != 3 && size != 4) {
307      _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)" );
308      return;
309   }
310   if (stride < 0) {
311      _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
312      return;
313   }
314
315   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
316      _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
317                  size, _mesa_lookup_enum_by_nr( type ), stride);
318
319   switch (type) {
320      case GL_BYTE:
321         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLbyte);
322         break;
323      case GL_UNSIGNED_BYTE:
324         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLubyte);
325         break;
326      case GL_SHORT:
327         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLshort);
328         break;
329      case GL_UNSIGNED_SHORT:
330         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLushort);
331         break;
332      case GL_INT:
333         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLint);
334         break;
335      case GL_UNSIGNED_INT:
336         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLuint);
337         break;
338      case GL_FLOAT:
339         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLfloat);
340         break;
341      case GL_DOUBLE:
342         ctx->Array.SecondaryColor.StrideB = size * sizeof(GLdouble);
343         break;
344      default:
345         _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" );
346         return;
347   }
348
349   if (stride)
350      ctx->Array.SecondaryColor.StrideB = stride;
351
352   ctx->Array.SecondaryColor.Size = 3; /* hardwire */
353   ctx->Array.SecondaryColor.Type = type;
354   ctx->Array.SecondaryColor.Stride = stride;
355   ctx->Array.SecondaryColor.Ptr = (void *) ptr;
356   ctx->NewState |= _NEW_ARRAY;
357   ctx->Array.NewState |= _NEW_ARRAY_COLOR1;
358
359   if (ctx->Driver.SecondaryColorPointer)
360      ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
361}
362
363
364
365void
366_mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
367                      const GLvoid *ptr)
368{
369   GET_CURRENT_CONTEXT(ctx);
370   GLuint texUnit = ctx->Array.ActiveTexture;
371   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
372
373   if (size < 1 || size > 4) {
374      _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
375      return;
376   }
377   if (stride < 0) {
378      _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
379      return;
380   }
381
382   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
383      _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
384                  texUnit, size, _mesa_lookup_enum_by_nr( type ), stride);
385
386   /* always need to check that <type> is legal */
387   switch (type) {
388      case GL_SHORT:
389         ctx->Array.TexCoord[texUnit].StrideB = size * sizeof(GLshort);
390         break;
391      case GL_INT:
392         ctx->Array.TexCoord[texUnit].StrideB = size * sizeof(GLint);
393         break;
394      case GL_FLOAT:
395         ctx->Array.TexCoord[texUnit].StrideB = size * sizeof(GLfloat);
396         break;
397      case GL_DOUBLE:
398         ctx->Array.TexCoord[texUnit].StrideB = size * sizeof(GLdouble);
399         break;
400      default:
401         _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
402         return;
403   }
404
405   if (stride)
406      ctx->Array.TexCoord[texUnit].StrideB = stride;
407
408   ctx->Array.TexCoord[texUnit].Size = size;
409   ctx->Array.TexCoord[texUnit].Type = type;
410   ctx->Array.TexCoord[texUnit].Stride = stride;
411   ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr;
412   ctx->NewState |= _NEW_ARRAY;
413   ctx->Array.NewState |= _NEW_ARRAY_TEXCOORD(texUnit);
414
415   if (ctx->Driver.TexCoordPointer)
416      ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
417}
418
419
420void
421_mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *vptr)
422{
423   GET_CURRENT_CONTEXT(ctx);
424   const GLboolean *ptr = (GLboolean *)vptr;
425   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
426
427   if (stride<0) {
428      _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
429      return;
430   }
431   ctx->Array.EdgeFlag.Stride = stride;
432   ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean);
433   ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr;
434   ctx->NewState |= _NEW_ARRAY;
435   ctx->Array.NewState |= _NEW_ARRAY_EDGEFLAG;
436
437   if (ctx->Driver.EdgeFlagPointer)
438      ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
439}
440
441
442void _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
443                                 GLsizei stride, const GLvoid *ptr)
444{
445   GET_CURRENT_CONTEXT(ctx);
446   ASSERT_OUTSIDE_BEGIN_END(ctx);
447
448   if (index >= VERT_ATTRIB_MAX) {
449      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
450      return;
451   }
452
453   if (size < 1 || size > 4) {
454      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
455      return;
456   }
457
458   if (stride < 0) {
459      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
460      return;
461   }
462
463   if (type == GL_UNSIGNED_BYTE && size != 4) {
464      _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
465      return;
466   }
467
468   /* check for valid 'type' and compute StrideB right away */
469   switch (type) {
470      case GL_UNSIGNED_BYTE:
471         ctx->Array.VertexAttrib[index].StrideB = size * sizeof(GLubyte);
472         break;
473      case GL_SHORT:
474         ctx->Array.VertexAttrib[index].StrideB = size * sizeof(GLshort);
475         break;
476      case GL_FLOAT:
477         ctx->Array.VertexAttrib[index].StrideB = size * sizeof(GLfloat);
478         break;
479      case GL_DOUBLE:
480         ctx->Array.VertexAttrib[index].StrideB = size * sizeof(GLdouble);
481         break;
482      default:
483         _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" );
484         return;
485   }
486
487   if (stride)
488      ctx->Array.VertexAttrib[index].StrideB = stride;
489
490   ctx->Array.VertexAttrib[index].Stride = stride;
491   ctx->Array.VertexAttrib[index].Size = size;
492   ctx->Array.VertexAttrib[index].Type = type;
493   ctx->Array.VertexAttrib[index].Ptr = (void *) ptr;
494
495   ctx->NewState |= _NEW_ARRAY;
496   ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
497
498   if (ctx->Driver.VertexAttribPointer)
499      ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
500}
501
502
503void
504_mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
505                       GLsizei count, const GLvoid *ptr)
506{
507   (void) count;
508   _mesa_VertexPointer(size, type, stride, ptr);
509}
510
511
512void
513_mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
514                       const GLvoid *ptr)
515{
516   (void) count;
517   _mesa_NormalPointer(type, stride, ptr);
518}
519
520
521void
522_mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
523                      const GLvoid *ptr)
524{
525   (void) count;
526   _mesa_ColorPointer(size, type, stride, ptr);
527}
528
529
530void
531_mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
532                      const GLvoid *ptr)
533{
534   (void) count;
535   _mesa_IndexPointer(type, stride, ptr);
536}
537
538
539void
540_mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
541                         GLsizei count, const GLvoid *ptr)
542{
543   (void) count;
544   _mesa_TexCoordPointer(size, type, stride, ptr);
545}
546
547
548void
549_mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
550{
551   (void) count;
552   _mesa_EdgeFlagPointer(stride, ptr);
553}
554
555
556
557
558void
559_mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
560{
561   GET_CURRENT_CONTEXT(ctx);
562   GLboolean tflag, cflag, nflag;  /* enable/disable flags */
563   GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
564
565   GLenum ctype = 0;               /* color type */
566   GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
567   GLint defstride;                /* default stride */
568   GLint c, f;
569   GLint coordUnitSave;
570
571   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
572
573   f = sizeof(GLfloat);
574   c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
575
576   if (stride<0) {
577      _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
578      return;
579   }
580
581   switch (format) {
582      case GL_V2F:
583         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
584         tcomps = 0;  ccomps = 0;  vcomps = 2;
585         voffset = 0;
586         defstride = 2*f;
587         break;
588      case GL_V3F:
589         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
590         tcomps = 0;  ccomps = 0;  vcomps = 3;
591         voffset = 0;
592         defstride = 3*f;
593         break;
594      case GL_C4UB_V2F:
595         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
596         tcomps = 0;  ccomps = 4;  vcomps = 2;
597         ctype = GL_UNSIGNED_BYTE;
598         coffset = 0;
599         voffset = c;
600         defstride = c + 2*f;
601         break;
602      case GL_C4UB_V3F:
603         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
604         tcomps = 0;  ccomps = 4;  vcomps = 3;
605         ctype = GL_UNSIGNED_BYTE;
606         coffset = 0;
607         voffset = c;
608         defstride = c + 3*f;
609         break;
610      case GL_C3F_V3F:
611         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
612         tcomps = 0;  ccomps = 3;  vcomps = 3;
613         ctype = GL_FLOAT;
614         coffset = 0;
615         voffset = 3*f;
616         defstride = 6*f;
617         break;
618      case GL_N3F_V3F:
619         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
620         tcomps = 0;  ccomps = 0;  vcomps = 3;
621         noffset = 0;
622         voffset = 3*f;
623         defstride = 6*f;
624         break;
625      case GL_C4F_N3F_V3F:
626         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
627         tcomps = 0;  ccomps = 4;  vcomps = 3;
628         ctype = GL_FLOAT;
629         coffset = 0;
630         noffset = 4*f;
631         voffset = 7*f;
632         defstride = 10*f;
633         break;
634      case GL_T2F_V3F:
635         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
636         tcomps = 2;  ccomps = 0;  vcomps = 3;
637         voffset = 2*f;
638         defstride = 5*f;
639         break;
640      case GL_T4F_V4F:
641         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
642         tcomps = 4;  ccomps = 0;  vcomps = 4;
643         voffset = 4*f;
644         defstride = 8*f;
645         break;
646      case GL_T2F_C4UB_V3F:
647         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
648         tcomps = 2;  ccomps = 4;  vcomps = 3;
649         ctype = GL_UNSIGNED_BYTE;
650         coffset = 2*f;
651         voffset = c+2*f;
652         defstride = c+5*f;
653         break;
654      case GL_T2F_C3F_V3F:
655         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
656         tcomps = 2;  ccomps = 3;  vcomps = 3;
657         ctype = GL_FLOAT;
658         coffset = 2*f;
659         voffset = 5*f;
660         defstride = 8*f;
661         break;
662      case GL_T2F_N3F_V3F:
663         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
664         tcomps = 2;  ccomps = 0;  vcomps = 3;
665         noffset = 2*f;
666         voffset = 5*f;
667         defstride = 8*f;
668         break;
669      case GL_T2F_C4F_N3F_V3F:
670         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
671         tcomps = 2;  ccomps = 4;  vcomps = 3;
672         ctype = GL_FLOAT;
673         coffset = 2*f;
674         noffset = 6*f;
675         voffset = 9*f;
676         defstride = 12*f;
677         break;
678      case GL_T4F_C4F_N3F_V4F:
679         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
680         tcomps = 4;  ccomps = 4;  vcomps = 4;
681         ctype = GL_FLOAT;
682         coffset = 4*f;
683         noffset = 8*f;
684         voffset = 11*f;
685         defstride = 15*f;
686         break;
687      default:
688         _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
689         return;
690   }
691
692   if (stride==0) {
693      stride = defstride;
694   }
695
696   _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
697   _mesa_DisableClientState( GL_INDEX_ARRAY );
698
699   /* Texcoords */
700   coordUnitSave = ctx->Array.ActiveTexture;
701   if (tflag) {
702      GLint i;
703      GLint factor = ctx->Array.TexCoordInterleaveFactor;
704      for (i = 0; i < factor; i++) {
705         _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
706         _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
707         _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
708				(GLubyte *) pointer + i * coffset );
709      }
710      for (i = factor; i < (GLint) ctx->Const.MaxTextureUnits; i++) {
711         _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
712         _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
713      }
714   }
715   else {
716      GLint i;
717      for (i = 0; i < (GLint) ctx->Const.MaxTextureUnits; i++) {
718         _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + i) );
719         _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
720      }
721   }
722   /* Restore texture coordinate unit index */
723   _mesa_ClientActiveTextureARB( (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
724
725
726   /* Color */
727   if (cflag) {
728      _mesa_EnableClientState( GL_COLOR_ARRAY );
729      _mesa_ColorPointer( ccomps, ctype, stride,
730			  (GLubyte*) pointer + coffset );
731   }
732   else {
733      _mesa_DisableClientState( GL_COLOR_ARRAY );
734   }
735
736
737   /* Normals */
738   if (nflag) {
739      _mesa_EnableClientState( GL_NORMAL_ARRAY );
740      _mesa_NormalPointer( GL_FLOAT, stride,
741			   (GLubyte*) pointer + noffset );
742   }
743   else {
744      _mesa_DisableClientState( GL_NORMAL_ARRAY );
745   }
746
747   _mesa_EnableClientState( GL_VERTEX_ARRAY );
748   _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
749			(GLubyte *) pointer + voffset );
750}
751
752
753
754void
755_mesa_LockArraysEXT(GLint first, GLsizei count)
756{
757   GET_CURRENT_CONTEXT(ctx);
758   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
759
760   if (MESA_VERBOSE & VERBOSE_API)
761      _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
762
763   if (first == 0 && count > 0 &&
764       count <= (GLint) ctx->Const.MaxArrayLockSize) {
765      ctx->Array.LockFirst = first;
766      ctx->Array.LockCount = count;
767   }
768   else {
769      ctx->Array.LockFirst = 0;
770      ctx->Array.LockCount = 0;
771   }
772
773   ctx->NewState |= _NEW_ARRAY;
774   ctx->Array.NewState |= _NEW_ARRAY_ALL;
775
776   if (ctx->Driver.LockArraysEXT)
777      ctx->Driver.LockArraysEXT( ctx, first, count );
778}
779
780
781void
782_mesa_UnlockArraysEXT( void )
783{
784   GET_CURRENT_CONTEXT(ctx);
785   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
786
787   if (MESA_VERBOSE & VERBOSE_API)
788      _mesa_debug(ctx, "glUnlockArrays\n");
789
790   ctx->Array.LockFirst = 0;
791   ctx->Array.LockCount = 0;
792   ctx->NewState |= _NEW_ARRAY;
793   ctx->Array.NewState |= _NEW_ARRAY_ALL;
794
795   if (ctx->Driver.UnlockArraysEXT)
796      ctx->Driver.UnlockArraysEXT( ctx );
797}
798
799
800
801/* GL_EXT_multi_draw_arrays */
802/* Somebody forgot to spec the first and count parameters as const! <sigh> */
803void
804_mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
805                          GLsizei *count, GLsizei primcount )
806{
807   GET_CURRENT_CONTEXT(ctx);
808   GLint i;
809
810   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
811
812   for (i = 0; i < primcount; i++) {
813      if (count[i] > 0) {
814         (ctx->Exec->DrawArrays)(mode, first[i], count[i]);
815      }
816   }
817}
818
819
820/* GL_EXT_multi_draw_arrays */
821void
822_mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
823                            const GLvoid **indices, GLsizei primcount )
824{
825   GET_CURRENT_CONTEXT(ctx);
826   GLint i;
827
828   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
829
830   for (i = 0; i < primcount; i++) {
831      if (count[i] > 0) {
832         (ctx->Exec->DrawElements)(mode, count[i], type, indices[i]);
833      }
834   }
835}
836