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