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