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