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