t_dd_dmatmp.h: Silence unused value warning in render_tri_fan_verts.
[mesa.git] / src / mesa / tnl_dd / t_dd_dmatmp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.1
4 *
5 * Copyright (C) 1999-2006 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 /**
30 * \file t_dd_dmatmp.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 * Produces code for both inline triangles and indexed triangles.
37 * Where various primitive types are unaccelerated by hardware, the
38 * code attempts to fallback to other primitive types (quadstrips to
39 * tristrips, lineloops to linestrips), or to indexed vertices.
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 (void) tmp;
245 }
246 else {
247 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
248 currentsz = dmasz;
249 }
250 }
251
252 }
253 else if (start + 1 < count && (flags & PRIM_END)) {
254 void *tmp;
255 tmp = ALLOC_VERTS(2);
256 tmp = TAG(emit_verts)( ctx, start+1, 1, tmp );
257 tmp = TAG(emit_verts)( ctx, start, 1, tmp );
258 (void) tmp;
259 }
260
261 FLUSH();
262
263 } else {
264 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
265 return;
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;
278 GLuint j, nr;
279
280 INIT(GL_TRIANGLES);
281
282 currentsz = (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
283
284 /* Emit whole number of tris in total. dmasz is already a multiple
285 * of 3.
286 */
287 count -= (count-start)%3;
288
289 if (currentsz < 8)
290 currentsz = dmasz;
291
292 for (j = start; j < count; j += nr) {
293 nr = MIN2( currentsz, count - j );
294 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
295 currentsz = dmasz;
296 }
297 }
298
299
300
301 static void TAG(render_tri_strip_verts)( GLcontext *ctx,
302 GLuint start,
303 GLuint count,
304 GLuint flags )
305 {
306 if (HAVE_TRI_STRIPS) {
307 LOCAL_VARS;
308 GLuint j, nr;
309 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
310 int currentsz;
311
312 INIT(GL_TRIANGLE_STRIP);
313
314 currentsz = GET_CURRENT_VB_MAX_VERTS();
315
316 if (currentsz < 8) {
317 currentsz = dmasz;
318 }
319
320 /* From here on emit even numbers of tris when wrapping over buffers:
321 */
322 dmasz -= (dmasz & 1);
323 currentsz -= (currentsz & 1);
324
325 for (j = start ; j + 2 < count; j += nr - 2 ) {
326 nr = MIN2( currentsz, count - j );
327 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
328 currentsz = dmasz;
329 }
330
331 FLUSH();
332
333 } else {
334 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
335 return;
336 }
337 }
338
339 static void TAG(render_tri_fan_verts)( GLcontext *ctx,
340 GLuint start,
341 GLuint count,
342 GLuint flags )
343 {
344 if (HAVE_TRI_FANS) {
345 LOCAL_VARS;
346 GLuint j, nr;
347 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
348 int currentsz;
349
350 INIT(GL_TRIANGLE_FAN);
351
352 currentsz = GET_CURRENT_VB_MAX_VERTS();
353 if (currentsz < 8) {
354 currentsz = dmasz;
355 }
356
357 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) {
358 void *tmp;
359 nr = MIN2( currentsz, count - j + 1 );
360 tmp = ALLOC_VERTS( nr );
361 tmp = TAG(emit_verts)( ctx, start, 1, tmp );
362 tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp );
363 (void) tmp;
364 currentsz = dmasz;
365 }
366
367 FLUSH();
368 }
369 else {
370 /* Could write code to emit these as indexed vertices (for the
371 * g400, for instance).
372 */
373 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
374 return;
375 }
376 }
377
378
379 static void TAG(render_poly_verts)( GLcontext *ctx,
380 GLuint start,
381 GLuint count,
382 GLuint flags )
383 {
384 if (HAVE_POLYGONS) {
385 LOCAL_VARS;
386 GLuint j, nr;
387 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
388 int currentsz;
389
390 INIT(GL_POLYGON);
391
392 currentsz = GET_CURRENT_VB_MAX_VERTS();
393 if (currentsz < 8) {
394 currentsz = dmasz;
395 }
396
397 for (j = start + 1 ; j + 1 < count ; j += nr - 2 ) {
398 void *tmp;
399 nr = MIN2( currentsz, count - j + 1 );
400 tmp = ALLOC_VERTS( nr );
401 tmp = TAG(emit_verts)( ctx, start, 1, tmp );
402 tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp );
403 currentsz = dmasz;
404 }
405
406 FLUSH();
407 }
408 else if (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH) {
409 TAG(render_tri_fan_verts)( ctx, start, count, flags );
410 } else {
411 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
412 return;
413 }
414 }
415
416 static void TAG(render_quad_strip_verts)( GLcontext *ctx,
417 GLuint start,
418 GLuint count,
419 GLuint flags )
420 {
421 GLuint j, nr;
422
423 if (HAVE_QUAD_STRIPS) {
424 LOCAL_VARS;
425 GLuint j, nr;
426 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
427 int currentsz;
428
429 INIT(GL_QUAD_STRIP);
430
431 currentsz = GET_CURRENT_VB_MAX_VERTS();
432 if (currentsz < 8) {
433 currentsz = dmasz;
434 }
435
436 dmasz -= (dmasz & 2);
437 currentsz -= (currentsz & 2);
438
439 for (j = start ; j + 3 < count; j += nr - 2 ) {
440 nr = MIN2( currentsz, count - j );
441 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
442 currentsz = dmasz;
443 }
444
445 FLUSH();
446
447 } else if (HAVE_TRI_STRIPS &&
448 ctx->Light.ShadeModel == GL_FLAT &&
449 TNL_CONTEXT(ctx)->vb.ColorPtr[0]->stride) {
450 if (HAVE_ELTS) {
451 LOCAL_VARS;
452 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
453 int currentsz;
454 GLuint j, nr;
455
456 EMIT_INDEXED_VERTS( ctx, start, count );
457
458 /* Simulate flat-shaded quadstrips using indexed vertices:
459 */
460 ELT_INIT( GL_TRIANGLES );
461
462 currentsz = GET_CURRENT_VB_MAX_ELTS();
463
464 /* Emit whole number of quads in total, and in each buffer.
465 */
466 dmasz -= dmasz & 1;
467 count -= (count-start) & 1;
468 currentsz -= currentsz & 1;
469
470 if (currentsz < 12)
471 currentsz = dmasz;
472
473 currentsz = currentsz/6*2;
474 dmasz = dmasz/6*2;
475
476 for (j = start; j + 3 < count; j += nr - 2 ) {
477 nr = MIN2( currentsz, count - j );
478 if (nr >= 4) {
479 GLint quads = (nr/2)-1;
480 GLint i;
481 ELTS_VARS( ALLOC_ELTS( quads*6 ) );
482
483 for ( i = j-start ; i < j-start+quads*2 ; i+=2 ) {
484 EMIT_TWO_ELTS( 0, (i+0), (i+1) );
485 EMIT_TWO_ELTS( 2, (i+2), (i+1) );
486 EMIT_TWO_ELTS( 4, (i+3), (i+2) );
487 INCR_ELTS( 6 );
488 }
489
490 FLUSH();
491 }
492 currentsz = dmasz;
493 }
494
495 RELEASE_ELT_VERTS();
496 FLUSH();
497 }
498 else {
499 /* Vertices won't fit in a single buffer or elts not
500 * available - should never happen.
501 */
502 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
503 return;
504 }
505 }
506 else if (HAVE_TRI_STRIPS) {
507 LOCAL_VARS;
508 int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
509 int currentsz;
510
511 /* Emit smooth-shaded quadstrips as tristrips:
512 */
513 FLUSH();
514 INIT( GL_TRIANGLE_STRIP );
515
516 /* Emit whole number of quads in total, and in each buffer.
517 */
518 dmasz -= dmasz & 1;
519 currentsz = GET_CURRENT_VB_MAX_VERTS();
520 currentsz -= currentsz & 1;
521 count -= (count-start) & 1;
522
523 if (currentsz < 8) {
524 currentsz = dmasz;
525 }
526
527 for (j = start; j + 3 < count; j += nr - 2 ) {
528 nr = MIN2( currentsz, count - j );
529 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
530 currentsz = dmasz;
531 }
532
533 FLUSH();
534
535 } else {
536 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
537 return;
538 }
539 }
540
541
542 static void TAG(render_quads_verts)( GLcontext *ctx,
543 GLuint start,
544 GLuint count,
545 GLuint flags )
546 {
547 if (HAVE_QUADS) {
548 LOCAL_VARS;
549 int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
550 int currentsz;
551 GLuint j, nr;
552
553 INIT(GL_QUADS);
554
555 /* Emit whole number of quads in total. dmasz is already a multiple
556 * of 4.
557 */
558 count -= (count-start)%4;
559
560 currentsz = (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
561 if (currentsz < 8)
562 currentsz = dmasz;
563
564 for (j = start; j < count; j += nr) {
565 nr = MIN2( currentsz, count - j );
566 TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) );
567 currentsz = dmasz;
568 }
569 }
570 else if (HAVE_ELTS) {
571 /* Hardware doesn't have a quad primitive type -- try to
572 * simulate it using indexed vertices and the triangle
573 * primitive:
574 */
575 LOCAL_VARS;
576 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
577 int currentsz;
578 GLuint j, nr;
579
580 EMIT_INDEXED_VERTS( ctx, start, count );
581
582 FLUSH();
583 ELT_INIT( GL_TRIANGLES );
584 currentsz = GET_CURRENT_VB_MAX_ELTS();
585
586 /* Emit whole number of quads in total, and in each buffer.
587 */
588 dmasz -= dmasz & 3;
589 count -= (count-start) & 3;
590 currentsz -= currentsz & 3;
591
592 /* Adjust for rendering as triangles:
593 */
594 currentsz = currentsz/6*4;
595 dmasz = dmasz/6*4;
596
597 if (currentsz < 8)
598 currentsz = dmasz;
599
600 for (j = start; j < count; j += nr ) {
601 nr = MIN2( currentsz, count - j );
602 if (nr >= 4) {
603 GLint quads = nr/4;
604 GLint i;
605 ELTS_VARS( ALLOC_ELTS( quads*6 ) );
606
607 for ( i = j-start ; i < j-start+quads*4 ; i+=4 ) {
608 EMIT_TWO_ELTS( 0, (i+0), (i+1) );
609 EMIT_TWO_ELTS( 2, (i+3), (i+1) );
610 EMIT_TWO_ELTS( 4, (i+2), (i+3) );
611 INCR_ELTS( 6 );
612 }
613
614 FLUSH();
615 }
616 currentsz = dmasz;
617 }
618
619 RELEASE_ELT_VERTS();
620 }
621 else if (HAVE_TRIANGLES) {
622 /* Hardware doesn't have a quad primitive type -- try to
623 * simulate it using triangle primitive. This is a win for
624 * gears, but is it useful in the broader world?
625 */
626 LOCAL_VARS;
627 GLuint j;
628
629 INIT(GL_TRIANGLES);
630
631 for (j = start; j < count-3; j += 4) {
632 void *tmp = ALLOC_VERTS( 6 );
633 /* Send v0, v1, v3
634 */
635 tmp = EMIT_VERTS(ctx, j, 2, tmp);
636 tmp = EMIT_VERTS(ctx, j + 3, 1, tmp);
637 /* Send v1, v2, v3
638 */
639 tmp = EMIT_VERTS(ctx, j + 1, 3, tmp);
640 }
641 }
642 else {
643 /* Vertices won't fit in a single buffer, should never happen.
644 */
645 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
646 return;
647 }
648 }
649
650 static void TAG(render_noop)( GLcontext *ctx,
651 GLuint start,
652 GLuint count,
653 GLuint flags )
654 {
655 }
656
657
658
659
660 static tnl_render_func TAG(render_tab_verts)[GL_POLYGON+2] =
661 {
662 TAG(render_points_verts),
663 TAG(render_lines_verts),
664 TAG(render_line_loop_verts),
665 TAG(render_line_strip_verts),
666 TAG(render_triangles_verts),
667 TAG(render_tri_strip_verts),
668 TAG(render_tri_fan_verts),
669 TAG(render_quads_verts),
670 TAG(render_quad_strip_verts),
671 TAG(render_poly_verts),
672 TAG(render_noop),
673 };
674
675
676 /****************************************************************************
677 * Render elts using hardware indexed verts *
678 ****************************************************************************/
679
680 #if (HAVE_ELTS)
681 static void TAG(render_points_elts)( GLcontext *ctx,
682 GLuint start,
683 GLuint count,
684 GLuint flags )
685 {
686 if (HAVE_POINTS) {
687 LOCAL_VARS;
688 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
689 int currentsz;
690 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
691 GLuint j, nr;
692
693 ELT_INIT( GL_POINTS );
694
695 currentsz = GET_CURRENT_VB_MAX_ELTS();
696 if (currentsz < 8)
697 currentsz = dmasz;
698
699 for (j = start; j < count; j += nr ) {
700 nr = MIN2( currentsz, count - j );
701 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
702 FLUSH();
703 currentsz = dmasz;
704 }
705 } else {
706 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
707 return;
708 }
709 }
710
711
712
713 static void TAG(render_lines_elts)( GLcontext *ctx,
714 GLuint start,
715 GLuint count,
716 GLuint flags )
717 {
718 if (HAVE_LINES) {
719 LOCAL_VARS;
720 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
721 int currentsz;
722 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
723 GLuint j, nr;
724
725 ELT_INIT( GL_LINES );
726
727 /* Emit whole number of lines in total and in each buffer:
728 */
729 count -= (count-start) & 1;
730 currentsz -= currentsz & 1;
731 dmasz -= dmasz & 1;
732
733 currentsz = GET_CURRENT_VB_MAX_ELTS();
734 if (currentsz < 8)
735 currentsz = dmasz;
736
737 for (j = start; j < count; j += nr ) {
738 nr = MIN2( currentsz, count - j );
739 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
740 FLUSH();
741 currentsz = dmasz;
742 }
743 } else {
744 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
745 return;
746 }
747 }
748
749
750 static void TAG(render_line_strip_elts)( GLcontext *ctx,
751 GLuint start,
752 GLuint count,
753 GLuint flags )
754 {
755 if (HAVE_LINE_STRIPS) {
756 LOCAL_VARS;
757 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
758 int currentsz;
759 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
760 GLuint j, nr;
761
762 FLUSH(); /* always a new primitive */
763 ELT_INIT( GL_LINE_STRIP );
764
765 currentsz = GET_CURRENT_VB_MAX_ELTS();
766 if (currentsz < 8)
767 currentsz = dmasz;
768
769 for (j = start; j + 1 < count; j += nr - 1 ) {
770 nr = MIN2( currentsz, count - j );
771 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
772 FLUSH();
773 currentsz = dmasz;
774 }
775 } else {
776 /* TODO: Try to emit as indexed lines.
777 */
778 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
779 return;
780 }
781 }
782
783
784 static void TAG(render_line_loop_elts)( GLcontext *ctx,
785 GLuint start,
786 GLuint count,
787 GLuint flags )
788 {
789 if (HAVE_LINE_STRIPS) {
790 LOCAL_VARS;
791 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
792 int currentsz;
793 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
794 GLuint j, nr;
795
796 FLUSH();
797 ELT_INIT( GL_LINE_STRIP );
798
799 if (flags & PRIM_BEGIN)
800 j = start;
801 else
802 j = start + 1;
803
804 currentsz = GET_CURRENT_VB_MAX_ELTS();
805 if (currentsz < 8) {
806 currentsz = dmasz;
807 }
808
809 /* Ensure last vertex doesn't wrap:
810 */
811 currentsz--;
812 dmasz--;
813
814 if (j + 1 < count) {
815 for ( ; j + 1 < count; j += nr - 1 ) {
816 nr = MIN2( currentsz, count - j );
817
818 if (j + nr >= count &&
819 start < count - 1 &&
820 (flags & PRIM_END))
821 {
822 void *tmp;
823 tmp = ALLOC_ELTS(nr+1);
824 tmp = TAG(emit_elts)( ctx, elts+j, nr, tmp );
825 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
826 }
827 else {
828 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
829 currentsz = dmasz;
830 }
831 }
832
833 }
834 else if (start + 1 < count && (flags & PRIM_END)) {
835 void *tmp;
836 tmp = ALLOC_ELTS(2);
837 tmp = TAG(emit_elts)( ctx, elts+start+1, 1, tmp );
838 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
839 }
840
841 FLUSH();
842 } else {
843 /* TODO: Try to emit as indexed lines */
844 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
845 return;
846 }
847 }
848
849
850 /* For verts, we still eliminate the copy from main memory to dma
851 * buffers. For elts, this is probably no better (worse?) than the
852 * standard path.
853 */
854 static void TAG(render_triangles_elts)( GLcontext *ctx,
855 GLuint start,
856 GLuint count,
857 GLuint flags )
858 {
859 LOCAL_VARS;
860 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
861 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
862 int currentsz;
863 GLuint j, nr;
864
865 FLUSH();
866 ELT_INIT( GL_TRIANGLES );
867
868 currentsz = GET_CURRENT_VB_MAX_ELTS();
869
870 /* Emit whole number of tris in total. dmasz is already a multiple
871 * of 3.
872 */
873 count -= (count-start)%3;
874 currentsz -= currentsz%3;
875 if (currentsz < 8)
876 currentsz = dmasz;
877
878 for (j = start; j < count; j += nr) {
879 nr = MIN2( currentsz, count - j );
880 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
881 FLUSH();
882 currentsz = dmasz;
883 }
884 }
885
886
887
888 static void TAG(render_tri_strip_elts)( GLcontext *ctx,
889 GLuint start,
890 GLuint count,
891 GLuint flags )
892 {
893 if (HAVE_TRI_STRIPS) {
894 LOCAL_VARS;
895 GLuint j, nr;
896 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
897 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
898 int currentsz;
899
900 FLUSH();
901 ELT_INIT( GL_TRIANGLE_STRIP );
902
903 currentsz = GET_CURRENT_VB_MAX_ELTS();
904 if (currentsz < 8) {
905 currentsz = dmasz;
906 }
907
908 /* Keep the same winding over multiple buffers:
909 */
910 dmasz -= (dmasz & 1);
911 currentsz -= (currentsz & 1);
912
913 for (j = start ; j + 2 < count; j += nr - 2 ) {
914 nr = MIN2( currentsz, count - j );
915 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
916 FLUSH();
917 currentsz = dmasz;
918 }
919 } else {
920 /* TODO: try to emit as indexed triangles */
921 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
922 return;
923 }
924 }
925
926 static void TAG(render_tri_fan_elts)( GLcontext *ctx,
927 GLuint start,
928 GLuint count,
929 GLuint flags )
930 {
931 if (HAVE_TRI_FANS) {
932 LOCAL_VARS;
933 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
934 GLuint j, nr;
935 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
936 int currentsz;
937
938 FLUSH();
939 ELT_INIT( GL_TRIANGLE_FAN );
940
941 currentsz = GET_CURRENT_VB_MAX_ELTS();
942 if (currentsz < 8) {
943 currentsz = dmasz;
944 }
945
946 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) {
947 void *tmp;
948 nr = MIN2( currentsz, count - j + 1 );
949 tmp = ALLOC_ELTS( nr );
950 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
951 tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp );
952 FLUSH();
953 currentsz = dmasz;
954 }
955 } else {
956 /* TODO: try to emit as indexed triangles */
957 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
958 return;
959 }
960 }
961
962
963 static void TAG(render_poly_elts)( GLcontext *ctx,
964 GLuint start,
965 GLuint count,
966 GLuint flags )
967 {
968 if (HAVE_POLYGONS) {
969 LOCAL_VARS;
970 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
971 GLuint j, nr;
972 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
973 int currentsz;
974
975 FLUSH();
976 ELT_INIT( GL_POLYGON );
977
978 currentsz = GET_CURRENT_VB_MAX_ELTS();
979 if (currentsz < 8) {
980 currentsz = dmasz;
981 }
982
983 for (j = start + 1 ; j + 1 < count; j += nr - 2 ) {
984 void *tmp;
985 nr = MIN2( currentsz, count - j + 1 );
986 tmp = ALLOC_ELTS( nr );
987 tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp );
988 tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp );
989 FLUSH();
990 currentsz = dmasz;
991 }
992 } else if (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH) {
993 TAG(render_tri_fan_verts)( ctx, start, count, flags );
994 } else {
995 fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__);
996 return;
997 }
998 }
999
1000 static void TAG(render_quad_strip_elts)( GLcontext *ctx,
1001 GLuint start,
1002 GLuint count,
1003 GLuint flags )
1004 {
1005 if (HAVE_QUAD_STRIPS && 0) {
1006 }
1007 else if (HAVE_TRI_STRIPS) {
1008 LOCAL_VARS;
1009 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
1010 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
1011 int currentsz;
1012 GLuint j, nr;
1013
1014 FLUSH();
1015 currentsz = GET_CURRENT_VB_MAX_ELTS();
1016
1017 /* Emit whole number of quads in total, and in each buffer.
1018 */
1019 dmasz -= dmasz & 1;
1020 count -= (count-start) & 1;
1021 currentsz -= currentsz & 1;
1022
1023 if (currentsz < 12)
1024 currentsz = dmasz;
1025
1026 if (ctx->Light.ShadeModel == GL_FLAT) {
1027 ELT_INIT( GL_TRIANGLES );
1028
1029 currentsz = currentsz/6*2;
1030 dmasz = dmasz/6*2;
1031
1032 for (j = start; j + 3 < count; j += nr - 2 ) {
1033 nr = MIN2( currentsz, count - j );
1034
1035 if (nr >= 4)
1036 {
1037 GLint i;
1038 GLint quads = (nr/2)-1;
1039 ELTS_VARS( ALLOC_ELTS( quads*6 ) );
1040
1041 for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) {
1042 EMIT_TWO_ELTS( 0, elts[0], elts[1] );
1043 EMIT_TWO_ELTS( 2, elts[2], elts[1] );
1044 EMIT_TWO_ELTS( 4, elts[3], elts[2] );
1045 INCR_ELTS( 6 );
1046 }
1047
1048 FLUSH();
1049 }
1050
1051 currentsz = dmasz;
1052 }
1053 }
1054 else {
1055 ELT_INIT( GL_TRIANGLE_STRIP );
1056
1057 for (j = start; j + 3 < count; j += nr - 2 ) {
1058 nr = MIN2( currentsz, count - j );
1059 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
1060 FLUSH();
1061 currentsz = dmasz;
1062 }
1063 }
1064 }
1065 }
1066
1067
1068 static void TAG(render_quads_elts)( GLcontext *ctx,
1069 GLuint start,
1070 GLuint count,
1071 GLuint flags )
1072 {
1073 if (HAVE_QUADS) {
1074 LOCAL_VARS;
1075 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
1076 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1077 int currentsz;
1078 GLuint j, nr;
1079
1080 FLUSH();
1081 ELT_INIT( GL_TRIANGLES );
1082
1083 currentsz = GET_CURRENT_VB_MAX_ELTS()/4*4;
1084
1085 count -= (count-start)%4;
1086
1087 if (currentsz < 8)
1088 currentsz = dmasz;
1089
1090 for (j = start; j < count; j += nr) {
1091 nr = MIN2( currentsz, count - j );
1092 TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) );
1093 FLUSH();
1094 currentsz = dmasz;
1095 }
1096 } else {
1097 LOCAL_VARS;
1098 GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
1099 int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
1100 int currentsz;
1101 GLuint j, nr;
1102
1103 ELT_INIT( GL_TRIANGLES );
1104 currentsz = GET_CURRENT_VB_MAX_ELTS();
1105
1106 /* Emit whole number of quads in total, and in each buffer.
1107 */
1108 dmasz -= dmasz & 3;
1109 count -= (count-start) & 3;
1110 currentsz -= currentsz & 3;
1111
1112 /* Adjust for rendering as triangles:
1113 */
1114 currentsz = currentsz/6*4;
1115 dmasz = dmasz/6*4;
1116
1117 if (currentsz < 8)
1118 currentsz = dmasz;
1119
1120 for (j = start; j + 3 < count; j += nr - 2 ) {
1121 nr = MIN2( currentsz, count - j );
1122
1123 if (nr >= 4)
1124 {
1125 GLint quads = nr/4;
1126 GLint i;
1127 ELTS_VARS( ALLOC_ELTS( quads * 6 ) );
1128
1129 for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) {
1130 EMIT_TWO_ELTS( 0, elts[0], elts[1] );
1131 EMIT_TWO_ELTS( 2, elts[3], elts[1] );
1132 EMIT_TWO_ELTS( 4, elts[2], elts[3] );
1133 INCR_ELTS( 6 );
1134 }
1135
1136 FLUSH();
1137 }
1138
1139 currentsz = dmasz;
1140 }
1141 }
1142 }
1143
1144
1145
1146 static tnl_render_func TAG(render_tab_elts)[GL_POLYGON+2] =
1147 {
1148 TAG(render_points_elts),
1149 TAG(render_lines_elts),
1150 TAG(render_line_loop_elts),
1151 TAG(render_line_strip_elts),
1152 TAG(render_triangles_elts),
1153 TAG(render_tri_strip_elts),
1154 TAG(render_tri_fan_elts),
1155 TAG(render_quads_elts),
1156 TAG(render_quad_strip_elts),
1157 TAG(render_poly_elts),
1158 TAG(render_noop),
1159 };
1160
1161
1162
1163 #endif
1164
1165
1166
1167 /* Pre-check the primitives in the VB to prevent the need for
1168 * fallbacks later on.
1169 */
1170 static GLboolean TAG(validate_render)( GLcontext *ctx,
1171 struct vertex_buffer *VB )
1172 {
1173 GLint i;
1174
1175 if (VB->ClipOrMask & ~CLIP_CULL_BIT)
1176 return GL_FALSE;
1177
1178 if (VB->Elts && !HAVE_ELTS)
1179 return GL_FALSE;
1180
1181 for (i = 0 ; i < VB->PrimitiveCount ; i++) {
1182 GLuint prim = VB->Primitive[i].mode;
1183 GLuint count = VB->Primitive[i].count;
1184 GLboolean ok = GL_FALSE;
1185
1186 if (!count)
1187 continue;
1188
1189 switch (prim & PRIM_MODE_MASK) {
1190 case GL_POINTS:
1191 ok = HAVE_POINTS;
1192 break;
1193 case GL_LINES:
1194 ok = HAVE_LINES && !ctx->Line.StippleFlag;
1195 break;
1196 case GL_LINE_STRIP:
1197 ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag;
1198 break;
1199 case GL_LINE_LOOP:
1200 ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag;
1201 break;
1202 case GL_TRIANGLES:
1203 ok = HAVE_TRIANGLES;
1204 break;
1205 case GL_TRIANGLE_STRIP:
1206 ok = HAVE_TRI_STRIPS;
1207 break;
1208 case GL_TRIANGLE_FAN:
1209 ok = HAVE_TRI_FANS;
1210 break;
1211 case GL_POLYGON:
1212 if (HAVE_POLYGONS) {
1213 ok = GL_TRUE;
1214 }
1215 else {
1216 ok = (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH);
1217 }
1218 break;
1219 case GL_QUAD_STRIP:
1220 if (VB->Elts) {
1221 ok = HAVE_TRI_STRIPS;
1222 }
1223 else if (HAVE_QUAD_STRIPS) {
1224 ok = GL_TRUE;
1225 } else if (HAVE_TRI_STRIPS &&
1226 ctx->Light.ShadeModel == GL_FLAT &&
1227 VB->ColorPtr[0]->stride != 0) {
1228 if (HAVE_ELTS) {
1229 ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS();
1230 }
1231 else {
1232 ok = GL_FALSE;
1233 }
1234 }
1235 else
1236 ok = HAVE_TRI_STRIPS;
1237 break;
1238 case GL_QUADS:
1239 if (HAVE_QUADS) {
1240 ok = GL_TRUE;
1241 } else if (HAVE_ELTS) {
1242 ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS();
1243 }
1244 else {
1245 ok = HAVE_TRIANGLES; /* flatshading is ok. */
1246 }
1247 break;
1248 default:
1249 break;
1250 }
1251
1252 if (!ok) {
1253 /* fprintf(stderr, "not ok %s\n", _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK)); */
1254 return GL_FALSE;
1255 }
1256 }
1257
1258 return GL_TRUE;
1259 }
1260