varray.c revision 6a9f16edae2a21b156d1893947cc2ec35593d0a8
1/* $Id: varray.c,v 1.12 1999/11/09 17:00:25 keithw Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.1
6 *
7 * Copyright (C) 1999  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27#ifdef PC_HEADER
28#include "all.h"
29#else
30#ifndef XFree86Server
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#else
35#include "GL/xf86glx.h"
36#endif
37#include "context.h"
38#include "api.h"
39#include "cva.h"
40#include "enable.h"
41#include "enums.h"
42#include "dlist.h"
43#include "light.h"
44#include "macros.h"
45#include "mmath.h"
46#include "pipeline.h"
47#include "texstate.h"
48#include "translate.h"
49#include "types.h"
50#include "varray.h"
51#include "vb.h"
52#include "vbfill.h"
53#include "vbrender.h"
54#include "vbindirect.h"
55#include "vbxform.h"
56#include "xform.h"
57#ifdef XFree86Server
58#include "GL/xf86glx.h"
59#endif
60#endif
61
62#if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) && !defined(GLX_USE_DLOPEN)
63#define NEED_MESA_FUNCS_WRAPPED
64#include "mesa_api.h"
65#endif
66
67
68void GLAPIENTRY glVertexPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
69                                 const GLvoid *ptr )
70{
71   GLcontext *ctx;
72   GET_CONTEXT;
73   CHECK_CONTEXT;
74   ctx = CC;
75
76   if (size<2 || size>4) {
77      gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
78      return;
79   }
80   if (stride<0) {
81      gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
82      return;
83   }
84
85   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
86      fprintf(stderr, "glVertexPointer( sz %d type %s stride %d )\n", size,
87	      gl_lookup_enum_by_nr( type ),
88	      stride);
89
90   ctx->Array.Vertex.StrideB = stride;
91   if (!stride) {
92      switch (type) {
93      case GL_SHORT:
94         ctx->Array.Vertex.StrideB =  size*sizeof(GLshort);
95         break;
96      case GL_INT:
97         ctx->Array.Vertex.StrideB =  size*sizeof(GLint);
98         break;
99      case GL_FLOAT:
100         ctx->Array.Vertex.StrideB =  size*sizeof(GLfloat);
101         break;
102      case GL_DOUBLE:
103         ctx->Array.Vertex.StrideB =  size*sizeof(GLdouble);
104         break;
105      default:
106         gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
107         return;
108      }
109   }
110   ctx->Array.Vertex.Size = size;
111   ctx->Array.Vertex.Type = type;
112   ctx->Array.Vertex.Stride = stride;
113   ctx->Array.Vertex.Ptr = (void *) ptr;
114   ctx->Array.VertexFunc = gl_trans_4f_tab[size][TYPE_IDX(type)];
115   ctx->Array.VertexEltFunc = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
116   ctx->Array.NewArrayState |= VERT_OBJ_ANY;
117   ctx->NewState |= NEW_CLIENT_STATE;
118}
119
120
121
122
123void GLAPIENTRY glNormalPointer(CTX_ARG GLenum type, GLsizei stride,
124                                 const GLvoid *ptr )
125{
126   GLcontext *ctx;
127   GET_CONTEXT;
128   CHECK_CONTEXT;
129   ctx = CC;
130
131   if (stride<0) {
132      gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
133      return;
134   }
135
136   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
137      fprintf(stderr, "glNormalPointer( type %s stride %d )\n",
138	      gl_lookup_enum_by_nr( type ),
139	      stride);
140
141   ctx->Array.Normal.StrideB = stride;
142   if (!stride) {
143      switch (type) {
144      case GL_BYTE:
145         ctx->Array.Normal.StrideB =  3*sizeof(GLbyte);
146         break;
147      case GL_SHORT:
148         ctx->Array.Normal.StrideB =  3*sizeof(GLshort);
149         break;
150      case GL_INT:
151         ctx->Array.Normal.StrideB =  3*sizeof(GLint);
152         break;
153      case GL_FLOAT:
154         ctx->Array.Normal.StrideB =  3*sizeof(GLfloat);
155         break;
156      case GL_DOUBLE:
157         ctx->Array.Normal.StrideB =  3*sizeof(GLdouble);
158         break;
159      default:
160         gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
161         return;
162      }
163   }
164   ctx->Array.Normal.Type = type;
165   ctx->Array.Normal.Stride = stride;
166   ctx->Array.Normal.Ptr = (void *) ptr;
167   ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(type)];
168   ctx->Array.NormalEltFunc = gl_trans_elt_3f_tab[TYPE_IDX(type)];
169   ctx->Array.NewArrayState |= VERT_NORM;
170   ctx->NewState |= NEW_CLIENT_STATE;
171}
172
173
174
175void GLAPIENTRY glColorPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
176                                const GLvoid *ptr )
177{
178   GLcontext *ctx;
179   GET_CONTEXT;
180   CHECK_CONTEXT;
181   ctx = CC;
182   if (size<3 || size>4) {
183      gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
184      return;
185   }
186   if (stride<0) {
187      gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
188      return;
189   }
190
191   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
192      fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size,
193	  gl_lookup_enum_by_nr( type ),
194	  stride);
195
196   ctx->Array.Color.StrideB = stride;
197   if (!stride) {
198      switch (type) {
199      case GL_BYTE:
200         ctx->Array.Color.StrideB =  size*sizeof(GLbyte);
201         break;
202      case GL_UNSIGNED_BYTE:
203         ctx->Array.Color.StrideB =  size*sizeof(GLubyte);
204         break;
205      case GL_SHORT:
206         ctx->Array.Color.StrideB =  size*sizeof(GLshort);
207         break;
208      case GL_UNSIGNED_SHORT:
209         ctx->Array.Color.StrideB =  size*sizeof(GLushort);
210         break;
211      case GL_INT:
212         ctx->Array.Color.StrideB =  size*sizeof(GLint);
213         break;
214      case GL_UNSIGNED_INT:
215         ctx->Array.Color.StrideB =  size*sizeof(GLuint);
216         break;
217      case GL_FLOAT:
218         ctx->Array.Color.StrideB =  size*sizeof(GLfloat);
219         break;
220      case GL_DOUBLE:
221         ctx->Array.Color.StrideB =  size*sizeof(GLdouble);
222         break;
223      default:
224         gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
225         return;
226      }
227   }
228   ctx->Array.Color.Size = size;
229   ctx->Array.Color.Type = type;
230   ctx->Array.Color.Stride = stride;
231   ctx->Array.Color.Ptr = (void *) ptr;
232   ctx->Array.ColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)];
233   ctx->Array.ColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)];
234   ctx->Array.NewArrayState |= VERT_RGBA;
235   ctx->NewState |= NEW_CLIENT_STATE;
236}
237
238
239
240void GLAPIENTRY glIndexPointer(CTX_ARG GLenum type, GLsizei stride,
241                                const GLvoid *ptr )
242{
243   GLcontext *ctx;
244   GET_CONTEXT;
245   CHECK_CONTEXT;
246   ctx = CC;
247
248   if (stride<0) {
249      gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
250      return;
251   }
252
253   ctx->Array.Index.StrideB = stride;
254   if (!stride) {
255      switch (type) {
256      case GL_UNSIGNED_BYTE:
257         ctx->Array.Index.StrideB =  sizeof(GLubyte);
258         break;
259      case GL_SHORT:
260         ctx->Array.Index.StrideB =  sizeof(GLshort);
261         break;
262      case GL_INT:
263         ctx->Array.Index.StrideB =  sizeof(GLint);
264         break;
265      case GL_FLOAT:
266         ctx->Array.Index.StrideB =  sizeof(GLfloat);
267         break;
268      case GL_DOUBLE:
269         ctx->Array.Index.StrideB =  sizeof(GLdouble);
270         break;
271      default:
272         gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
273         return;
274      }
275   }
276   ctx->Array.Index.Type = type;
277   ctx->Array.Index.Stride = stride;
278   ctx->Array.Index.Ptr = (void *) ptr;
279   ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
280   ctx->Array.IndexEltFunc = gl_trans_elt_1ui_tab[TYPE_IDX(type)];
281   ctx->Array.NewArrayState |= VERT_INDEX;
282   ctx->NewState |= NEW_CLIENT_STATE;
283}
284
285
286
287void GLAPIENTRY glTexCoordPointer(CTX_ARG GLint size, GLenum type,
288                                   GLsizei stride, const GLvoid *ptr )
289{
290   GLuint texUnit;
291
292   GLcontext *ctx;
293   GET_CONTEXT;
294   CHECK_CONTEXT;
295   ctx = CC;
296
297   texUnit = ctx->Array.ActiveTexture;
298
299   if (size<1 || size>4) {
300      gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
301      return;
302   }
303   if (stride<0) {
304      gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
305      return;
306   }
307
308   if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
309      fprintf(stderr, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
310	  texUnit,
311	  size,
312	  gl_lookup_enum_by_nr( type ),
313	  stride);
314
315   ctx->Array.TexCoord[texUnit].StrideB = stride;
316   if (!stride) {
317      switch (type) {
318      case GL_SHORT:
319         ctx->Array.TexCoord[texUnit].StrideB =  size*sizeof(GLshort);
320         break;
321      case GL_INT:
322         ctx->Array.TexCoord[texUnit].StrideB =  size*sizeof(GLint);
323         break;
324      case GL_FLOAT:
325         ctx->Array.TexCoord[texUnit].StrideB =  size*sizeof(GLfloat);
326         break;
327      case GL_DOUBLE:
328         ctx->Array.TexCoord[texUnit].StrideB =  size*sizeof(GLdouble);
329         break;
330      default:
331         gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
332         return;
333      }
334   }
335   ctx->Array.TexCoord[texUnit].Size = size;
336   ctx->Array.TexCoord[texUnit].Type = type;
337   ctx->Array.TexCoord[texUnit].Stride = stride;
338   ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr;
339
340   ctx->Array.TexCoordFunc[texUnit] = gl_trans_4f_tab[size][TYPE_IDX(type)];
341   ctx->Array.TexCoordEltFunc[texUnit] = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
342   ctx->Array.NewArrayState |= PIPE_TEX(texUnit);
343   ctx->NewState |= NEW_CLIENT_STATE;
344}
345
346
347
348
349void GLAPIENTRY glEdgeFlagPointer(CTX_ARG GLsizei stride, const void *vptr )
350{
351   const GLboolean *ptr = (GLboolean *)vptr;
352
353   GLcontext *ctx;
354   GET_CONTEXT;
355   CHECK_CONTEXT;
356   ctx = CC;
357
358   if (stride<0) {
359      gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
360      return;
361   }
362   ctx->Array.EdgeFlag.Stride = stride;
363   ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean);
364   ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr;
365   if (stride != sizeof(GLboolean)) {
366      ctx->Array.EdgeFlagFunc = gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
367   } else {
368      ctx->Array.EdgeFlagFunc = 0;
369   }
370   ctx->Array.EdgeFlagEltFunc = gl_trans_elt_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
371   ctx->Array.NewArrayState |= VERT_EDGE;
372   ctx->NewState |= NEW_CLIENT_STATE;
373}
374
375
376/* Called only from gl_DrawElements
377 */
378void gl_CVAEltPointer( GLcontext *ctx, GLenum type, const GLvoid *ptr )
379{
380   switch (type) {
381      case GL_UNSIGNED_BYTE:
382         ctx->CVA.Elt.StrideB = sizeof(GLubyte);
383         break;
384      case GL_UNSIGNED_SHORT:
385         ctx->CVA.Elt.StrideB = sizeof(GLushort);
386         break;
387      case GL_UNSIGNED_INT:
388         ctx->CVA.Elt.StrideB = sizeof(GLuint);
389         break;
390      default:
391         gl_error( ctx, GL_INVALID_ENUM, "glEltPointer(type)" );
392         return;
393   }
394   ctx->CVA.Elt.Type = type;
395   ctx->CVA.Elt.Stride = 0;
396   ctx->CVA.Elt.Ptr = (void *) ptr;
397   ctx->CVA.EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
398   ctx->Array.NewArrayState |= VERT_ELT; /* ??? */
399}
400
401
402
403/* KW: Batch function to exec all the array elements in the input
404 *     buffer prior to transform.  Done only the first time a vertex
405 *     buffer is executed or compiled.
406 *
407 * KW: Have to do this after each glEnd if cva isn't active.  (also
408 *     have to do it after each full buffer)
409 */
410void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM,
411			     GLuint start,
412			     GLuint count)
413{
414   GLuint *flags = IM->Flag;
415   GLuint *elts = IM->Elt;
416   GLuint translate = ctx->Array.Flags;
417   GLuint i;
418
419   if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
420      fprintf(stderr, "exec_array_elements %d .. %d\n", start, count);
421
422   if (translate & VERT_OBJ_ANY)
423      (ctx->Array.VertexEltFunc)( IM->Obj,
424				  &ctx->Array.Vertex,
425				  flags, elts, (VERT_ELT|VERT_OBJ_ANY),
426				  start, count);
427
428   if (translate & VERT_NORM)
429      (ctx->Array.NormalEltFunc)( IM->Normal,
430				  &ctx->Array.Normal,
431				  flags, elts, (VERT_ELT|VERT_NORM),
432				  start, count);
433
434   if (translate & VERT_EDGE)
435      (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag,
436				    &ctx->Array.EdgeFlag,
437				    flags, elts, (VERT_ELT|VERT_EDGE),
438				    start, count);
439
440   if (translate & VERT_RGBA)
441      (ctx->Array.ColorEltFunc)( IM->Color,
442				 &ctx->Array.Color,
443				 flags, elts, (VERT_ELT|VERT_RGBA),
444				 start, count);
445
446   if (translate & VERT_INDEX)
447      (ctx->Array.IndexEltFunc)( IM->Index,
448				 &ctx->Array.Index,
449				 flags, elts, (VERT_ELT|VERT_INDEX),
450				 start, count);
451
452   if (translate & VERT_TEX0_ANY)
453      (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0],
454				       &ctx->Array.TexCoord[0],
455				       flags, elts, (VERT_ELT|VERT_TEX0_ANY),
456				       start, count);
457
458   if (translate & VERT_TEX1_ANY)
459      (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1],
460				       &ctx->Array.TexCoord[1],
461				       flags, elts, (VERT_ELT|VERT_TEX1_ANY),
462				       start, count);
463
464   /* Lighting ignores the and-flag, so still need to do this.
465    */
466/*     fprintf(stderr, "start %d count %d\n", start, count); */
467/*     gl_print_vert_flags("translate", translate); */
468
469   for (i = start ; i < count ; i++)
470      if (flags[i] & VERT_ELT) {
471/*  	 flags[i] &= ~VERT_ELT;	*/
472	 flags[i] |= translate;
473      }
474}
475
476
477
478void gl_DrawArrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count )
479{
480   struct vertex_buffer *VB = ctx->VB;
481   GLint i;
482
483   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays");
484
485   if (count<0) {
486      gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
487      return;
488   }
489
490   if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled)
491   {
492      GLint remaining = count;
493      GLint i;
494      struct gl_client_array *Normal;
495      struct gl_client_array *Color;
496      struct gl_client_array *Index;
497      struct gl_client_array *TexCoord[MAX_TEXTURE_UNITS];
498      struct gl_client_array *EdgeFlag;
499      struct immediate *IM = VB->IM;
500      struct gl_pipeline *elt = &ctx->CVA.elt;
501      GLboolean relock;
502      GLuint fallback, required;
503
504      if (ctx->NewState)
505	 gl_update_state( ctx );
506
507      /* Just turn off cva on this path.  Could be useful for multipass
508       * rendering to keep it turned on.
509       */
510      relock = ctx->CompileCVAFlag;
511      ctx->CompileCVAFlag = 0;
512
513      if (!elt->pipeline_valid || relock)
514	 gl_build_immediate_pipeline( ctx );
515
516      required = elt->inputs;
517      fallback = (elt->inputs & ~ctx->Array.Summary);
518
519      if (required & VERT_RGBA)
520      {
521	 Color = &ctx->Array.Color;
522	 if (fallback & VERT_RGBA) {
523	    Color = &ctx->Fallback.Color;
524	    ctx->Array.ColorFunc =
525	       gl_trans_4ub_tab[4][TYPE_IDX(GL_UNSIGNED_BYTE)];
526	 }
527      }
528
529      if (required & VERT_INDEX)
530      {
531	 Index = &ctx->Array.Index;
532	 if (fallback & VERT_INDEX) {
533	    Index = &ctx->Fallback.Index;
534	    ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(GL_UNSIGNED_INT)];
535	 }
536      }
537
538      for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
539      {
540	 GLuint flag = VERT_TEX_ANY(i);
541
542	 if (required & flag) {
543	    TexCoord[i] = &ctx->Array.TexCoord[i];
544
545	    if (fallback & flag)
546	    {
547	       TexCoord[i] = &ctx->Fallback.TexCoord[i];
548	       TexCoord[i]->Size = gl_texcoord_size( ctx->Current.Flag, i );
549
550	       ctx->Array.TexCoordFunc[i] =
551		  gl_trans_4f_tab[TexCoord[i]->Size][TYPE_IDX(GL_FLOAT)];
552	    }
553	 }
554      }
555
556      if (ctx->Array.Flags != ctx->Array.Flag[0])
557 	 for (i = 0 ; i < VB_MAX ; i++)
558	    ctx->Array.Flag[i] = ctx->Array.Flags;
559
560
561      if (required & VERT_NORM)
562      {
563	 Normal = &ctx->Array.Normal;
564	 if (fallback & VERT_NORM) {
565	    Normal = &ctx->Fallback.Normal;
566	    ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(GL_FLOAT)];
567	 }
568      }
569
570      if ( required & VERT_EDGE )
571      {
572	 if (mode == GL_TRIANGLES ||
573	     mode == GL_QUADS ||
574	     mode == GL_POLYGON)
575	 {
576	    EdgeFlag = &ctx->Array.EdgeFlag;
577	    if (fallback & VERT_EDGE) {
578	       EdgeFlag = &ctx->Fallback.EdgeFlag;
579	       ctx->Array.EdgeFlagFunc =
580		  gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
581	    }
582	 }
583	 else
584	    required &= ~VERT_EDGE;
585      }
586
587      VB->Primitive = IM->Primitive;
588      VB->NextPrimitive = IM->NextPrimitive;
589      VB->MaterialMask = IM->MaterialMask;
590      VB->Material = IM->Material;
591      VB->BoundsPtr = 0;
592
593      while (remaining > 0) {
594         GLint vbspace = VB_MAX - VB_START;
595	 GLuint count, n;
596
597	 if (vbspace >= remaining) {
598	    n = remaining;
599	    VB->LastPrimitive = VB_START + n;
600	 } else {
601	    n = vbspace;
602	    VB->LastPrimitive = VB_START;
603	 }
604
605	 VB->CullMode = 0;
606
607	 ctx->Array.VertexFunc( IM->Obj + VB_START,
608				&ctx->Array.Vertex, start, n );
609
610	 if (required & VERT_NORM) {
611	    ctx->Array.NormalFunc( IM->Normal + VB_START,
612				   Normal, start, n );
613	 }
614
615	 if (required & VERT_EDGE) {
616	    ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START,
617				     EdgeFlag, start, n );
618	 }
619
620	 if (required & VERT_RGBA) {
621	    ctx->Array.ColorFunc( IM->Color + VB_START,
622				  Color, start, n );
623	 }
624
625	 if (required & VERT_INDEX) {
626	    ctx->Array.IndexFunc( IM->Index + VB_START,
627				  Index, start, n );
628	 }
629
630	 if (required & VERT_TEX0_ANY) {
631	    IM->v.TexCoord[0].size = TexCoord[0]->Size;
632	    ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START,
633					TexCoord[0], start, n );
634	 }
635
636	 if (required & VERT_TEX1_ANY) {
637	    IM->v.TexCoord[1].size = TexCoord[1]->Size;
638	    ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START,
639					TexCoord[1], start, n );
640	 }
641
642	 VB->ObjPtr = &IM->v.Obj;
643	 VB->NormalPtr = &IM->v.Normal;
644	 VB->ColorPtr = &IM->v.Color;
645	 VB->Color[0] = VB->Color[1] = VB->ColorPtr;
646	 VB->IndexPtr = &IM->v.Index;
647	 VB->EdgeFlagPtr = &IM->v.EdgeFlag;
648	 VB->TexCoordPtr[0] = &IM->v.TexCoord[0];
649	 VB->TexCoordPtr[1] = &IM->v.TexCoord[1];
650
651	 VB->Flag = ctx->Array.Flag;
652	 VB->OrFlag = ctx->Array.Flags;
653
654	 VB->Start = IM->Start = VB_START;
655	 count = VB->Count = IM->Count = VB_START + n;
656
657#define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)
658
659	 RESET_VEC(IM->v.Obj, (GLfloat *), VB_START, count);
660	 RESET_VEC(IM->v.Normal, (GLfloat *), VB_START, count);
661	 RESET_VEC(IM->v.TexCoord[0], (GLfloat *), VB_START, count);
662	 RESET_VEC(IM->v.TexCoord[1], (GLfloat *), VB_START, count);
663	 RESET_VEC(IM->v.Index, &, VB_START, count);
664	 RESET_VEC(IM->v.Elt, &, VB_START, count);
665	 RESET_VEC(IM->v.EdgeFlag, &, VB_START, count);
666	 RESET_VEC(IM->v.Color, (GLubyte *), VB_START, count);
667	 RESET_VEC(VB->Clip, (GLfloat *), VB_START, count);
668	 RESET_VEC(VB->Eye, (GLfloat *), VB_START, count);
669	 RESET_VEC(VB->Win, (GLfloat *), VB_START, count);
670	 RESET_VEC(VB->BColor, (GLubyte *), VB_START, count);
671	 RESET_VEC(VB->BIndex, &, VB_START, count);
672
673	 VB->NextPrimitive[VB->CopyStart] = VB->Count;
674	 VB->Primitive[VB->CopyStart] = mode;
675
676         /* Transform and render.
677	  */
678	 if (0) gl_print_cassette_flags( IM, VB->Flag );
679         gl_run_pipeline( VB );
680	 gl_reset_vb( VB );
681
682	 ctx->Array.Flag[count] = ctx->Array.Flags;
683	 ctx->Array.Flag[VB_START] = ctx->Array.Flags;
684
685         start += n;
686         remaining -= n;
687      }
688
689      ctx->CompileCVAFlag = relock;
690   }
691   else if (ctx->Array.Vertex.Enabled)
692   {
693      /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases.  These
694       * could be handled by the above code, but it gets a little
695       * complex.  The generated list is still of good quality
696       * this way.
697       */
698      gl_Begin( ctx, mode );
699      for (i=0;i<count;i++) {
700         gl_ArrayElement( ctx, start+i );
701      }
702      gl_End( ctx );
703   }
704   else
705   {
706      /* The degenerate case where vertices are not enabled - only
707       * need to process the very final array element, as all of the
708       * preceding ones would be overwritten anyway.
709       */
710      gl_Begin( ctx, mode );
711      gl_ArrayElement( ctx, start+count );
712      gl_End( ctx );
713   }
714}
715
716
717
718/* KW: Exactly fakes the effects of calling glArrayElement multiple times.
719 *     Compilation is handled via. the IM->maybe_transform_vb() callback.
720 */
721#if 1
722#define DRAW_ELT(FUNC, TYPE)				\
723static void FUNC( GLcontext *ctx, GLenum mode,		\
724		  TYPE *indices, GLuint count )		\
725{							\
726   GLuint i,j;						\
727							\
728   gl_Begin( ctx, mode );				\
729							\
730   for (j = 0 ; j < count ; ) {				\
731      struct immediate *IM = ctx->input;		\
732      GLuint start = IM->Start;				\
733      GLuint nr = MIN2( VB_MAX, count - j + start );	\
734      GLuint sf = IM->Flag[start];			\
735      IM->FlushElt |= IM->ArrayEltFlush;		\
736							\
737      for (i = start ; i < nr ; i++) {			\
738	 IM->Elt[i] = (GLuint) *indices++;		\
739	 IM->Flag[i] = VERT_ELT;			\
740      }							\
741							\
742      if (j == 0) IM->Flag[start] |= sf;		\
743							\
744      IM->Count = nr;					\
745      j += nr - start;					\
746							\
747      if (j == count) gl_End( ctx );			\
748      IM->maybe_transform_vb( IM );			\
749   }							\
750}
751#else
752#define DRAW_ELT(FUNC, TYPE)				\
753static void FUNC( GLcontext *ctx, GLenum mode,		\
754		   TYPE *indices, GLuint count )	\
755{							\
756  int i;						\
757  glBegin(mode);					\
758  for (i = 0 ; i < count ; i++)				\
759    glArrayElement( indices[i] );			\
760  glEnd();						\
761}
762#endif
763
764
765DRAW_ELT( draw_elt_ubyte, GLubyte )
766DRAW_ELT( draw_elt_ushort, GLushort )
767DRAW_ELT( draw_elt_uint, GLuint )
768
769
770static GLuint natural_stride[0x10] =
771{
772   sizeof(GLbyte),		/* 0 */
773   sizeof(GLubyte),		/* 1 */
774   sizeof(GLshort),		/* 2 */
775   sizeof(GLushort),		/* 3 */
776   sizeof(GLint),		/* 4 */
777   sizeof(GLuint),		/* 5 */
778   sizeof(GLfloat),		/* 6 */
779   2 * sizeof(GLbyte),		/* 7 */
780   3 * sizeof(GLbyte),		/* 8 */
781   4 * sizeof(GLbyte),		/* 9 */
782   sizeof(GLdouble),		/* a */
783   0,				/* b */
784   0,				/* c */
785   0,				/* d */
786   0,				/* e */
787   0				/* f */
788};
789
790void GLAPIENTRY glDrawElements(CTX_ARG GLenum mode, GLsizei count,
791                                GLenum type, const GLvoid *indices )
792{
793   GLcontext *ctx;
794   struct gl_cva *cva;
795
796   GET_CONTEXT;
797   CHECK_CONTEXT;
798   ctx = CC;
799
800   cva = &ctx->CVA;
801   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
802
803   if (count <= 0) {
804      if (count < 0)
805	 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
806      return;
807   }
808
809   if (mode < 0 || mode > GL_POLYGON) {
810      gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
811      return;
812   }
813
814   if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
815   {
816       gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
817       return;
818   }
819
820   if (ctx->NewState)
821      gl_update_state(ctx);
822
823   if (ctx->CompileCVAFlag)
824   {
825#if defined(MESA_CVA_PROF)
826      force_init_prof();
827#endif
828
829      /* Treat VERT_ELT like a special client array.
830       */
831      ctx->Array.NewArrayState |= VERT_ELT;
832      ctx->Array.Summary |= VERT_ELT;
833      ctx->Array.Flags |= VERT_ELT;
834
835      cva->elt_mode = mode;
836      cva->elt_count = count;
837      cva->Elt.Type = type;
838      cva->Elt.Ptr = (void *) indices;
839      cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
840      cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
841
842      if (!cva->pre.pipeline_valid)
843	 gl_build_precalc_pipeline( ctx );
844      else if (MESA_VERBOSE & VERBOSE_PIPELINE)
845	 fprintf(stderr, ": dont rebuild\n");
846
847      gl_cva_force_precalc( ctx );
848
849      /* Did we 'precalculate' the render op?
850       */
851      if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
852	 ctx->Array.NewArrayState |= VERT_ELT;
853	 ctx->Array.Summary &= ~VERT_ELT;
854	 ctx->Array.Flags &= ~VERT_ELT;
855	 return;
856      }
857
858      if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
859	 printf("using immediate\n");
860   }
861
862
863   /* Otherwise, have to use the immediate path to render.
864    */
865   switch (type) {
866   case GL_UNSIGNED_BYTE:
867   {
868      GLubyte *ub_indices = (GLubyte *) indices;
869      if (ctx->Array.Summary & VERT_OBJ_ANY) {
870	 draw_elt_ubyte( ctx, mode, ub_indices, count );
871      } else {
872	 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
873      }
874   }
875   break;
876   case GL_UNSIGNED_SHORT:
877   {
878      GLushort *us_indices = (GLushort *) indices;
879      if (ctx->Array.Summary & VERT_OBJ_ANY) {
880	 draw_elt_ushort( ctx, mode, us_indices, count );
881      } else {
882	 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
883      }
884   }
885   break;
886   case GL_UNSIGNED_INT:
887   {
888      GLuint *ui_indices = (GLuint *) indices;
889      if (ctx->Array.Summary & VERT_OBJ_ANY) {
890	 draw_elt_uint( ctx, mode, ui_indices, count );
891      } else {
892	 gl_ArrayElement( ctx, ui_indices[count-1] );
893      }
894   }
895   break;
896   default:
897      gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
898      break;
899   }
900
901   if (ctx->CompileCVAFlag) {
902      ctx->Array.NewArrayState |= VERT_ELT;
903      ctx->Array.Summary &= ~VERT_ELT;
904   }
905}
906
907
908
909void GLAPIENTRY glInterleavedArrays(CTX_ARG GLenum format, GLsizei stride,
910                                     const GLvoid *pointer )
911{
912   GLcontext *ctx;
913   GLboolean tflag, cflag, nflag;  /* enable/disable flags */
914   GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
915
916   GLenum ctype;                   /* color type */
917   GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
918   GLint defstride;                /* default stride */
919   GLint c, f;
920   GLint coordUnitSave;
921
922   GET_CONTEXT;
923   CHECK_CONTEXT;
924   ctx = CC;
925
926
927   f = sizeof(GLfloat);
928   c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
929
930   if (stride<0) {
931      gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
932      return;
933   }
934
935   switch (format) {
936      case GL_V2F:
937         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
938         tcomps = 0;  ccomps = 0;  vcomps = 2;
939         voffset = 0;
940         defstride = 2*f;
941         break;
942      case GL_V3F:
943         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
944         tcomps = 0;  ccomps = 0;  vcomps = 3;
945         voffset = 0;
946         defstride = 3*f;
947         break;
948      case GL_C4UB_V2F:
949         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
950         tcomps = 0;  ccomps = 4;  vcomps = 2;
951         ctype = GL_UNSIGNED_BYTE;
952         coffset = 0;
953         voffset = c;
954         defstride = c + 2*f;
955         break;
956      case GL_C4UB_V3F:
957         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
958         tcomps = 0;  ccomps = 4;  vcomps = 3;
959         ctype = GL_UNSIGNED_BYTE;
960         coffset = 0;
961         voffset = c;
962         defstride = c + 3*f;
963         break;
964      case GL_C3F_V3F:
965         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
966         tcomps = 0;  ccomps = 3;  vcomps = 3;
967         ctype = GL_FLOAT;
968         coffset = 0;
969         voffset = 3*f;
970         defstride = 6*f;
971         break;
972      case GL_N3F_V3F:
973         tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
974         tcomps = 0;  ccomps = 0;  vcomps = 3;
975         noffset = 0;
976         voffset = 3*f;
977         defstride = 6*f;
978         break;
979      case GL_C4F_N3F_V3F:
980         tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
981         tcomps = 0;  ccomps = 4;  vcomps = 3;
982         ctype = GL_FLOAT;
983         coffset = 0;
984         noffset = 4*f;
985         voffset = 7*f;
986         defstride = 10*f;
987         break;
988      case GL_T2F_V3F:
989         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
990         tcomps = 2;  ccomps = 0;  vcomps = 3;
991         voffset = 2*f;
992         defstride = 5*f;
993         break;
994      case GL_T4F_V4F:
995         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
996         tcomps = 4;  ccomps = 0;  vcomps = 4;
997         voffset = 4*f;
998         defstride = 8*f;
999         break;
1000      case GL_T2F_C4UB_V3F:
1001         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
1002         tcomps = 2;  ccomps = 4;  vcomps = 3;
1003         ctype = GL_UNSIGNED_BYTE;
1004         coffset = 2*f;
1005         voffset = c+2*f;
1006         defstride = c+5*f;
1007         break;
1008      case GL_T2F_C3F_V3F:
1009         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
1010         tcomps = 2;  ccomps = 3;  vcomps = 3;
1011         ctype = GL_FLOAT;
1012         coffset = 2*f;
1013         voffset = 5*f;
1014         defstride = 8*f;
1015         break;
1016      case GL_T2F_N3F_V3F:
1017         tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
1018         tcomps = 2;  ccomps = 0;  vcomps = 3;
1019         noffset = 2*f;
1020         voffset = 5*f;
1021         defstride = 8*f;
1022         break;
1023      case GL_T2F_C4F_N3F_V3F:
1024         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
1025         tcomps = 2;  ccomps = 4;  vcomps = 3;
1026         ctype = GL_FLOAT;
1027         coffset = 2*f;
1028         noffset = 6*f;
1029         voffset = 9*f;
1030         defstride = 12*f;
1031         break;
1032      case GL_T4F_C4F_N3F_V4F:
1033         tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
1034         tcomps = 4;  ccomps = 4;  vcomps = 4;
1035         ctype = GL_FLOAT;
1036         coffset = 4*f;
1037         noffset = 8*f;
1038         voffset = 11*f;
1039         defstride = 15*f;
1040         break;
1041      default:
1042         gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1043         return;
1044   }
1045
1046   if (stride==0) {
1047      stride = defstride;
1048   }
1049
1050   gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
1051   gl_DisableClientState( ctx, GL_INDEX_ARRAY );
1052
1053   /* Texcoords */
1054   coordUnitSave = ctx->Array.ActiveTexture;
1055   if (tflag) {
1056      GLint i;
1057      GLint factor = ctx->Array.TexCoordInterleaveFactor;
1058      for (i = 0; i < factor; i++) {
1059         gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1060         gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1061         glTexCoordPointer(CTX_PRM  tcomps, GL_FLOAT, stride,
1062                             (GLubyte *) pointer + i * coffset );
1063      }
1064      for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
1065         gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1066         gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1067      }
1068   }
1069   else {
1070      GLint i;
1071      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1072         gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1073         gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1074      }
1075   }
1076   /* Restore texture coordinate unit index */
1077   gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
1078
1079
1080   /* Color */
1081   if (cflag) {
1082      gl_EnableClientState( ctx, GL_COLOR_ARRAY );
1083      glColorPointer(CTX_PRM ccomps, ctype, stride,
1084                       (GLubyte*) pointer + coffset );
1085   }
1086   else {
1087      gl_DisableClientState( ctx, GL_COLOR_ARRAY );
1088   }
1089
1090
1091   /* Normals */
1092   if (nflag) {
1093      gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
1094      glNormalPointer(CTX_PRM GL_FLOAT, stride,
1095                        (GLubyte*) pointer + noffset );
1096   }
1097   else {
1098      gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
1099   }
1100
1101   gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
1102   glVertexPointer(CTX_PRM vcomps, GL_FLOAT, stride,
1103                     (GLubyte *) pointer + voffset );
1104}
1105
1106
1107
1108void GLAPIENTRY glDrawRangeElements(CTX_ARG GLenum mode, GLuint start,
1109                                     GLuint end, GLsizei count,
1110                                     GLenum type, const GLvoid *indices )
1111{
1112   GLcontext *ctx;
1113   GET_CONTEXT;
1114   CHECK_CONTEXT;
1115   ctx = CC;
1116
1117   if (end < start) {
1118      gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
1119      return;
1120   }
1121
1122   if (!ctx->Array.LockCount && 2*count > (GLint) 3*(end-start)) {
1123      glLockArraysEXT(CTX_PRM start, end );
1124      glDrawElements(CTX_PRM mode, count, type, indices );
1125      glUnlockArraysEXT(CTX_VPRM );
1126   } else {
1127      glDrawElements(CTX_PRM mode, count, type, indices );
1128   }
1129}
1130
1131
1132
1133void gl_update_client_state( GLcontext *ctx )
1134{
1135   static GLuint sz_flags[5] = { 0,
1136				 0,
1137				 VERT_OBJ_2,
1138				 VERT_OBJ_23,
1139				 VERT_OBJ_234 };
1140
1141   static GLuint tc_flags[5] = { 0,
1142				 VERT_TEX0_1,
1143				 VERT_TEX0_12,
1144				 VERT_TEX0_123,
1145				 VERT_TEX0_1234 };
1146
1147   ctx->Array.Flags = 0;
1148   ctx->Array.Summary = 0;
1149   ctx->input->ArrayIncr = 0;
1150
1151   if (ctx->Array.Normal.Enabled)      ctx->Array.Flags |= VERT_NORM;
1152   if (ctx->Array.Color.Enabled)       ctx->Array.Flags |= VERT_RGBA;
1153   if (ctx->Array.Index.Enabled)       ctx->Array.Flags |= VERT_INDEX;
1154   if (ctx->Array.EdgeFlag.Enabled)    ctx->Array.Flags |= VERT_EDGE;
1155   if (ctx->Array.Vertex.Enabled) {
1156      ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size];
1157      ctx->input->ArrayIncr = 1;
1158   }
1159   if (ctx->Array.TexCoord[0].Enabled) {
1160      ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size];
1161   }
1162   if (ctx->Array.TexCoord[1].Enabled) {
1163      ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS);
1164   }
1165
1166   /* Not really important any more:
1167    */
1168   ctx->Array.Summary = ctx->Array.Flags & VERT_DATA;
1169   ctx->input->ArrayAndFlags = ~ctx->Array.Flags;
1170   ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
1171}
1172
1173