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