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