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