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