Removed two unnecessary variables.
[mesa.git] / src / mesa / tnl_dd / t_dd_dmatmp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keith@tungstengraphics.com>
26 */
27
28
29 /* Template for render stages which build and emit vertices directly
30 * to fixed-size dma buffers. Useful for rendering strips and other
31 * native primitives where clipping and per-vertex tweaks such as
32 * those in t_dd_tritmp.h are not required.
33 *
34 * Produces code for both inline triangles and indexed triangles.
35 * Where various primitive types are unaccelerated by hardware, the
36 * code attempts to fallback to other primitive types (quadstrips to
37 * tristrips, lineloops to linestrips), or to indexed vertices.
38 * Ultimately, a FALLBACK() macro is invoked if there is no way to
39 * render the primitive natively.
40 */
41
42 #if !defined(HAVE_TRIANGLES)
43 #error "must have at least triangles to use render template"
44 #endif
45
46 #if !HAVE_ELTS
47 #define ELTS_VARS(buf)
48 #define ALLOC_ELTS(nr) 0
49 #define EMIT_ELT( offset, elt )
50 #define EMIT_TWO_ELTS( offset, elt0, elt1 )
51 #define INCR_ELTS( nr )
52 #define ELT_INIT(prim)
53 #define GET_CURRENT_VB_MAX_ELTS() 0
54 #define GET_SUBSEQUENT_VB_MAX_ELTS() 0
55 #define RELEASE_ELT_VERTS()
56 #define EMIT_INDEXED_VERTS( ctx, start, count )
57 #endif
58
59 #ifndef EMIT_TWO_ELTS
60 #define EMIT_TWO_ELTS( offset, elt0, elt1 ) \
61 do { \
62 EMIT_ELT( offset, elt0 ); \
63 EMIT_ELT( offset+1, elt1 ); \
64 } while (0)
65 #endif
66
67
68 /**********************************************************************/
69 /* Render whole begin/end objects */
70 /**********************************************************************/
71
72
73
74
75 #if (HAVE_ELTS)
76 static void *TAG(emit_elts)( GLcontext *ctx, GLuint *elts, GLuint nr,
77 void *buf)
78 {
79 GLint i;
80 LOCAL_VARS;
81 ELTS_VARS(buf);
82
83 for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) {
84 EMIT_TWO_ELTS( 0, elts[0], elts[1] );
85 INCR_ELTS( 2 );
86 }
87
88 if (i < nr) {
89 EMIT_ELT( 0, elts[0] );
90 INCR_ELTS( 1 );
91 }
92
93 return (void *)ELTPTR;
94 }
95 #endif
96
97 static __inline void *TAG(emit_verts)( GLcontext *ctx, GLuint start,
98 GLuint count, void *buf )
99 {
100 return EMIT_VERTS(ctx, start, count, buf);
101 }
102
103 /***********************************************************************
104 * Render non-indexed primitives.
105 ***********************************************************************/
106
107 static void TAG(render_points_verts)( GLcontext *ctx,
108 GLuint start,
109 GLuint count,
110 GLuint flags )
111 {
112 if (HAVE_POINTS) {
113 LOCAL_VARS;
114 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
115 int currentsz;
116 GLuint j, nr;
117
118 INIT( GL_POINTS );
119
120 currentsz = GET_CURRENT_VB_MAX_VERTS();
121 if (currentsz < 8)
122 currentsz = dmasz;
123
124 for (j = start; j < count; j += nr ) {
125 nr = MIN2( currentsz, count - j );
126 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
127 currentsz = dmasz;
128 }
129
130 } else {
131 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
132 return;
133 }
134 }
135
136 static void TAG(render_lines_verts)( GLcontext *ctx,
137 GLuint start,
138 GLuint count,
139 GLuint flags )
140 {
141 if (HAVE_LINES) {
142 LOCAL_VARS;
143 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
144 int currentsz;
145 GLuint j, nr;
146
147 INIT( GL_LINES );
148
149 /* Emit whole number of lines in total and in each buffer:
150 */
151 count -= (count-start) & 1;
152 currentsz = GET_CURRENT_VB_MAX_VERTS();
153 currentsz -= currentsz & 1;
154 dmasz -= dmasz & 1;
155
156 if (currentsz < 8)
157 currentsz = dmasz;
158
159 for (j = start; j < count; j += nr ) {
160 nr = MIN2( currentsz, count - j );
161 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
162 currentsz = dmasz;
163 }
164
165 } else {
166 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
167 return;
168 }
169 }
170
171
172 static void TAG(render_line_strip_verts)( GLcontext *ctx,
173 GLuint start,
174 GLuint count,
175 GLuint flags )
176 {
177 if (HAVE_LINE_STRIPS) {
178 LOCAL_VARS;
179 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
180 int currentsz;
181 GLuint j, nr;
182
183 INIT( GL_LINE_STRIP );
184
185 currentsz = GET_CURRENT_VB_MAX_VERTS();
186 if (currentsz < 8)
187 currentsz = dmasz;
188
189 for (j = start; j + 1 < count; j += nr - 1 ) {
190 nr = MIN2( currentsz, count - j );
191 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
192 currentsz = dmasz;
193 }
194
195 FLUSH();
196
197 } else {
198 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
199 return;
200 }
201 }
202
203
204 static void TAG(render_line_loop_verts)( GLcontext *ctx,
205 GLuint start,
206 GLuint count,
207 GLuint flags )
208 {
209 if (HAVE_LINE_STRIPS) {
210 LOCAL_VARS;
211 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
212 int currentsz;
213 GLuint j, nr;
214
215 INIT( GL_LINE_STRIP );
216
217 if (flags & PRIM_BEGIN)
218 j = start;
219 else
220 j = start + 1;
221
222 /* Ensure last vertex won't wrap buffers:
223 */
224 currentsz = GET_CURRENT_VB_MAX_VERTS();
225 currentsz--;
226 dmasz--;
227
228 if (currentsz < 8) {
229 currentsz = dmasz;
230 }
231
232 if (j + 1 < count) {
233 for ( ; j + 1 < count; j += nr - 1 ) {
234 nr = MIN2( currentsz, count - j );
235
236 if (j + nr >= count &&
237 start < count - 1 &&
238 (flags & PRIM_END))
239 {
240 void *tmp;
241 tmp = ALLOC_VERTS(nr+1);
242 tmp = TAG(emit_verts)( ctx, j, nr, tmp );
243 tmp = TAG(emit_verts)( ctx, start, 1, tmp );
244 }
245 else {
246 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
247 currentsz = dmasz;
248 }
249 }
250
251 }
252 else if (start + 1 < count && (flags & PRIM_END)) {
253 void *tmp;
254 tmp = ALLOC_VERTS(2);
255 tmp = TAG(emit_verts)( ctx, start+1, 1, tmp );
256 tmp = TAG(emit_verts)( ctx, start, 1, tmp );
257 }
258
259 FLUSH();
260
261 } else {
262 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
263 return;
264 }
265 }
266
267
268 static void TAG(render_triangles_verts)( GLcontext *ctx,
269 GLuint start,
270 GLuint count,
271 GLuint flags )
272 {
273 LOCAL_VARS;
274 int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
275 int currentsz;
276 GLuint j, nr;
277
278 INIT(GL_TRIANGLES);
279
280 currentsz = (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
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 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
293 currentsz = dmasz;
294 }
295 }
296
297
298
299 static void TAG(render_tri_strip_verts)( GLcontext *ctx,
300 GLuint start,
301 GLuint count,
302 GLuint flags )
303 {
304 if (HAVE_TRI_STRIPS) {
305 LOCAL_VARS;
306 GLuint j, nr;
307 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
308 int currentsz;
309
310 INIT(GL_TRIANGLE_STRIP);
311
312 currentsz = GET_CURRENT_VB_MAX_VERTS();
313
314 if (currentsz < 8) {
315 currentsz = dmasz;
316 }
317
318 /* From here on emit even numbers of tris when wrapping over buffers:
319 */
320 dmasz -= (dmasz & 1);
321 currentsz -= (currentsz & 1);
322
323 for (j = start ; j + 2 < count; j += nr - 2 ) {
324 nr = MIN2( currentsz, count - j );
325 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
326 currentsz = dmasz;
327 }
328
329 FLUSH();
330
331 } else {
332 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
333 return;
334 }
335 }
336
337 static void TAG(render_tri_fan_verts)( GLcontext *ctx,
338 GLuint start,
339 GLuint count,
340 GLuint flags )
341 {
342 if (HAVE_TRI_FANS) {
343 LOCAL_VARS;
344 GLuint j, nr;
345 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
346 int currentsz;
347
348 INIT(GL_TRIANGLE_FAN);
349
350 currentsz = GET_CURRENT_VB_MAX_VERTS();
351 if (currentsz < 8) {
352 currentsz = dmasz;
353 }
354
355 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) {
356 void *tmp;
357 nr = MIN2( currentsz, count - j + 1 );
358 tmp = ALLOC_VERTS( nr );
359 tmp = TAG(emit_verts)( ctx, start, 1, tmp );
360 tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp );
361 currentsz = dmasz;
362 }
363
364 FLUSH();
365 }
366 else {
367 /* Could write code to emit these as indexed vertices (for the
368 * g400, for instance).
369 */
370 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
371 return;
372 }
373 }
374
375
376 static void TAG(render_poly_verts)( GLcontext *ctx,
377 GLuint start,
378 GLuint count,
379 GLuint flags )
380 {
381 if (HAVE_POLYGONS) {
382 LOCAL_VARS;
383 GLuint j, nr;
384 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
385 int currentsz;
386
387 INIT(GL_POLYGON);
388
389 currentsz = GET_CURRENT_VB_MAX_VERTS();
390 if (currentsz < 8) {
391 currentsz = dmasz;
392 }
393
394 for (j = start + 1 ; j + 1 < count ; j += nr - 2 ) {
395 void *tmp;
396 nr = MIN2( currentsz, count - j + 1 );
397 tmp = ALLOC_VERTS( nr );
398 tmp = TAG(emit_verts)( ctx, start, 1, tmp );
399 tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp );
400 currentsz = dmasz;
401 }
402
403 FLUSH();
404 }
405 else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) {
406 TAG(render_tri_fan_verts)( ctx, start, count, flags );
407 } else {
408 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
409 return;
410 }
411 }
412
413 static void TAG(render_quad_strip_verts)( GLcontext *ctx,
414 GLuint start,
415 GLuint count,
416 GLuint flags )
417 {
418 GLuint j, nr;
419
420 if (HAVE_QUAD_STRIPS) {
421 LOCAL_VARS;
422 GLuint j, nr;
423 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
424 int currentsz;
425
426 INIT(GL_QUAD_STRIP);
427
428 currentsz = GET_CURRENT_VB_MAX_VERTS();
429 if (currentsz < 8) {
430 currentsz = dmasz;
431 }
432
433 dmasz -= (dmasz & 2);
434 currentsz -= (currentsz & 2);
435
436 for (j = start ; j + 3 < count; j += nr - 2 ) {
437 nr = MIN2( currentsz, count - j );
438 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
439 currentsz = dmasz;
440 }
441
442 FLUSH();
443
444 } else if (HAVE_TRI_STRIPS && (ctx->_TriangleCaps & DD_FLATSHADE)) {
445 if (HAVE_ELTS) {
446 LOCAL_VARS;
447 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
448 int currentsz;
449 GLuint j, nr;
450
451 EMIT_INDEXED_VERTS( ctx, start, count );
452
453 /* Simulate flat-shaded quadstrips using indexed vertices:
454 */
455 ELT_INIT( GL_TRIANGLES );
456
457 currentsz = GET_CURRENT_VB_MAX_ELTS();
458
459 /* Emit whole number of quads in total, and in each buffer.
460 */
461 dmasz -= dmasz & 1;
462 count -= (count-start) & 1;
463 currentsz -= currentsz & 1;
464
465 if (currentsz < 12)
466 currentsz = dmasz;
467
468 currentsz = currentsz/6*2;
469 dmasz = dmasz/6*2;
470
471 for (j = start; j + 3 < count; j += nr - 2 ) {
472 nr = MIN2( currentsz, count - j );
473 if (nr >= 4) {
474 GLint quads = (nr/2)-1;
475 GLint i;
476 ELTS_VARS( ALLOC_ELTS( quads*6 ) );
477
478 for ( i = j-start ; i < j-start+quads*2 ; i+=2 ) {
479 EMIT_TWO_ELTS( 0, (i+0), (i+1) );
480 EMIT_TWO_ELTS( 2, (i+2), (i+1) );
481 EMIT_TWO_ELTS( 4, (i+3), (i+2) );
482 INCR_ELTS( 6 );
483 }
484
485 FLUSH();
486 }
487 currentsz = dmasz;
488 }
489
490 RELEASE_ELT_VERTS();
491 FLUSH();
492 }
493 else {
494 /* Vertices won't fit in a single buffer or elts not available,
495 * VERT_FALLBACK.
496 */
497 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
498 return;
499 }
500 }
501 else if (HAVE_TRI_STRIPS) {
502 LOCAL_VARS;
503 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
504 int currentsz;
505
506 /* Emit smooth-shaded quadstrips as tristrips:
507 */
508 FLUSH();
509 INIT( GL_TRIANGLE_STRIP );
510
511 /* Emit whole number of quads in total, and in each buffer.
512 */
513 dmasz -= dmasz & 1;
514 currentsz = GET_CURRENT_VB_MAX_VERTS();
515 currentsz -= currentsz & 1;
516 count -= (count-start) & 1;
517
518 if (currentsz < 8) {
519 currentsz = dmasz;
520 }
521
522 for (j = start; j + 3 < count; j += nr - 2 ) {
523 nr = MIN2( currentsz, count - j );
524 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
525 currentsz = dmasz;
526 }
527
528 FLUSH();
529
530 } else {
531 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
532 return;
533 }
534 }
535
536
537 static void TAG(render_quads_verts)( GLcontext *ctx,
538 GLuint start,
539 GLuint count,
540 GLuint flags )
541 {
542 if (HAVE_QUADS) {
543 LOCAL_VARS;
544 int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
545 int currentsz;
546 GLuint j, nr;
547
548 INIT(GL_QUADS);
549
550 /* Emit whole number of quads in total. dmasz is already a multiple
551 * of 4.
552 */
553 count -= (count-start)%4;
554
555 currentsz = (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
556 if (currentsz < 8)
557 currentsz = dmasz;
558
559 for (j = start; j < count; j += nr) {
560 nr = MIN2( currentsz, count - j );
561 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
562 currentsz = dmasz;
563 }
564
565
566 } else if (HAVE_ELTS) {
567 /* Hardware doesn't have a quad primitive type -- try to
568 * simulate it using indexed vertices and the triangle
569 * primitive:
570 */
571 LOCAL_VARS;
572 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
573 int currentsz;
574 GLuint j, nr;
575
576 EMIT_INDEXED_VERTS( ctx, start, count );
577
578 FLUSH();
579 ELT_INIT( GL_TRIANGLES );
580 currentsz = GET_CURRENT_VB_MAX_ELTS();
581
582 /* Emit whole number of quads in total, and in each buffer.
583 */
584 dmasz -= dmasz & 3;
585 count -= (count-start) & 3;
586 currentsz -= currentsz & 3;
587
588 /* Adjust for rendering as triangles:
589 */
590 currentsz = currentsz/6*4;
591 dmasz = dmasz/6*4;
592
593 if (currentsz < 8)
594 currentsz = dmasz;
595
596 for (j = start; j < count; j += nr ) {
597 nr = MIN2( currentsz, count - j );
598 if (nr >= 4) {
599 GLint quads = nr/4;
600 GLint i;
601 ELTS_VARS( ALLOC_ELTS( quads*6 ) );
602
603 for ( i = j-start ; i < j-start+quads*4 ; i+=4 ) {
604 EMIT_TWO_ELTS( 0, (i+0), (i+1) );
605 EMIT_TWO_ELTS( 2, (i+3), (i+1) );
606 EMIT_TWO_ELTS( 4, (i+2), (i+3) );
607 INCR_ELTS( 6 );
608 }
609
610 FLUSH();
611 }
612 currentsz = dmasz;
613 }
614
615 RELEASE_ELT_VERTS();
616 }
617 else {
618 /* Vertices won't fit in a single buffer, fallback.
619 */
620 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
621 return;
622 }
623 }
624
625 static void TAG(render_noop)( GLcontext *ctx,
626 GLuint start,
627 GLuint count,
628 GLuint flags )
629 {
630 }
631
632
633
634
635 static tnl_render_func TAG(render_tab_verts)[GL_POLYGON+2] =
636 {
637 TAG(render_points_verts),
638 TAG(render_lines_verts),
639 TAG(render_line_loop_verts),
640 TAG(render_line_strip_verts),
641 TAG(render_triangles_verts),
642 TAG(render_tri_strip_verts),
643 TAG(render_tri_fan_verts),
644 TAG(render_quads_verts),
645 TAG(render_quad_strip_verts),
646 TAG(render_poly_verts),
647 TAG(render_noop),
648 };
649
650
651 /****************************************************************************
652 * Render elts using hardware indexed verts *
653 ****************************************************************************/
654
655 #if (HAVE_ELTS)
656 static void TAG(render_points_elts)( GLcontext *ctx,
657 GLuint start,
658 GLuint count,
659 GLuint flags )
660 {
661 if (HAVE_POINTS) {
662 LOCAL_VARS;
663 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
664 int currentsz;
665 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
666 GLuint j, nr;
667
668 ELT_INIT( GL_POINTS );
669
670 currentsz = GET_CURRENT_VB_MAX_ELTS();
671 if (currentsz < 8)
672 currentsz = dmasz;
673
674 for (j = start; j < count; j += nr ) {
675 nr = MIN2( currentsz, count - j );
676 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
677 FLUSH();
678 currentsz = dmasz;
679 }
680 } else {
681 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
682 return;
683 }
684 }
685
686
687
688 static void TAG(render_lines_elts)( GLcontext *ctx,
689 GLuint start,
690 GLuint count,
691 GLuint flags )
692 {
693 if (HAVE_LINES) {
694 LOCAL_VARS;
695 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
696 int currentsz;
697 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
698 GLuint j, nr;
699
700 ELT_INIT( GL_LINES );
701
702 /* Emit whole number of lines in total and in each buffer:
703 */
704 count -= (count-start) & 1;
705 currentsz -= currentsz & 1;
706 dmasz -= dmasz & 1;
707
708 currentsz = GET_CURRENT_VB_MAX_ELTS();
709 if (currentsz < 8)
710 currentsz = dmasz;
711
712 for (j = start; j < count; j += nr ) {
713 nr = MIN2( currentsz, count - j );
714 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
715 FLUSH();
716 currentsz = dmasz;
717 }
718 } else {
719 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
720 return;
721 }
722 }
723
724
725 static void TAG(render_line_strip_elts)( GLcontext *ctx,
726 GLuint start,
727 GLuint count,
728 GLuint flags )
729 {
730 if (HAVE_LINE_STRIPS) {
731 LOCAL_VARS;
732 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
733 int currentsz;
734 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
735 GLuint j, nr;
736
737 FLUSH(); /* always a new primitive */
738 ELT_INIT( GL_LINE_STRIP );
739
740 currentsz = GET_CURRENT_VB_MAX_ELTS();
741 if (currentsz < 8)
742 currentsz = dmasz;
743
744 for (j = start; j + 1 < count; j += nr - 1 ) {
745 nr = MIN2( currentsz, count - j );
746 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
747 FLUSH();
748 currentsz = dmasz;
749 }
750 } else {
751 /* TODO: Try to emit as indexed lines.
752 */
753 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
754 return;
755 }
756 }
757
758
759 static void TAG(render_line_loop_elts)( GLcontext *ctx,
760 GLuint start,
761 GLuint count,
762 GLuint flags )
763 {
764 if (HAVE_LINE_STRIPS) {
765 LOCAL_VARS;
766 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
767 int currentsz;
768 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
769 GLuint j, nr;
770
771 FLUSH();
772 ELT_INIT( GL_LINE_STRIP );
773
774 if (flags & PRIM_BEGIN)
775 j = start;
776 else
777 j = start + 1;
778
779 currentsz = GET_CURRENT_VB_MAX_ELTS();
780 if (currentsz < 8) {
781 currentsz = dmasz;
782 }
783
784 /* Ensure last vertex doesn't wrap:
785 */
786 currentsz--;
787 dmasz--;
788
789 if (j + 1 < count) {
790 for ( ; j + 1 < count; j += nr - 1 ) {
791 nr = MIN2( currentsz, count - j );
792
793 if (j + nr >= count &&
794 start < count - 1 &&
795 (flags & PRIM_END))
796 {
797 void *tmp;
798 tmp = ALLOC_ELTS(nr+1);
799 tmp = TAG(emit_elts)( ctx, elts+j, nr, tmp );
800 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
801 }
802 else {
803 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
804 currentsz = dmasz;
805 }
806 }
807
808 }
809 else if (start + 1 < count && (flags & PRIM_END)) {
810 void *tmp;
811 tmp = ALLOC_ELTS(2);
812 tmp = TAG(emit_elts)( ctx, elts+start+1, 1, tmp );
813 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
814 }
815
816 FLUSH();
817 } else {
818 /* TODO: Try to emit as indexed lines */
819 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
820 return;
821 }
822 }
823
824
825 /* For verts, we still eliminate the copy from main memory to dma
826 * buffers. For elts, this is probably no better (worse?) than the
827 * standard path.
828 */
829 static void TAG(render_triangles_elts)( GLcontext *ctx,
830 GLuint start,
831 GLuint count,
832 GLuint flags )
833 {
834 LOCAL_VARS;
835 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
836 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
837 int currentsz;
838 GLuint j, nr;
839
840 FLUSH();
841 ELT_INIT( GL_TRIANGLES );
842
843 currentsz = GET_CURRENT_VB_MAX_ELTS();
844
845 /* Emit whole number of tris in total. dmasz is already a multiple
846 * of 3.
847 */
848 count -= (count-start)%3;
849 currentsz -= currentsz%3;
850 if (currentsz < 8)
851 currentsz = dmasz;
852
853 for (j = start; j < count; j += nr) {
854 nr = MIN2( currentsz, count - j );
855 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
856 FLUSH();
857 currentsz = dmasz;
858 }
859 }
860
861
862
863 static void TAG(render_tri_strip_elts)( GLcontext *ctx,
864 GLuint start,
865 GLuint count,
866 GLuint flags )
867 {
868 if (HAVE_TRI_STRIPS) {
869 LOCAL_VARS;
870 GLuint j, nr;
871 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
872 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
873 int currentsz;
874
875 FLUSH();
876 ELT_INIT( GL_TRIANGLE_STRIP );
877
878 currentsz = GET_CURRENT_VB_MAX_ELTS();
879 if (currentsz < 8) {
880 currentsz = dmasz;
881 }
882
883 /* Keep the same winding over multiple buffers:
884 */
885 dmasz -= (dmasz & 1);
886 currentsz -= (currentsz & 1);
887
888 for (j = start ; j + 2 < count; j += nr - 2 ) {
889 nr = MIN2( currentsz, count - j );
890 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
891 FLUSH();
892 currentsz = dmasz;
893 }
894 } else {
895 /* TODO: try to emit as indexed triangles */
896 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
897 return;
898 }
899 }
900
901 static void TAG(render_tri_fan_elts)( GLcontext *ctx,
902 GLuint start,
903 GLuint count,
904 GLuint flags )
905 {
906 if (HAVE_TRI_FANS) {
907 LOCAL_VARS;
908 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
909 GLuint j, nr;
910 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
911 int currentsz;
912
913 FLUSH();
914 ELT_INIT( GL_TRIANGLE_FAN );
915
916 currentsz = GET_CURRENT_VB_MAX_ELTS();
917 if (currentsz < 8) {
918 currentsz = dmasz;
919 }
920
921 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) {
922 void *tmp;
923 nr = MIN2( currentsz, count - j + 1 );
924 tmp = ALLOC_ELTS( nr );
925 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
926 tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp );
927 FLUSH();
928 currentsz = dmasz;
929 }
930 } else {
931 /* TODO: try to emit as indexed triangles */
932 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
933 return;
934 }
935 }
936
937
938 static void TAG(render_poly_elts)( GLcontext *ctx,
939 GLuint start,
940 GLuint count,
941 GLuint flags )
942 {
943 if (HAVE_POLYGONS) {
944 LOCAL_VARS;
945 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
946 GLuint j, nr;
947 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
948 int currentsz;
949
950 FLUSH();
951 ELT_INIT( GL_POLYGON );
952
953 currentsz = GET_CURRENT_VB_MAX_ELTS();
954 if (currentsz < 8) {
955 currentsz = dmasz;
956 }
957
958 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) {
959 void *tmp;
960 nr = MIN2( currentsz, count - j + 1 );
961 tmp = ALLOC_ELTS( nr );
962 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
963 tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp );
964 FLUSH();
965 currentsz = dmasz;
966 }
967 } else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) {
968 TAG(render_tri_fan_verts)( ctx, start, count, flags );
969 } else {
970 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
971 return;
972 }
973 }
974
975 static void TAG(render_quad_strip_elts)( GLcontext *ctx,
976 GLuint start,
977 GLuint count,
978 GLuint flags )
979 {
980 if (HAVE_QUAD_STRIPS && 0) {
981 }
982 else if (HAVE_TRI_STRIPS) {
983 LOCAL_VARS;
984 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
985 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
986 int currentsz;
987 GLuint j, nr;
988
989 FLUSH();
990 currentsz = GET_CURRENT_VB_MAX_ELTS();
991
992 /* Emit whole number of quads in total, and in each buffer.
993 */
994 dmasz -= dmasz & 1;
995 count -= (count-start) & 1;
996 currentsz -= currentsz & 1;
997
998 if (currentsz < 12)
999 currentsz = dmasz;
1000
1001 if (ctx->_TriangleCaps & DD_FLATSHADE) {
1002 ELT_INIT( GL_TRIANGLES );
1003
1004 currentsz = currentsz/6*2;
1005 dmasz = dmasz/6*2;
1006
1007 for (j = start; j + 3 < count; j += nr - 2 ) {
1008 nr = MIN2( currentsz, count - j );
1009
1010 if (nr >= 4)
1011 {
1012 GLint i;
1013 GLint quads = (nr/2)-1;
1014 ELTS_VARS( ALLOC_ELTS( quads*6 ) );
1015
1016 for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) {
1017 EMIT_TWO_ELTS( 0, elts[0], elts[1] );
1018 EMIT_TWO_ELTS( 2, elts[2], elts[1] );
1019 EMIT_TWO_ELTS( 4, elts[3], elts[2] );
1020 INCR_ELTS( 6 );
1021 }
1022
1023 FLUSH();
1024 }
1025
1026 currentsz = dmasz;
1027 }
1028 }
1029 else {
1030 ELT_INIT( GL_TRIANGLE_STRIP );
1031
1032 for (j = start; j + 3 < count; j += nr - 2 ) {
1033 nr = MIN2( currentsz, count - j );
1034 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
1035 FLUSH();
1036 currentsz = dmasz;
1037 }
1038 }
1039 }
1040 }
1041
1042
1043 static void TAG(render_quads_elts)( GLcontext *ctx,
1044 GLuint start,
1045 GLuint count,
1046 GLuint flags )
1047 {
1048 if (HAVE_QUADS) {
1049 LOCAL_VARS;
1050 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
1051 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1052 int currentsz;
1053 GLuint j, nr;
1054
1055 FLUSH();
1056 ELT_INIT( GL_TRIANGLES );
1057
1058 currentsz = GET_CURRENT_VB_MAX_ELTS()/4*4;
1059
1060 count -= (count-start)%4;
1061
1062 if (currentsz < 8)
1063 currentsz = dmasz;
1064
1065 for (j = start; j < count; j += nr) {
1066 nr = MIN2( currentsz, count - j );
1067 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
1068 FLUSH();
1069 currentsz = dmasz;
1070 }
1071 } else {
1072 LOCAL_VARS;
1073 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
1074 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
1075 int currentsz;
1076 GLuint j, nr;
1077
1078 ELT_INIT( GL_TRIANGLES );
1079 currentsz = GET_CURRENT_VB_MAX_ELTS();
1080
1081 /* Emit whole number of quads in total, and in each buffer.
1082 */
1083 dmasz -= dmasz & 3;
1084 count -= (count-start) & 3;
1085 currentsz -= currentsz & 3;
1086
1087 /* Adjust for rendering as triangles:
1088 */
1089 currentsz = currentsz/6*4;
1090 dmasz = dmasz/6*4;
1091
1092 if (currentsz < 8)
1093 currentsz = dmasz;
1094
1095 for (j = start; j + 3 < count; j += nr - 2 ) {
1096 nr = MIN2( currentsz, count - j );
1097
1098 if (nr >= 4)
1099 {
1100 GLint quads = nr/4;
1101 GLint i;
1102 ELTS_VARS( ALLOC_ELTS( quads * 6 ) );
1103
1104 for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) {
1105 EMIT_TWO_ELTS( 0, elts[0], elts[1] );
1106 EMIT_TWO_ELTS( 2, elts[3], elts[1] );
1107 EMIT_TWO_ELTS( 4, elts[2], elts[3] );
1108 INCR_ELTS( 6 );
1109 }
1110
1111 FLUSH();
1112 }
1113
1114 currentsz = dmasz;
1115 }
1116 }
1117 }
1118
1119
1120
1121 static tnl_render_func TAG(render_tab_elts)[GL_POLYGON+2] =
1122 {
1123 TAG(render_points_elts),
1124 TAG(render_lines_elts),
1125 TAG(render_line_loop_elts),
1126 TAG(render_line_strip_elts),
1127 TAG(render_triangles_elts),
1128 TAG(render_tri_strip_elts),
1129 TAG(render_tri_fan_elts),
1130 TAG(render_quads_elts),
1131 TAG(render_quad_strip_elts),
1132 TAG(render_poly_elts),
1133 TAG(render_noop),
1134 };
1135
1136
1137
1138 #endif
1139
1140
1141
1142
1143
1144
1145 /* Prevent fallbacks later on.
1146 */
1147 static GLboolean TAG(validate_render)( GLcontext *ctx,
1148 struct vertex_buffer *VB )
1149 {
1150 GLint i;
1151
1152 if (VB->ClipOrMask & ~CLIP_CULL_BIT)
1153 return GL_FALSE;
1154
1155 if (VB->Elts && !HAVE_ELTS)
1156 return GL_FALSE;
1157
1158 for (i = 0 ; i < VB->PrimitiveCount ; i++) {
1159 GLuint prim = VB->Primitive[i].mode;
1160 GLuint count = VB->Primitive[i].count;
1161 GLboolean ok = GL_FALSE;
1162
1163 if (!count)
1164 continue;
1165
1166 switch (prim & PRIM_MODE_MASK) {
1167 case GL_POINTS:
1168 ok = HAVE_POINTS;
1169 break;
1170 case GL_LINES:
1171 ok = HAVE_LINES && !ctx->Line.StippleFlag;
1172 break;
1173 case GL_LINE_STRIP:
1174 ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag;
1175 break;
1176 case GL_LINE_LOOP:
1177 ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag;
1178 break;
1179 case GL_TRIANGLES:
1180 ok = HAVE_TRIANGLES;
1181 break;
1182 case GL_TRIANGLE_STRIP:
1183 ok = HAVE_TRI_STRIPS;
1184 break;
1185 case GL_TRIANGLE_FAN:
1186 ok = HAVE_TRI_FANS;
1187 break;
1188 case GL_POLYGON:
1189 if (HAVE_POLYGONS) {
1190 ok = GL_TRUE;
1191 }
1192 else
1193 ok = (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE));
1194 break;
1195 case GL_QUAD_STRIP:
1196 if (VB->Elts) {
1197 ok = HAVE_TRI_STRIPS;
1198 }
1199 else if (HAVE_QUAD_STRIPS) {
1200 ok = GL_TRUE;
1201 } else if (HAVE_TRI_STRIPS && (ctx->_TriangleCaps & DD_FLATSHADE)) {
1202 if (HAVE_ELTS) {
1203 ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS();
1204 }
1205 else {
1206 ok = GL_FALSE;
1207 }
1208 }
1209 else
1210 ok = HAVE_TRI_STRIPS;
1211 break;
1212 case GL_QUADS:
1213 if (HAVE_QUADS) {
1214 ok = GL_TRUE;
1215 } else if (HAVE_ELTS) {
1216 ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS();
1217 }
1218 else {
1219 ok = GL_FALSE;
1220 }
1221 break;
1222 default:
1223 break;
1224 }
1225
1226 if (!ok) return GL_FALSE;
1227 }
1228
1229 return GL_TRUE;
1230 }
1231