Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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