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 <keithw@vmware.com>
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
TAG(emit_elts)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
TAG(emit_consecutive_elts)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
TAG(render_points_verts)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
TAG(render_lines_verts)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
TAG(render_line_strip_verts)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
TAG(render_line_loop_verts)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
TAG(render_triangles_verts)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
TAG(render_tri_strip_verts)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
TAG(render_tri_fan_verts)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
TAG(render_poly_verts)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
TAG(render_quad_strip_verts)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
TAG(render_quads_verts)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
TAG(render_noop)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
TAG(render_points_elts)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
TAG(render_lines_elts)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
TAG(render_line_strip_elts)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
TAG(render_line_loop_elts)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
TAG(render_triangles_elts)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
TAG(render_tri_strip_elts)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
TAG(render_tri_fan_elts)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
TAG(render_poly_elts)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
TAG(render_quad_strip_elts)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
TAG(render_quads_elts)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 };
927