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