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