2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 /* Template for render stages which build and emit vertices directly
26 * to fixed-size dma buffers. Useful for rendering strips and other
27 * native primitives where clipping and per-vertex tweaks such as
28 * those in t_dd_tritmp.h are not required.
30 * Produces code for both inline triangles and indexed triangles.
31 * Where various primitive types are unaccelerated by hardware, the
32 * code attempts to fallback to other primitive types (quadstrips to
33 * tristrips, lineloops to linestrips), or to indexed vertices.
34 * Ultimately, a FALLBACK() macro is invoked if there is no way to
35 * render the primitive natively.
38 #if !defined(HAVE_TRIANGLES)
39 #error "must have at least triangles to use render template"
44 #define ALLOC_ELTS(nr)
45 #define EMIT_ELT(offset, elt)
46 #define EMIT_TWO_ELTS(offset, elt0, elt1)
48 #define ELT_INIT(prim)
49 #define GET_CURRENT_VB_MAX_ELTS() 0
50 #define GET_SUBSEQUENT_VB_MAX_ELTS() 0
51 #define ALLOC_ELTS_NEW_PRIMITIVE(nr)
52 #define RELEASE_ELT_VERTS()
53 #define EMIT_INDEXED_VERTS(ctx, start, count)
57 #define EMIT_TWO_ELTS(offset, elt0, elt1) \
59 EMIT_ELT(offset, elt0); \
60 EMIT_ELT(offset + 1, elt1); \
68 /***********************************************************************
69 * Render non-indexed primitives.
70 ***********************************************************************/
72 static void TAG(render_points_verts
)(GLcontext
*ctx
,
77 #ifdef PERFORMANCE_MEASURE
78 if (VIA_PERFORMANCE
) P_M_X
;
81 if (VIA_DEBUG
) fprintf(stderr
, "%s in\n", __FUNCTION__
);
85 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
86 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
94 for (j
= start
; j
< count
; j
+= nr
) {
95 nr
= MIN2(currentsz
, count
- j
);
96 EMIT_VERTS(ctx
, j
, nr
);
103 VERT_FALLBACK(ctx
, start
, count
, flags
);
106 if (VIA_DEBUG
) fprintf(stderr
, "%s out\n", __FUNCTION__
);
110 static void TAG(render_lines_verts
)(GLcontext
*ctx
,
115 #ifdef PERFORMANCE_MEASURE
116 if (VIA_PERFORMANCE
) P_M_X
;
119 if (VIA_DEBUG
) fprintf(stderr
, "%s in\n", __FUNCTION__
);
123 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
124 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
129 /* Emit whole number of lines in total and in each buffer:
131 count
-= (count
- start
) & 1;
132 currentsz
-= currentsz
& 1;
138 for (j
= start
; j
< count
; j
+= nr
) {
139 nr
= MIN2(currentsz
, count
- j
);
140 EMIT_VERTS(ctx
, j
, nr
);
147 VERT_FALLBACK(ctx
, start
, count
, flags
);
150 if (VIA_DEBUG
) fprintf(stderr
, "%s out\n", __FUNCTION__
);
155 static void TAG(render_line_strip_verts
)(GLcontext
*ctx
,
160 #ifdef PERFORMANCE_MEASURE
161 if (VIA_PERFORMANCE
) P_M_X
;
164 if (VIA_DEBUG
) fprintf(stderr
, "%s in\n", __FUNCTION__
);
166 if (HAVE_LINE_STRIPS
) {
168 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
169 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
177 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1) {
178 nr
= MIN2(currentsz
, count
- j
);
179 EMIT_VERTS(ctx
, j
, nr
);
186 VERT_FALLBACK(ctx
, start
, count
, flags
);
189 if (VIA_DEBUG
) fprintf(stderr
, "%s out\n", __FUNCTION__
);
194 static void TAG(render_line_loop_verts
)(GLcontext
*ctx
,
199 #ifdef PERFORMANCE_MEASURE
200 if (VIA_PERFORMANCE
) P_M_X
;
203 if (VIA_DEBUG
) fprintf(stderr
, "%s in\n", __FUNCTION__
);
205 if (HAVE_LINE_STRIPS
) {
207 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
208 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
213 if (flags
& PRIM_BEGIN
)
218 /* Ensure last vertex won't wrap buffers:
226 for (; j
+ 1 < count
; j
+= nr
- 1) {
227 nr
= MIN2(currentsz
, count
- j
);
228 EMIT_VERTS(ctx
, j
, nr
);
232 if (start
< count
- 1 && (flags
& PRIM_END
))
233 EMIT_VERTS(ctx
, start
, 1);
238 VERT_FALLBACK(ctx
, start
, count
, flags
);
241 if (VIA_DEBUG
) fprintf(stderr
, "%s out\n", __FUNCTION__
);
246 static void TAG(render_triangles_verts
)(GLcontext
*ctx
,
252 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS() / 3) * 3;
253 int currentsz
= (GET_CURRENT_VB_MAX_VERTS() / 3) * 3;
256 if (VIA_DEBUG
) fprintf(stderr
, "%s - in\n", __FUNCTION__
);
258 #ifdef PERFORMANCE_MEASURE
259 if (VIA_PERFORMANCE
) P_M_X
;
263 /* Emit whole number of tris in total. dmasz is already a multiple
266 count
-= (count
- start
) % 3;
271 for (j
= start
; j
< count
; j
+= nr
) {
272 nr
= MIN2(currentsz
, count
- j
);
273 EMIT_VERTS(ctx
, j
, nr
);
278 if (VIA_DEBUG
) fprintf(stderr
, "%s - out\n", __FUNCTION__
);
283 static void TAG(render_tri_strip_verts
)(GLcontext
*ctx
,
288 #ifdef PERFORMANCE_MEASURE
289 if (VIA_PERFORMANCE
) P_M_X
;
292 if (VIA_DEBUG
) fprintf(stderr
, "%s in\n", __FUNCTION__
);
294 if (HAVE_TRI_STRIPS
) {
297 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
298 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
300 INIT(GL_TRIANGLE_STRIP
);
307 /* From here on emit even numbers of tris when wrapping over buffers:
309 dmasz
-= (dmasz
& 1);
310 currentsz
-= (currentsz
& 1);
312 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2) {
313 nr
= MIN2(currentsz
, count
- j
);
314 EMIT_VERTS(ctx
, j
, nr
);
321 VERT_FALLBACK(ctx
, start
, count
, flags
);
324 if (VIA_DEBUG
) fprintf(stderr
, "%s out\n", __FUNCTION__
);
328 static void TAG(render_tri_fan_verts
)(GLcontext
*ctx
,
334 if (VIA_DEBUG
) fprintf(stderr
, "%s - in\n", __FUNCTION__
);
336 #ifdef PERFORMANCE_MEASURE
337 if (VIA_PERFORMANCE
) P_M_X
;
342 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
343 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
345 INIT(GL_TRIANGLE_FAN
);
352 for (j
= start
+ 1; j
+ 1 < count
; j
+= nr
- 1) {
353 nr
= MIN2(currentsz
, count
- j
+ 1);
354 EMIT_VERTS(ctx
, start
, 1);
355 EMIT_VERTS(ctx
, j
, nr
- 1);
362 /* Could write code to emit these as indexed vertices (for the
363 * g400, for instance).
365 VERT_FALLBACK(ctx
, start
, count
, flags
);
368 if (VIA_DEBUG
) fprintf(stderr
, "%s - out\n", __FUNCTION__
);
373 static void TAG(render_poly_verts
)(GLcontext
*ctx
,
378 #ifdef PERFORMANCE_MEASURE
379 if (VIA_PERFORMANCE
) P_M_X
;
382 if (VIA_DEBUG
) fprintf(stderr
, "%s in\n", __FUNCTION__
);
387 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
388 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
397 for (j
= start
+ 1; j
+ 1 < count
; j
+= nr
- 1) {
398 nr
= MIN2(currentsz
, count
- j
+ 1);
399 EMIT_VERTS(ctx
, start
, 1);
400 EMIT_VERTS(ctx
, j
, nr
- 1);
406 else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
407 TAG(render_tri_fan_verts
)(ctx
, start
, count
, flags
);
410 VERT_FALLBACK(ctx
, start
, count
, flags
);
413 if (VIA_DEBUG
) fprintf(stderr
, "%s out\n", __FUNCTION__
);
417 static void TAG(render_quad_strip_verts
)(GLcontext
*ctx
,
423 #ifdef PERFORMANCE_MEASURE
424 if (VIA_PERFORMANCE
) P_M_X
;
427 if (VIA_DEBUG
) fprintf(stderr
, "%s in\n", __FUNCTION__
);
429 if (HAVE_QUAD_STRIPS
) {
432 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
437 currentsz
= GET_CURRENT_VB_MAX_VERTS();
444 dmasz
-= (dmasz
& 2);
445 currentsz
-= (currentsz
& 2);
447 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2) {
448 nr
= MIN2(currentsz
, count
- j
);
449 EMIT_VERTS(ctx
, j
, nr
);
455 else if (HAVE_TRI_STRIPS
) {
457 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
458 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
460 /* Emit smooth-shaded quadstrips as tristrips:
462 INIT(GL_TRIANGLE_STRIP
);
464 /* Emit whole number of quads in total, and in each buffer.
467 currentsz
-= currentsz
& 1;
468 count
-= (count
- start
) & 1;
475 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2) {
476 nr
= MIN2(currentsz
, count
- j
);
477 EMIT_VERTS(ctx
, j
, nr
);
484 VERT_FALLBACK(ctx
, start
, count
, flags
);
487 if (VIA_DEBUG
) fprintf(stderr
, "%s out\n", __FUNCTION__
);
492 static void TAG(render_quads_verts
)(GLcontext
*ctx
,
498 if (VIA_DEBUG
) fprintf(stderr
, "%s - in\n", __FUNCTION__
);
500 #ifdef PERFORMANCE_MEASURE
501 if (VIA_PERFORMANCE
) P_M_X
;
505 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS() / 4) * 4;
506 int currentsz
= (GET_CURRENT_VB_MAX_VERTS() / 4) * 4;
511 /* Emit whole number of quads in total. dmasz is already a multiple
514 count
-= (count
- start
) % 4;
519 for (j
= start
; j
< count
; j
+= nr
) {
520 nr
= MIN2(currentsz
, count
- j
);
521 EMIT_VERTS(ctx
, j
, nr
);
526 else if (HAVE_TRIANGLES
) {
527 /* Hardware doesn't have a quad primitive type -- try to
528 * simulate it using triangle primitive.
531 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
537 currentsz
= GET_CURRENT_VB_MAX_VERTS();
539 /* Emit whole number of quads in total, and in each buffer.
542 count
-= (count
- start
) & 3;
543 currentsz
-= currentsz
& 3;
545 /* Adjust for rendering as triangles:
547 currentsz
= currentsz
/ 6 * 4;
548 dmasz
= dmasz
/ 6 * 4;
553 for (j
= start
; j
< count
; j
+= 4) {
556 EMIT_VERTS(ctx
, j
, 2);
557 EMIT_VERTS(ctx
, j
+ 3, 1);
560 EMIT_VERTS(ctx
, j
+ 1, 3);
565 /* Vertices won't fit in a single buffer, fallback.
567 VERT_FALLBACK(ctx
, start
, count
, flags
);
570 if (VIA_DEBUG
) fprintf(stderr
, "%s - out\n", __FUNCTION__
);
574 static void TAG(render_noop
)(GLcontext
*ctx
,
582 static tnl_render_func
TAG(render_tab_verts
)[GL_POLYGON
+ 2] =
584 TAG(render_points_verts
),
585 TAG(render_lines_verts
),
586 TAG(render_line_loop_verts
),
587 TAG(render_line_strip_verts
),
588 TAG(render_triangles_verts
),
589 TAG(render_tri_strip_verts
),
590 TAG(render_tri_fan_verts
),
591 TAG(render_quads_verts
),
592 TAG(render_quad_strip_verts
),
593 TAG(render_poly_verts
),