t_dd_dmatmp2.h revision 47909141985a5aa38a49ea45b3aea795f1922dfb
1
2/*
3 * Mesa 3-D graphics library
4 * Version:  4.0.3
5 *
6 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Keith Whitwell <keith@tungstengraphics.com>
27 */
28
29
30/* Template for render stages which build and emit vertices directly
31 * to fixed-size dma buffers.  Useful for rendering strips and other
32 * native primitives where clipping and per-vertex tweaks such as
33 * those in t_dd_tritmp.h are not required.
34 *
35 */
36
37#if !HAVE_TRIANGLES || !HAVE_POINTS || !HAVE_LINES
38#error "must have points, lines & triangles to use render template"
39#endif
40
41#if !HAVE_TRI_STRIPS || !HAVE_TRI_FANS
42#error "must have tri strip and fans to use render template"
43#endif
44
45#if !HAVE_LINE_STRIPS
46#error "must have line strips to use render template"
47#endif
48
49#if !HAVE_POLYGONS
50#error "must have polygons to use render template"
51#endif
52
53#if !HAVE_ELTS
54#error "must have elts to use render template"
55#endif
56
57
58#ifndef EMIT_TWO_ELTS
59#define EMIT_TWO_ELTS( dest, offset, elt0, elt1 )	\
60do { 						\
61   (dest)[offset] = (elt0); 			\
62   (dest)[offset+1] = (elt1); 			\
63} while (0)
64#endif
65
66
67/**********************************************************************/
68/*                  Render whole begin/end objects                    */
69/**********************************************************************/
70
71
72static ELT_TYPE *TAG(emit_elts)( GLcontext *ctx,
73			    ELT_TYPE *dest,
74			    GLuint *elts, GLuint nr )
75{
76   GLint i;
77   LOCAL_VARS;
78
79   for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) {
80      EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
81      dest += 2;
82   }
83   if (i < nr) {
84      EMIT_ELT( dest, 0, elts[0] );
85      dest += 1;
86   }
87
88   return dest;
89}
90
91static ELT_TYPE *TAG(emit_consecutive_elts)( GLcontext *ctx,
92					ELT_TYPE *dest,
93					GLuint start, GLuint nr )
94{
95   GLint i;
96   LOCAL_VARS;
97
98   for ( i = 0 ; i+1 < nr ; i+=2, start += 2 ) {
99      EMIT_TWO_ELTS( dest, 0, start, start+1 );
100      dest += 2;
101   }
102   if (i < nr) {
103      EMIT_ELT( dest, 0, start );
104      dest += 1;
105   }
106
107   return dest;
108}
109
110/***********************************************************************
111 *                    Render non-indexed primitives.
112 ***********************************************************************/
113
114
115
116static void TAG(render_points_verts)( GLcontext *ctx,
117				      GLuint start,
118				      GLuint count,
119				      GLuint flags )
120{
121   if (start < count) {
122      LOCAL_VARS;
123      if (0) fprintf(stderr, "%s\n", __FUNCTION__);
124      EMIT_PRIM( ctx, GL_POINTS, HW_POINTS, start, count );
125   }
126}
127
128static void TAG(render_lines_verts)( GLcontext *ctx,
129				     GLuint start,
130				     GLuint count,
131				     GLuint flags )
132{
133   LOCAL_VARS;
134   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
135   count -= (count-start) & 1;
136
137   if (start+1 >= count)
138      return;
139
140   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
141      RESET_STIPPLE();
142      AUTO_STIPPLE( GL_TRUE );
143   }
144
145   EMIT_PRIM( ctx, GL_LINES, HW_LINES, start, count );
146
147   if ((flags & PRIM_END) && ctx->Line.StippleFlag)
148      AUTO_STIPPLE( GL_FALSE );
149}
150
151
152static void TAG(render_line_strip_verts)( GLcontext *ctx,
153					  GLuint start,
154					  GLuint count,
155					  GLuint flags )
156{
157   LOCAL_VARS;
158   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
159
160   if (start+1 >= count)
161      return;
162
163   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
164      RESET_STIPPLE();
165
166
167   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES ))
168   {
169      int dmasz = GET_MAX_HW_ELTS();
170      GLuint j, nr;
171
172      ELT_INIT( GL_LINES, HW_LINES );
173
174      /* Emit whole number of lines in each full buffer.
175       */
176      dmasz = dmasz/2;
177
178
179      for (j = start; j + 1 < count; j += nr - 1 ) {
180	 ELT_TYPE *dest;
181	 GLint i;
182
183	 nr = MIN2( dmasz, count - j );
184	 dest = ALLOC_ELTS( (nr-1)*2 );
185
186	 for ( i = j ; i+1 < j+nr ; i+=1 ) {
187	    EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
188	    dest += 2;
189	 }
190
191	 CLOSE_ELTS();
192      }
193   }
194   else
195      EMIT_PRIM( ctx, GL_LINE_STRIP, HW_LINE_STRIP, start, count );
196}
197
198
199static void TAG(render_line_loop_verts)( GLcontext *ctx,
200					 GLuint start,
201					 GLuint count,
202					 GLuint flags )
203{
204   LOCAL_VARS;
205   GLuint j, nr;
206   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
207
208   if (flags & PRIM_BEGIN) {
209      j = start;
210      if (ctx->Line.StippleFlag)
211	 RESET_STIPPLE( );
212   }
213   else
214      j = start + 1;
215
216   if (flags & PRIM_END) {
217
218      if (start+1 >= count)
219	 return;
220
221      if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) {
222	 int dmasz = GET_MAX_HW_ELTS();
223
224	 ELT_INIT( GL_LINES, HW_LINES );
225
226	 /* Emit whole number of lines in each full buffer.
227	  */
228	 dmasz = dmasz/2;
229
230	 /* Ensure last vertex doesn't wrap:
231	  */
232	 dmasz--;
233
234	 for (; j + 1 < count;  ) {
235	    GLint i;
236	    ELT_TYPE *dest;
237
238	    nr = MIN2( dmasz, count - j );
239	    dest = ALLOC_ELTS( nr*2 );	/* allocs room for 1 more line */
240
241	    for ( i = 0 ; i < nr - 1 ; i+=1 ) {
242	       EMIT_TWO_ELTS( dest, 0, (j+i), (j+i+1) );
243	       dest += 2;
244	    }
245
246	    j += nr - 1;
247
248	    /* Emit 1 more line into space alloced above */
249	    if (j + 1 >= count) {
250 	       EMIT_TWO_ELTS( dest, 0, (j), (start) );
251 	       dest += 2;
252 	    }
253
254	    CLOSE_ELTS();
255	 }
256      }
257      else
258      {
259	 int dmasz = GET_MAX_HW_ELTS() - 1;
260
261	 ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
262
263	 for ( ; j + 1 < count;  ) {
264	    nr = MIN2( dmasz, count - j );
265	    if (j + nr < count) {
266	       ELT_TYPE *dest = ALLOC_ELTS( nr );
267	       dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr );
268	       j += nr - 1;
269	       CLOSE_ELTS();
270	    }
271	    else if (nr) {
272	       ELT_TYPE *dest = ALLOC_ELTS( nr + 1 );
273	       dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr );
274	       dest = TAG(emit_consecutive_elts)( ctx, dest, start, 1 );
275	       j += nr;
276	       CLOSE_ELTS();
277	    }
278	 }
279      }
280   } else {
281      TAG(render_line_strip_verts)( ctx, j, count, flags );
282   }
283}
284
285
286static void TAG(render_triangles_verts)( GLcontext *ctx,
287					 GLuint start,
288					 GLuint count,
289					 GLuint flags )
290{
291   LOCAL_VARS;
292   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
293
294   count -= (count-start)%3;
295
296   if (start+2 >= count) {
297      return;
298   }
299
300   /* need a PREFER_DISCRETE_ELT_PRIM here too..
301    */
302   EMIT_PRIM( ctx, GL_TRIANGLES, HW_TRIANGLES, start, count );
303}
304
305
306
307static void TAG(render_tri_strip_verts)( GLcontext *ctx,
308					 GLuint start,
309					 GLuint count,
310					 GLuint flags )
311{
312   LOCAL_VARS;
313   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
314
315   if (start + 2 >= count)
316      return;
317
318   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
319   {
320      int dmasz = GET_MAX_HW_ELTS();
321      int parity = 0;
322      GLuint j, nr;
323
324      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
325
326      /* Emit even number of tris in each full buffer.
327       */
328      dmasz = dmasz/3;
329      dmasz -= dmasz & 1;
330
331      for (j = start; j + 2 < count; j += nr - 2 ) {
332	 ELT_TYPE *dest;
333	 GLint i;
334
335	 nr = MIN2( dmasz, count - j );
336	 dest = ALLOC_ELTS( (nr-2)*3 );
337
338	 for ( i = j ; i+2 < j+nr ; i++, parity^=1 ) {
339	    EMIT_ELT( dest, 0, (i+0+parity) );
340	    EMIT_ELT( dest, 1, (i+1-parity) );
341	    EMIT_ELT( dest, 2, (i+2) );
342	    dest += 3;
343	 }
344
345	 CLOSE_ELTS();
346      }
347   }
348   else
349      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
350}
351
352static void TAG(render_tri_fan_verts)( GLcontext *ctx,
353				       GLuint start,
354				       GLuint count,
355				       GLuint flags )
356{
357   LOCAL_VARS;
358   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
359
360   if (start+2 >= count)
361      return;
362
363   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
364   {
365      int dmasz = GET_MAX_HW_ELTS();
366      GLuint j, nr;
367
368      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
369
370      dmasz = dmasz/3;
371
372      for (j = start + 1; j + 1 < count; j += nr - 1 ) {
373	 ELT_TYPE *dest;
374	 GLint i;
375
376	 nr = MIN2( dmasz, count - j );
377	 dest = ALLOC_ELTS( (nr-1)*3 );
378
379	 for ( i = j ; i+1 < j+nr ; i++ ) {
380	    EMIT_ELT( dest, 0, (start) );
381	    EMIT_ELT( dest, 1, (i) );
382	    EMIT_ELT( dest, 2, (i+1) );
383	    dest += 3;
384	 }
385
386	 CLOSE_ELTS();
387      }
388   }
389   else {
390      EMIT_PRIM( ctx, GL_TRIANGLE_FAN, HW_TRIANGLE_FAN, start, count );
391   }
392}
393
394
395static void TAG(render_poly_verts)( GLcontext *ctx,
396				    GLuint start,
397				    GLuint count,
398				    GLuint flags )
399{
400   LOCAL_VARS;
401   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
402
403   if (start+2 >= count)
404      return;
405
406   EMIT_PRIM( ctx, GL_POLYGON, HW_POLYGON, start, count );
407}
408
409static void TAG(render_quad_strip_verts)( GLcontext *ctx,
410					  GLuint start,
411					  GLuint count,
412					  GLuint flags )
413{
414   LOCAL_VARS;
415   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
416
417   count -= (count-start) & 1;
418
419   if (start+3 >= count)
420      return;
421
422   if (HAVE_QUAD_STRIPS) {
423      EMIT_PRIM( ctx, GL_QUAD_STRIP, HW_QUAD_STRIP, start, count );
424   }
425   else if (ctx->_TriangleCaps & DD_FLATSHADE) {
426      LOCAL_VARS;
427      int dmasz = GET_MAX_HW_ELTS();
428      GLuint j, nr;
429
430      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
431
432      /* Emit whole number of quads in total, and in each buffer.
433       */
434      dmasz = (dmasz/6)*2;
435
436      for (j = start; j + 3 < count; j += nr - 2 ) {
437	 ELT_TYPE *dest;
438	 GLint quads, i;
439
440	 nr = MIN2( dmasz, count - j );
441	 quads = (nr/2)-1;
442	 dest = ALLOC_ELTS( quads*6 );
443
444	 for ( i = j ; i < j+quads*2 ; i+=2 ) {
445	    EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
446	    EMIT_TWO_ELTS( dest, 2, (i+2), (i+1) );
447	    EMIT_TWO_ELTS( dest, 4, (i+3), (i+2) );
448	    dest += 6;
449	 }
450
451	 CLOSE_ELTS();
452      }
453   }
454   else {
455      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
456   }
457}
458
459
460static void TAG(render_quads_verts)( GLcontext *ctx,
461				     GLuint start,
462				     GLuint count,
463				     GLuint flags )
464{
465   LOCAL_VARS;
466   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
467   count -= (count-start)%4;
468
469   if (start+3 >= count)
470      return;
471
472   if (HAVE_QUADS) {
473      EMIT_PRIM( ctx, HW_QUADS, GL_QUADS, start, count );
474   }
475   else {
476      /* Hardware doesn't have a quad primitive type -- simulate it
477       * using indexed vertices and the triangle primitive:
478       */
479      LOCAL_VARS;
480      int dmasz = GET_MAX_HW_ELTS();
481      GLuint j, nr;
482
483      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
484
485      /* Adjust for rendering as triangles:
486       */
487      dmasz = (dmasz/6)*4;
488
489      for (j = start; j < count; j += nr ) {
490	 ELT_TYPE *dest;
491	 GLint quads, i;
492
493	 nr = MIN2( dmasz, count - j );
494	 quads = nr/4;
495	 dest = ALLOC_ELTS( quads*6 );
496
497	 for ( i = j ; i < j+quads*4 ; i+=4 ) {
498	    EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
499	    EMIT_TWO_ELTS( dest, 2, (i+3), (i+1) );
500	    EMIT_TWO_ELTS( dest, 4, (i+2), (i+3) );
501	    dest += 6;
502	 }
503
504	 CLOSE_ELTS();
505      }
506   }
507}
508
509static void TAG(render_noop)( GLcontext *ctx,
510			      GLuint start,
511			      GLuint count,
512			      GLuint flags )
513{
514}
515
516
517
518
519static render_func TAG(render_tab_verts)[GL_POLYGON+2] =
520{
521   TAG(render_points_verts),
522   TAG(render_lines_verts),
523   TAG(render_line_loop_verts),
524   TAG(render_line_strip_verts),
525   TAG(render_triangles_verts),
526   TAG(render_tri_strip_verts),
527   TAG(render_tri_fan_verts),
528   TAG(render_quads_verts),
529   TAG(render_quad_strip_verts),
530   TAG(render_poly_verts),
531   TAG(render_noop),
532};
533
534
535/****************************************************************************
536 *                 Render elts using hardware indexed verts                 *
537 ****************************************************************************/
538
539static void TAG(render_points_elts)( GLcontext *ctx,
540				     GLuint start,
541				     GLuint count,
542				     GLuint flags )
543{
544   LOCAL_VARS;
545   int dmasz = GET_MAX_HW_ELTS();
546   GLuint *elts = GET_MESA_ELTS();
547   GLuint j, nr;
548   ELT_TYPE *dest;
549
550   ELT_INIT( GL_POINTS, HW_POINTS );
551
552   for (j = start; j < count; j += nr ) {
553      nr = MIN2( dmasz, count - j );
554      dest = ALLOC_ELTS( nr );
555      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
556      CLOSE_ELTS();
557   }
558}
559
560
561
562static void TAG(render_lines_elts)( GLcontext *ctx,
563				    GLuint start,
564				    GLuint count,
565				    GLuint flags )
566{
567   LOCAL_VARS;
568   int dmasz = GET_MAX_HW_ELTS();
569   GLuint *elts = GET_MESA_ELTS();
570   GLuint j, nr;
571   ELT_TYPE *dest;
572
573   if (start+1 >= count)
574      return;
575
576   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
577      RESET_STIPPLE();
578      AUTO_STIPPLE( GL_TRUE );
579   }
580
581   ELT_INIT( GL_LINES, HW_LINES );
582
583   /* Emit whole number of lines in total and in each buffer:
584    */
585   count -= (count-start) & 1;
586   dmasz -= dmasz & 1;
587
588   for (j = start; j < count; j += nr ) {
589      nr = MIN2( dmasz, count - j );
590      dest = ALLOC_ELTS( nr );
591      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
592      CLOSE_ELTS();
593   }
594
595   if ((flags & PRIM_END) && ctx->Line.StippleFlag)
596      AUTO_STIPPLE( GL_FALSE );
597}
598
599
600static void TAG(render_line_strip_elts)( GLcontext *ctx,
601					 GLuint start,
602					 GLuint count,
603					 GLuint flags )
604{
605   LOCAL_VARS;
606   int dmasz = GET_MAX_HW_ELTS();
607   GLuint *elts = GET_MESA_ELTS();
608   GLuint j, nr;
609   ELT_TYPE *dest;
610
611   if (start+1 >= count)
612      return;
613
614   ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
615
616   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
617      RESET_STIPPLE();
618
619   for (j = start; j + 1 < count; j += nr - 1 ) {
620      nr = MIN2( dmasz, count - j );
621      dest = ALLOC_ELTS( nr );
622      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
623      CLOSE_ELTS();
624   }
625}
626
627
628static void TAG(render_line_loop_elts)( GLcontext *ctx,
629					GLuint start,
630					GLuint count,
631					GLuint flags )
632{
633   LOCAL_VARS;
634   int dmasz = GET_MAX_HW_ELTS();
635   GLuint *elts = GET_MESA_ELTS();
636   GLuint j, nr;
637   ELT_TYPE *dest;
638
639   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
640
641   if (flags & PRIM_BEGIN)
642      j = start;
643   else
644      j = start + 1;
645
646
647   if (flags & PRIM_END) {
648      if (start+1 >= count)
649	 return;
650   }
651   else {
652      if (j+1 >= count)
653	 return;
654   }
655
656   ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
657
658   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
659      RESET_STIPPLE();
660
661
662   /* Ensure last vertex doesn't wrap:
663    */
664   dmasz--;
665
666   for ( ; j + 1 < count; ) {
667      nr = MIN2( dmasz, count - j );
668      dest = ALLOC_ELTS( nr+1 );	/* Reserve possible space for last elt */
669      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
670      j += nr - 1;
671      if (j + 1 >= count && (flags & PRIM_END)) {
672	 dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
673      }
674      CLOSE_ELTS();
675   }
676}
677
678
679static void TAG(render_triangles_elts)( GLcontext *ctx,
680					GLuint start,
681					GLuint count,
682					GLuint flags )
683{
684   LOCAL_VARS;
685   GLuint *elts = GET_MESA_ELTS();
686   int dmasz = GET_MAX_HW_ELTS()/3*3;
687   GLuint j, nr;
688   ELT_TYPE *dest;
689
690   if (start+2 >= count)
691      return;
692
693   ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
694
695
696   /* Emit whole number of tris in total.  dmasz is already a multiple
697    * of 3.
698    */
699   count -= (count-start)%3;
700
701   for (j = start; j < count; j += nr) {
702      nr = MIN2( dmasz, count - j );
703      dest = ALLOC_ELTS( nr );
704      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
705      CLOSE_ELTS();
706   }
707}
708
709
710
711static void TAG(render_tri_strip_elts)( GLcontext *ctx,
712					GLuint start,
713					GLuint count,
714					GLuint flags )
715{
716   LOCAL_VARS;
717   GLuint j, nr;
718   GLuint *elts = GET_MESA_ELTS();
719   int dmasz = GET_MAX_HW_ELTS();
720   ELT_TYPE *dest;
721
722   if (start+2 >= count)
723      return;
724
725   ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
726
727   /* Keep the same winding over multiple buffers:
728    */
729   dmasz -= (dmasz & 1);
730
731   for (j = start ; j + 2 < count; j += nr - 2 ) {
732      nr = MIN2( dmasz, count - j );
733
734      dest = ALLOC_ELTS( nr );
735      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
736      CLOSE_ELTS();
737   }
738}
739
740static void TAG(render_tri_fan_elts)( GLcontext *ctx,
741				      GLuint start,
742				      GLuint count,
743				      GLuint flags )
744{
745   LOCAL_VARS;
746   GLuint *elts = GET_MESA_ELTS();
747   GLuint j, nr;
748   int dmasz = GET_MAX_HW_ELTS();
749   ELT_TYPE *dest;
750
751   if (start+2 >= count)
752      return;
753
754   ELT_INIT( GL_TRIANGLE_FAN, HW_TRIANGLE_FAN );
755
756   for (j = start + 1 ; j + 1 < count; j += nr - 1 ) {
757      nr = MIN2( dmasz, count - j + 1 );
758      dest = ALLOC_ELTS( nr );
759      dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
760      dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 );
761      CLOSE_ELTS();
762   }
763}
764
765
766static void TAG(render_poly_elts)( GLcontext *ctx,
767				   GLuint start,
768				   GLuint count,
769				   GLuint flags )
770{
771   LOCAL_VARS;
772   GLuint *elts = GET_MESA_ELTS();
773   GLuint j, nr;
774   int dmasz = GET_MAX_HW_ELTS();
775   ELT_TYPE *dest;
776
777   if (start+2 >= count)
778      return;
779
780   ELT_INIT( GL_POLYGON, HW_POLYGON );
781
782   for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) {
783      nr = MIN2( dmasz, count - j + 1 );
784      dest = ALLOC_ELTS( nr );
785      dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
786      dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 );
787      CLOSE_ELTS();
788   }
789}
790
791static void TAG(render_quad_strip_elts)( GLcontext *ctx,
792					 GLuint start,
793					 GLuint count,
794					 GLuint flags )
795{
796   if (start+3 >= count)
797      return;
798
799   if (HAVE_QUAD_STRIPS && 0) {
800   }
801   else {
802      LOCAL_VARS;
803      GLuint *elts = GET_MESA_ELTS();
804      int dmasz = GET_MAX_HW_ELTS();
805      GLuint j, nr;
806      ELT_TYPE *dest;
807
808      /* Emit whole number of quads in total, and in each buffer.
809       */
810      dmasz -= dmasz & 1;
811      count -= (count-start) & 1;
812
813      if (ctx->_TriangleCaps & DD_FLATSHADE) {
814	 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
815
816	 dmasz = dmasz/6*2;
817
818	 for (j = start; j + 3 < count; j += nr - 2 ) {
819	    nr = MIN2( dmasz, count - j );
820
821	    if (nr >= 4)
822	    {
823	       GLint quads = (nr/2)-1;
824	       ELT_TYPE *dest = ALLOC_ELTS( quads*6 );
825	       GLint i;
826
827	       for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) {
828		  EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
829		  EMIT_TWO_ELTS( dest, 2, elts[2], elts[1] );
830		  EMIT_TWO_ELTS( dest, 4, elts[3], elts[2] );
831		  dest += 6;
832	       }
833
834	       CLOSE_ELTS();
835	    }
836	 }
837      }
838      else {
839	 ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
840
841	 for (j = start; j + 3 < count; j += nr - 2 ) {
842	    nr = MIN2( dmasz, count - j );
843	    dest = ALLOC_ELTS( nr );
844	    dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
845	    CLOSE_ELTS();
846	 }
847      }
848   }
849}
850
851
852static void TAG(render_quads_elts)( GLcontext *ctx,
853				    GLuint start,
854				    GLuint count,
855				    GLuint flags )
856{
857   if (start+3 >= count)
858      return;
859
860   if (HAVE_QUADS && 0) {
861   } else {
862      LOCAL_VARS;
863      GLuint *elts = GET_MESA_ELTS();
864      int dmasz = GET_MAX_HW_ELTS();
865      GLuint j, nr;
866
867      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
868
869      /* Emit whole number of quads in total, and in each buffer.
870       */
871      dmasz -= dmasz & 3;
872      count -= (count-start) & 3;
873
874      /* Adjust for rendering as triangles:
875       */
876      dmasz = dmasz/6*4;
877
878      for (j = start; j + 3 < count; j += nr ) {
879	 nr = MIN2( dmasz, count - j );
880
881	 {
882	    GLint quads = nr/4;
883	    ELT_TYPE *dest = ALLOC_ELTS( quads * 6 );
884	    GLint i;
885
886	    for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) {
887	       EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
888	       EMIT_TWO_ELTS( dest, 2, elts[3], elts[1] );
889	       EMIT_TWO_ELTS( dest, 4, elts[2], elts[3] );
890	       dest += 6;
891	    }
892
893	    CLOSE_ELTS();
894	 }
895      }
896   }
897}
898
899
900
901static render_func TAG(render_tab_elts)[GL_POLYGON+2] =
902{
903   TAG(render_points_elts),
904   TAG(render_lines_elts),
905   TAG(render_line_loop_elts),
906   TAG(render_line_strip_elts),
907   TAG(render_triangles_elts),
908   TAG(render_tri_strip_elts),
909   TAG(render_tri_fan_elts),
910   TAG(render_quads_elts),
911   TAG(render_quad_strip_elts),
912   TAG(render_poly_elts),
913   TAG(render_noop),
914};
915