Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
58 pj 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( offset, elt0, elt1 )     \
60
do {                                            \
61
   EMIT_ELT( offset, elt0 );                    \
62
   EMIT_ELT( offset+1, elt1 );                  \
63
} while (0)
64
#endif
65
 
66
 
67
/**********************************************************************/
68
/*                  Render whole begin/end objects                    */
69
/**********************************************************************/
70
 
71
 
72
static void TAG(emit_elts)( GLcontext *ctx, GLuint *elts, GLuint nr )
73
{
74
   GLint i;
75
   LOCAL_VARS;
76
   ELTS_VARS;
77
 
78
   ALLOC_ELTS( nr );
79
 
80
   for ( i = 0 ; i < nr ; i+=2, elts += 2 ) {
81
      EMIT_TWO_ELTS( 0, elts[0], elts[1] );
82
      INCR_ELTS( 2 );
83
   }
84
}
85
 
86
static void TAG(emit_consecutive_elts)( GLcontext *ctx, GLuint start, GLuint nr )
87
{
88
   GLint i;
89
   LOCAL_VARS;
90
   ELTS_VARS;
91
 
92
   ALLOC_ELTS( nr );
93
 
94
   for ( i = 0 ; i+1 < nr ; i+=2, start += 2 ) {
95
      EMIT_TWO_ELTS( 0, start, start+1 );
96
      INCR_ELTS( 2 );
97
   }
98
   if (i < nr) {
99
      EMIT_ELT( 0, start );
100
      INCR_ELTS( 1 );
101
   }
102
}
103
 
104
/***********************************************************************
105
 *                    Render non-indexed primitives.
106
 ***********************************************************************/
107
 
108
 
109
 
110
static void TAG(render_points_verts)( GLcontext *ctx,
111
                                      GLuint start,
112
                                      GLuint count,
113
                                      GLuint flags )
114
{
115
   if (start < count) {
116
      LOCAL_VARS;
117
      if (0) fprintf(stderr, "%s\n", __FUNCTION__);
118
      EMIT_PRIM( ctx, GL_POINTS, HW_POINTS, start, count );
119
   }
120
}
121
 
122
static void TAG(render_lines_verts)( GLcontext *ctx,
123
                                     GLuint start,
124
                                     GLuint count,
125
                                     GLuint flags )
126
{
127
   LOCAL_VARS;
128
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
129
   count -= (count-start) & 1;
130
 
131
   if (start+1 >= count)
132
      return;
133
 
134
   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
135
      RESET_STIPPLE();
136
      AUTO_STIPPLE( GL_TRUE );
137
   }
138
 
139
   EMIT_PRIM( ctx, GL_LINES, HW_LINES, start, count );
140
 
141
   if ((flags & PRIM_END) && ctx->Line.StippleFlag)
142
      AUTO_STIPPLE( GL_FALSE );
143
}
144
 
145
 
146
static void TAG(render_line_strip_verts)( GLcontext *ctx,
147
                                          GLuint start,
148
                                          GLuint count,
149
                                          GLuint flags )
150
{
151
   LOCAL_VARS;
152
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
153
 
154
   if (start+1 >= count)
155
      return;
156
 
157
   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
158
      RESET_STIPPLE();
159
 
160
 
161
   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES ))
162
   {  
163
      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
164
      int currentsz;
165
      GLuint j, nr;
166
 
167
      ELT_INIT( GL_LINES, HW_LINES );
168
 
169
      /* Emit whole number of lines in each full buffer.
170
       */
171
      dmasz = dmasz/2;
172
      currentsz = GET_CURRENT_VB_MAX_ELTS();
173
      currentsz = currentsz/2;
174
 
175
      if (currentsz < 4) {
176
         NEW_BUFFER();
177
         currentsz = dmasz;
178
      }
179
 
180
      for (j = start; j + 1 < count; j += nr - 1 ) {
181
         GLint i;
182
         ELTS_VARS;
183
         nr = MIN2( currentsz, count - j );
184
 
185
         ALLOC_ELTS( (nr-1)*2 );
186
 
187
         for ( i = j ; i+1 < j+nr ; i+=1 ) {
188
            EMIT_TWO_ELTS( 0, (i+0), (i+1) );
189
            INCR_ELTS( 2 );
190
         }
191
 
192
         if (nr == currentsz) {
193
            NEW_BUFFER();
194
            currentsz = dmasz;
195
         }
196
      }
197
   }
198
   else
199
      EMIT_PRIM( ctx, GL_LINE_STRIP, HW_LINE_STRIP, start, count );
200
}
201
 
202
 
203
static void TAG(render_line_loop_verts)( GLcontext *ctx,
204
                                         GLuint start,
205
                                         GLuint count,
206
                                         GLuint flags )
207
{
208
   LOCAL_VARS;
209
   GLuint j, nr;
210
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
211
 
212
   if (flags & PRIM_BEGIN) {
213
      j = start;
214
      if (ctx->Line.StippleFlag)
215
         RESET_STIPPLE( );
216
   }
217
   else
218
      j = start + 1;
219
 
220
   if (flags & PRIM_END) {
221
 
222
      if (start+1 >= count)
223
         return;
224
 
225
      if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) {
226
         int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
227
         int currentsz;
228
 
229
         ELT_INIT( GL_LINES, HW_LINES );
230
 
231
         /* Emit whole number of lines in each full buffer.
232
          */
233
         dmasz = dmasz/2;
234
         currentsz = GET_CURRENT_VB_MAX_ELTS();
235
         currentsz = currentsz/2;
236
 
237
         if (currentsz < 4) {
238
            NEW_BUFFER();
239
            currentsz = dmasz;
240
         }
241
 
242
         /* Ensure last vertex doesn't wrap:
243
          */
244
         currentsz--;
245
         dmasz--;
246
 
247
         for (; j + 1 < count;  ) {
248
            GLint i;
249
            ELTS_VARS;
250
            nr = MIN2( currentsz, count - j );
251
 
252
            ALLOC_ELTS( (nr-1)*2 );        
253
            for ( i = j ; i+1 < j+nr ; i+=1 ) {
254
               EMIT_TWO_ELTS( 0, (i+0), (i+1) );
255
               INCR_ELTS( 2 );
256
            }
257
 
258
            j += nr - 1;
259
            if (j + 1 < count) {
260
               NEW_BUFFER();
261
               currentsz = dmasz;
262
            }
263
            else {
264
               ALLOC_ELTS( 2 );
265
               EMIT_TWO_ELTS( 0, (j), (start) );
266
               INCR_ELTS( 2 );
267
            }
268
         }
269
      }
270
      else
271
      {
272
         int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
273
         int currentsz;
274
 
275
         ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
276
 
277
         currentsz = GET_CURRENT_VB_MAX_ELTS();
278
 
279
         if (currentsz < 8) {
280
            NEW_BUFFER();
281
            currentsz = dmasz;
282
         }
283
 
284
         /* Ensure last vertex doesn't wrap:
285
          */
286
         currentsz--;
287
         dmasz--;
288
 
289
         for ( ; j + 1 < count;  ) {
290
            nr = MIN2( currentsz, count - j );
291
            if (j + nr < count) {
292
               TAG(emit_consecutive_elts)( ctx, j, nr );
293
               currentsz = dmasz;
294
               j += nr - 1;
295
               NEW_BUFFER();
296
            }
297
            else if (nr) {
298
               ELTS_VARS;
299
               int i;
300
 
301
               ALLOC_ELTS( nr + 1 );
302
               for ( i = 0 ; i+1 < nr ; i+=2, j += 2 ) {
303
                  EMIT_TWO_ELTS( 0, j, j+1 );
304
                  INCR_ELTS( 2 );
305
               }
306
               if (i < nr) {
307
                  EMIT_ELT( 0, j ); j++;
308
                  INCR_ELTS( 1 );
309
               }
310
               EMIT_ELT( 0, start );
311
               INCR_ELTS( 1 );
312
               NEW_BUFFER();
313
            }
314
            else {
315
               fprintf(stderr, "warining nr==0\n");
316
            }
317
         }  
318
      }
319
   } else {
320
      TAG(render_line_strip_verts)( ctx, j, count, flags );
321
   }
322
}
323
 
324
 
325
static void TAG(render_triangles_verts)( GLcontext *ctx,
326
                                         GLuint start,
327
                                         GLuint count,
328
                                         GLuint flags )
329
{
330
   LOCAL_VARS;
331
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
332
 
333
   count -= (count-start)%3;
334
 
335
   if (start+2 >= count) {
336
      return;
337
   }
338
 
339
   /* need a PREFER_DISCRETE_ELT_PRIM here too..
340
    */
341
   EMIT_PRIM( ctx, GL_TRIANGLES, HW_TRIANGLES, start, count );
342
}
343
 
344
 
345
 
346
static void TAG(render_tri_strip_verts)( GLcontext *ctx,
347
                                         GLuint start,
348
                                         GLuint count,
349
                                         GLuint flags )
350
{
351
   LOCAL_VARS;
352
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
353
 
354
   if (start + 2 >= count)
355
      return;
356
 
357
   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
358
   {  
359
      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
360
      int currentsz;
361
      int parity = 0;
362
      GLuint j, nr;
363
 
364
      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
365
 
366
      if (flags & PRIM_PARITY)
367
         parity = 1;
368
 
369
      /* Emit even number of tris in each full buffer.
370
       */
371
      dmasz = dmasz/3;
372
      dmasz -= dmasz & 1;
373
      currentsz = GET_CURRENT_VB_MAX_ELTS();
374
      currentsz = currentsz/3;
375
      currentsz -= currentsz & 1;
376
 
377
      if (currentsz < 4) {
378
         NEW_BUFFER();
379
         currentsz = dmasz;
380
      }
381
 
382
      for (j = start; j + 2 < count; j += nr - 2 ) {
383
         GLint i;
384
         ELTS_VARS;
385
         nr = MIN2( currentsz, count - j );
386
 
387
         ALLOC_ELTS( (nr-2)*3 );
388
 
389
         for ( i = j ; i+2 < j+nr ; i++, parity^=1 ) {
390
            EMIT_ELT( 0, (i+0+parity) );
391
            EMIT_ELT( 1, (i+1-parity) );
392
            EMIT_ELT( 2, (i+2) );
393
            INCR_ELTS( 3 );
394
         }
395
 
396
         if (nr == currentsz) {
397
            NEW_BUFFER();
398
            currentsz = dmasz;
399
         }
400
      }
401
   }
402
   else if ((flags & PRIM_PARITY) == 0)  
403
      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
404
   else if (HAVE_TRI_STRIP_1)
405
      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_1, start, count );
406
   else {
407
      /* Emit the first triangle with elts, then the rest as a regular strip.
408
       * TODO:  Make this unlikely in t_imm_api.c
409
       */
410
      ELTS_VARS;
411
      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
412
      ALLOC_ELTS( 3 );
413
      EMIT_ELT( 0, (start+1) );
414
      EMIT_ELT( 1, (start+0) );
415
      EMIT_ELT( 2, (start+2) );
416
      INCR_ELTS( 3 );
417
      NEW_PRIMITIVE();
418
 
419
      start++;
420
      if (start + 2 >= count)
421
         return;
422
 
423
      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start,
424
                 count );
425
   }
426
}
427
 
428
static void TAG(render_tri_fan_verts)( GLcontext *ctx,
429
                                       GLuint start,
430
                                       GLuint count,
431
                                       GLuint flags )
432
{
433
   LOCAL_VARS;
434
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
435
 
436
   if (start+2 >= count)
437
      return;
438
 
439
   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
440
   {  
441
      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
442
      int currentsz;
443
      GLuint j, nr;
444
 
445
      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
446
 
447
      dmasz = dmasz/3;
448
      currentsz = GET_CURRENT_VB_MAX_ELTS();
449
      currentsz = currentsz/3;
450
 
451
      if (currentsz < 4) {
452
         NEW_BUFFER();
453
         currentsz = dmasz;
454
      }
455
 
456
      for (j = start + 1; j + 1 < count; j += nr - 1 ) {
457
         GLint i;
458
         ELTS_VARS;
459
         nr = MIN2( currentsz, count - j );
460
 
461
         ALLOC_ELTS( (nr-1)*3 );
462
 
463
         for ( i = j ; i+1 < j+nr ; i++ ) {
464
            EMIT_ELT( 0, (start) );
465
            EMIT_ELT( 1, (i) );
466
            EMIT_ELT( 2, (i+1) );
467
            INCR_ELTS( 3 );
468
         }
469
 
470
         if (nr == currentsz) {
471
            NEW_BUFFER();
472
            currentsz = dmasz;
473
         }
474
      }
475
   }
476
   else {
477
      EMIT_PRIM( ctx, GL_TRIANGLE_FAN, HW_TRIANGLE_FAN, start, count );
478
   }
479
}
480
 
481
 
482
static void TAG(render_poly_verts)( GLcontext *ctx,
483
                                    GLuint start,
484
                                    GLuint count,
485
                                    GLuint flags )
486
{
487
   LOCAL_VARS;
488
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
489
 
490
   if (start+2 >= count)
491
      return;
492
 
493
   EMIT_PRIM( ctx, GL_POLYGON, HW_POLYGON, start, count );
494
}
495
 
496
static void TAG(render_quad_strip_verts)( GLcontext *ctx,
497
                                          GLuint start,
498
                                          GLuint count,
499
                                          GLuint flags )
500
{
501
   LOCAL_VARS;
502
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
503
 
504
   count -= (count-start) & 1;
505
 
506
   if (start+3 >= count)
507
      return;
508
 
509
   if (HAVE_QUAD_STRIPS) {
510
      EMIT_PRIM( ctx, GL_QUAD_STRIP, HW_QUAD_STRIP, start, count );
511
   }
512
   else if (ctx->_TriangleCaps & DD_FLATSHADE) {
513
      LOCAL_VARS;
514
      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
515
      int currentsz;
516
      GLuint j, nr;
517
 
518
      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
519
 
520
      currentsz = GET_CURRENT_VB_MAX_ELTS();
521
 
522
      /* Emit whole number of quads in total, and in each buffer.
523
       */
524
      currentsz = (currentsz/6)*2;
525
      dmasz = (dmasz/6)*2;
526
 
527
      if (currentsz < 4) {
528
         NEW_BUFFER();
529
         currentsz = dmasz;
530
      }
531
 
532
      for (j = start; j + 3 < count; j += nr - 2 ) {
533
         ELTS_VARS;
534
         GLint quads, i;
535
 
536
         nr = MIN2( currentsz, count - j );
537
         quads = (nr/2)-1;
538
 
539
         ALLOC_ELTS( quads*6 );
540
 
541
         for ( i = j ; i < j+quads*2 ; i+=2 ) {
542
            EMIT_TWO_ELTS( 0, (i+0), (i+1) );
543
            EMIT_TWO_ELTS( 2, (i+2), (i+1) );
544
            EMIT_TWO_ELTS( 4, (i+3), (i+2) );
545
            INCR_ELTS( 6 );
546
         }
547
 
548
         if (nr == currentsz) {
549
            NEW_BUFFER();
550
            currentsz = dmasz;
551
         }
552
      }
553
   }
554
   else {
555
      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
556
   }
557
}
558
 
559
 
560
static void TAG(render_quads_verts)( GLcontext *ctx,
561
                                     GLuint start,
562
                                     GLuint count,
563
                                     GLuint flags )
564
{
565
   LOCAL_VARS;
566
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
567
   count -= (count-start)%4;
568
 
569
   if (start+3 >= count)
570
      return;
571
 
572
   if (HAVE_QUADS) {
573
      EMIT_PRIM( ctx, HW_QUADS, GL_QUADS, start, count );
574
   }
575
   else {
576
      /* Hardware doesn't have a quad primitive type -- simulate it
577
       * using indexed vertices and the triangle primitive:
578
       */
579
      LOCAL_VARS;
580
      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
581
      int currentsz;
582
      GLuint j, nr;
583
 
584
      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
585
      currentsz = GET_CURRENT_VB_MAX_ELTS();
586
 
587
      /* Adjust for rendering as triangles:
588
       */
589
      currentsz = (currentsz/6)*4;
590
      dmasz = (dmasz/6)*4;
591
 
592
      if (currentsz < 8) {
593
         NEW_BUFFER();
594
         currentsz = dmasz;
595
      }
596
 
597
      for (j = start; j < count; j += nr ) {
598
         ELTS_VARS;
599
         GLint quads, i;
600
         nr = MIN2( currentsz, count - j );
601
         quads = nr/4;
602
 
603
         ALLOC_ELTS( quads*6 );
604
 
605
         for ( i = j ; i < j+quads*4 ; i+=4 ) {
606
            EMIT_TWO_ELTS( 0, (i+0), (i+1) );
607
            EMIT_TWO_ELTS( 2, (i+3), (i+1) );
608
            EMIT_TWO_ELTS( 4, (i+2), (i+3) );
609
            INCR_ELTS( 6 );
610
         }
611
 
612
         if (nr == currentsz) {
613
            NEW_BUFFER();
614
            currentsz = dmasz;
615
         }
616
      }
617
   }
618
}
619
 
620
static void TAG(render_noop)( GLcontext *ctx,
621
                              GLuint start,
622
                              GLuint count,
623
                              GLuint flags )
624
{
625
}
626
 
627
 
628
 
629
 
630
static render_func TAG(render_tab_verts)[GL_POLYGON+2] =
631
{
632
   TAG(render_points_verts),
633
   TAG(render_lines_verts),
634
   TAG(render_line_loop_verts),
635
   TAG(render_line_strip_verts),
636
   TAG(render_triangles_verts),
637
   TAG(render_tri_strip_verts),
638
   TAG(render_tri_fan_verts),
639
   TAG(render_quads_verts),
640
   TAG(render_quad_strip_verts),
641
   TAG(render_poly_verts),
642
   TAG(render_noop),
643
};
644
 
645
 
646
/****************************************************************************
647
 *                 Render elts using hardware indexed verts                 *
648
 ****************************************************************************/
649
 
650
static void TAG(render_points_elts)( GLcontext *ctx,
651
                                     GLuint start,
652
                                     GLuint count,
653
                                     GLuint flags )
654
{
655
   LOCAL_VARS;
656
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
657
   int currentsz;
658
   GLuint *elts = GET_ELTS();
659
   GLuint j, nr;
660
 
661
   ELT_INIT( GL_POINTS, HW_POINTS );
662
 
663
   currentsz = GET_CURRENT_VB_MAX_ELTS();
664
   if (currentsz < 8)
665
      currentsz = dmasz;
666
 
667
   for (j = start; j < count; j += nr ) {
668
      nr = MIN2( currentsz, count - j );
669
      TAG(emit_elts)( ctx, elts+j, nr );
670
      NEW_PRIMITIVE();
671
      currentsz = dmasz;
672
   }
673
}
674
 
675
 
676
 
677
static void TAG(render_lines_elts)( GLcontext *ctx,
678
                                    GLuint start,
679
                                    GLuint count,
680
                                    GLuint flags )
681
{
682
   LOCAL_VARS;
683
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
684
   int currentsz;
685
   GLuint *elts = GET_ELTS();
686
   GLuint j, nr;
687
 
688
   if (start+1 >= count)
689
      return;
690
 
691
   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
692
      RESET_STIPPLE();
693
      AUTO_STIPPLE( GL_TRUE );
694
   }
695
 
696
   ELT_INIT( GL_LINES, HW_LINES );
697
 
698
   /* Emit whole number of lines in total and in each buffer:
699
    */
700
   count -= (count-start) & 1;
701
   currentsz -= currentsz & 1;
702
   dmasz -= dmasz & 1;
703
 
704
   currentsz = GET_CURRENT_VB_MAX_ELTS();
705
   if (currentsz < 8)
706
      currentsz = dmasz;
707
 
708
   for (j = start; j < count; j += nr ) {
709
      nr = MIN2( currentsz, count - j );
710
      TAG(emit_elts)( ctx, elts+j, nr );
711
      NEW_PRIMITIVE();
712
      currentsz = dmasz;
713
   }
714
 
715
   if ((flags & PRIM_END) && ctx->Line.StippleFlag)
716
      AUTO_STIPPLE( GL_FALSE );
717
}
718
 
719
 
720
static void TAG(render_line_strip_elts)( GLcontext *ctx,
721
                                         GLuint start,
722
                                         GLuint count,
723
                                         GLuint flags )
724
{
725
   LOCAL_VARS;
726
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
727
   int currentsz;
728
   GLuint *elts = GET_ELTS();
729
   GLuint j, nr;
730
 
731
   if (start+1 >= count)
732
      return;
733
 
734
   ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
735
 
736
   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
737
      RESET_STIPPLE();
738
 
739
   currentsz = GET_CURRENT_VB_MAX_ELTS();
740
   if (currentsz < 8)
741
      currentsz = dmasz;
742
 
743
   for (j = start; j + 1 < count; j += nr - 1 ) {
744
      nr = MIN2( currentsz, count - j );
745
      TAG(emit_elts)( ctx, elts+j, nr );
746
      NEW_PRIMITIVE();
747
      currentsz = dmasz;
748
   }
749
}
750
 
751
 
752
static void TAG(render_line_loop_elts)( GLcontext *ctx,
753
                                        GLuint start,
754
                                        GLuint count,
755
                                        GLuint flags )
756
{
757
   LOCAL_VARS;
758
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
759
   int currentsz;
760
   GLuint *elts = GET_ELTS();
761
   GLuint j, nr;
762
 
763
   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
764
 
765
   if (flags & PRIM_BEGIN)
766
      j = start;
767
   else
768
      j = start + 1;
769
 
770
 
771
   if (flags & PRIM_END) {
772
      if (start+1 >= count)
773
         return;
774
   }
775
   else {
776
      if (j+1 >= count)
777
         return;
778
   }
779
 
780
   ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
781
 
782
   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
783
      RESET_STIPPLE();
784
 
785
 
786
   currentsz = GET_CURRENT_VB_MAX_ELTS();
787
   if (currentsz < 8) {
788
      NEW_BUFFER();
789
      currentsz = dmasz;
790
   }
791
 
792
   /* Ensure last vertex doesn't wrap:
793
    */
794
   currentsz--;
795
   dmasz--;
796
 
797
   for ( ; j + 1 < count; j += nr - 1 ) {
798
      nr = MIN2( currentsz, count - j );
799
      TAG(emit_elts)( ctx, elts+j, nr );
800
      currentsz = dmasz;
801
   }
802
 
803
   if (flags & PRIM_END)
804
      TAG(emit_elts)( ctx, elts+start, 1 );
805
 
806
   NEW_PRIMITIVE();
807
}
808
 
809
 
810
static void TAG(render_triangles_elts)( GLcontext *ctx,
811
                                        GLuint start,
812
                                        GLuint count,
813
                                        GLuint flags )
814
{
815
   LOCAL_VARS;
816
   GLuint *elts = GET_ELTS();
817
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
818
   int currentsz;
819
   GLuint j, nr;
820
 
821
   if (start+2 >= count)
822
      return;
823
 
824
/*     NEW_PRIMITIVE(); */
825
   ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
826
 
827
   currentsz = GET_CURRENT_VB_MAX_ELTS();
828
 
829
   /* Emit whole number of tris in total.  dmasz is already a multiple
830
    * of 3.
831
    */
832
   count -= (count-start)%3;
833
   currentsz -= currentsz%3;
834
   if (currentsz < 8)
835
      currentsz = dmasz;
836
 
837
   for (j = start; j < count; j += nr) {
838
      nr = MIN2( currentsz, count - j );
839
      TAG(emit_elts)( ctx, elts+j, nr );
840
      NEW_PRIMITIVE();
841
      currentsz = dmasz;
842
   }
843
}
844
 
845
 
846
 
847
static void TAG(render_tri_strip_elts)( GLcontext *ctx,
848
                                        GLuint start,
849
                                        GLuint count,
850
                                        GLuint flags )
851
{
852
   LOCAL_VARS;
853
   GLuint j, nr;
854
   GLuint *elts = GET_ELTS();
855
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
856
   int currentsz;
857
 
858
   if (start+2 >= count)
859
      return;
860
 
861
   ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
862
 
863
   currentsz = GET_CURRENT_VB_MAX_ELTS();
864
   if (currentsz < 8) {
865
      NEW_BUFFER();
866
      currentsz = dmasz;
867
   }
868
 
869
   if ((flags & PRIM_PARITY) && count - start > 2) {
870
      TAG(emit_elts)( ctx, elts+start, 1 );
871
      currentsz--;
872
   }
873
 
874
   /* Keep the same winding over multiple buffers:
875
    */
876
   dmasz -= (dmasz & 1);
877
   currentsz -= (currentsz & 1);
878
 
879
   for (j = start ; j + 2 < count; j += nr - 2 ) {
880
      nr = MIN2( currentsz, count - j );
881
      TAG(emit_elts)( ctx, elts+j, nr );
882
      NEW_PRIMITIVE();
883
      currentsz = dmasz;
884
   }
885
}
886
 
887
static void TAG(render_tri_fan_elts)( GLcontext *ctx,
888
                                      GLuint start,
889
                                      GLuint count,
890
                                      GLuint flags )
891
{
892
   LOCAL_VARS;
893
   GLuint *elts = GET_ELTS();
894
   GLuint j, nr;
895
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
896
   int currentsz;
897
 
898
   if (start+2 >= count)
899
      return;
900
 
901
   ELT_INIT( GL_TRIANGLE_FAN, HW_TRIANGLE_FAN );
902
 
903
   currentsz = GET_CURRENT_VB_MAX_ELTS();
904
   if (currentsz < 8) {
905
      NEW_BUFFER();
906
      currentsz = dmasz;
907
   }
908
 
909
   for (j = start + 1 ; j + 1 < count; j += nr - 1 ) {
910
      nr = MIN2( currentsz, count - j + 1 );
911
      TAG(emit_elts)( ctx, elts+start, 1 );
912
      TAG(emit_elts)( ctx, elts+j, nr - 1 );
913
      NEW_PRIMITIVE();
914
      currentsz = dmasz;
915
   }
916
}
917
 
918
 
919
static void TAG(render_poly_elts)( GLcontext *ctx,
920
                                   GLuint start,
921
                                   GLuint count,
922
                                   GLuint flags )
923
{
924
   LOCAL_VARS;
925
   GLuint *elts = GET_ELTS();
926
   GLuint j, nr;
927
   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
928
   int currentsz;
929
 
930
   if (start+2 >= count)
931
      return;
932
 
933
   ELT_INIT( GL_POLYGON, HW_POLYGON );
934
 
935
   currentsz = GET_CURRENT_VB_MAX_ELTS();
936
   if (currentsz < 8) {
937
      NEW_BUFFER();
938
      currentsz = dmasz;
939
   }
940
 
941
   for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) {
942
      nr = MIN2( currentsz, count - j + 1 );
943
      TAG(emit_elts)( ctx, elts+start, 1 );
944
      TAG(emit_elts)( ctx, elts+j, nr - 1 );
945
      NEW_PRIMITIVE();
946
      currentsz = dmasz;
947
   }
948
}
949
 
950
static void TAG(render_quad_strip_elts)( GLcontext *ctx,
951
                                         GLuint start,
952
                                         GLuint count,
953
                                         GLuint flags )
954
{
955
   if (start+3 >= count)
956
      return;
957
 
958
   if (HAVE_QUAD_STRIPS && 0) {
959
   }
960
   else {
961
      LOCAL_VARS;
962
      GLuint *elts = GET_ELTS();
963
      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
964
      int currentsz;
965
      GLuint j, nr;
966
 
967
      NEW_PRIMITIVE();
968
      currentsz = GET_CURRENT_VB_MAX_ELTS();
969
 
970
      /* Emit whole number of quads in total, and in each buffer.
971
       */
972
      dmasz -= dmasz & 1;
973
      count -= (count-start) & 1;
974
      currentsz -= currentsz & 1;
975
 
976
      if (currentsz < 12)
977
         currentsz = dmasz;
978
 
979
      if (ctx->_TriangleCaps & DD_FLATSHADE) {
980
         ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
981
 
982
         currentsz = currentsz/6*2;
983
         dmasz = dmasz/6*2;
984
 
985
         for (j = start; j + 3 < count; j += nr - 2 ) {
986
            nr = MIN2( currentsz, count - j );
987
 
988
            if (nr >= 4)
989
            {
990
               GLint i;
991
               GLint quads = (nr/2)-1;
992
               ELTS_VARS;
993
 
994
               ALLOC_ELTS( quads*6 );
995
 
996
               for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) {
997
                  EMIT_TWO_ELTS( 0, elts[0], elts[1] );
998
                  EMIT_TWO_ELTS( 2, elts[2], elts[1] );
999
                  EMIT_TWO_ELTS( 4, elts[3], elts[2] );
1000
                  INCR_ELTS( 6 );
1001
               }
1002
 
1003
               NEW_PRIMITIVE();
1004
            }
1005
 
1006
            currentsz = dmasz;
1007
         }
1008
      }
1009
      else {
1010
         ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
1011
 
1012
         for (j = start; j + 3 < count; j += nr - 2 ) {
1013
            nr = MIN2( currentsz, count - j );
1014
            TAG(emit_elts)( ctx, elts+j, nr );
1015
            NEW_PRIMITIVE();
1016
            currentsz = dmasz;
1017
         }
1018
      }
1019
   }
1020
}
1021
 
1022
 
1023
static void TAG(render_quads_elts)( GLcontext *ctx,
1024
                                    GLuint start,
1025
                                    GLuint count,
1026
                                    GLuint flags )
1027
{
1028
   if (start+3 >= count)
1029
      return;
1030
 
1031
   if (HAVE_QUADS && 0) {
1032
   } else {
1033
      LOCAL_VARS;
1034
      GLuint *elts = GET_ELTS();
1035
      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
1036
      int currentsz;
1037
      GLuint j, nr;
1038
 
1039
      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
1040
      currentsz = GET_CURRENT_VB_MAX_ELTS();
1041
 
1042
      /* Emit whole number of quads in total, and in each buffer.
1043
       */
1044
      dmasz -= dmasz & 3;
1045
      count -= (count-start) & 3;
1046
      currentsz -= currentsz & 3;
1047
 
1048
      /* Adjust for rendering as triangles:
1049
       */
1050
      currentsz = currentsz/6*4;
1051
      dmasz = dmasz/6*4;
1052
 
1053
      if (currentsz < 8)
1054
         currentsz = dmasz;
1055
 
1056
      for (j = start; j + 3 < count; j += nr - 2 ) {
1057
         nr = MIN2( currentsz, count - j );
1058
 
1059
         if (nr >= 4)
1060
         {
1061
            GLint quads = nr/4;
1062
            GLint i;
1063
            ELTS_VARS;
1064
            ALLOC_ELTS( quads * 6 );
1065
 
1066
            for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) {
1067
               EMIT_TWO_ELTS( 0, elts[0], elts[1] );
1068
               EMIT_TWO_ELTS( 2, elts[3], elts[1] );
1069
               EMIT_TWO_ELTS( 4, elts[2], elts[3] );
1070
               INCR_ELTS( 6 );
1071
            }
1072
         }
1073
 
1074
         NEW_PRIMITIVE();
1075
         currentsz = dmasz;
1076
      }
1077
   }
1078
}
1079
 
1080
 
1081
 
1082
static render_func TAG(render_tab_elts)[GL_POLYGON+2] =
1083
{
1084
   TAG(render_points_elts),
1085
   TAG(render_lines_elts),
1086
   TAG(render_line_loop_elts),
1087
   TAG(render_line_strip_elts),
1088
   TAG(render_triangles_elts),
1089
   TAG(render_tri_strip_elts),
1090
   TAG(render_tri_fan_elts),
1091
   TAG(render_quads_elts),
1092
   TAG(render_quad_strip_elts),
1093
   TAG(render_poly_elts),
1094
   TAG(render_noop),
1095
};