2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * Keith Whitwell <keith@tungstengraphics.com>
37 #include "swrast/swrast.h"
38 #include "swrast_setup/swrast_setup.h"
39 #include "tnl/t_context.h"
40 #include "tnl/t_pipeline.h"
46 * Subpixel offsets to adjust Mesa's (true) window coordinates to
47 * Glide coordinates. We need these to ensure precise rasterization.
48 * Otherwise, we'll fail a bunch of conformance tests.
50 #define TRI_X_OFFSET ( 0.0F)
51 #define TRI_Y_OFFSET ( 0.0F)
52 #define LINE_X_OFFSET ( 0.0F)
53 #define LINE_Y_OFFSET ( 0.125F)
54 #define PNT_X_OFFSET ( 0.375F)
55 #define PNT_Y_OFFSET ( 0.375F)
57 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
);
58 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
60 /***********************************************************************
61 * Macros for t_dd_tritmp.h to draw basic primitives *
62 ***********************************************************************/
64 #define TRI( a, b, c ) \
67 fxMesa->draw_tri( fxMesa, a, b, c ); \
69 grDrawTriangle( a, b, c ); \
72 #define QUAD( a, b, c, d ) \
75 fxMesa->draw_tri( fxMesa, a, b, d ); \
76 fxMesa->draw_tri( fxMesa, b, c, d ); \
78 grDrawTriangle( a, b, d ); \
79 grDrawTriangle( b, c, d ); \
83 #define LINE( v0, v1 ) \
86 fxMesa->draw_line( fxMesa, v0, v1 ); \
88 v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
89 v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
90 v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
91 v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
92 grDrawLine( v0, v1 ); \
93 v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
94 v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
95 v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
96 v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
100 #define POINT( v0 ) \
103 fxMesa->draw_point( fxMesa, v0 ); \
105 v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
106 v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
108 v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
109 v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
114 /***********************************************************************
115 * Fallback to swrast for basic primitives *
116 ***********************************************************************/
118 /* Build an SWvertex from a hardware vertex.
120 * This code is hit only when a mix of accelerated and unaccelerated
121 * primitives are being drawn, and only for the unaccelerated
125 fx_translate_vertex( GLcontext
*ctx
, const GrVertex
*src
, SWvertex
*dst
)
127 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
128 GLuint ts0
= fxMesa
->tmu_source
[0];
129 GLuint ts1
= fxMesa
->tmu_source
[1];
130 GLfloat w
= 1.0 / src
->oow
;
132 dst
->win
[0] = src
->x
;
133 dst
->win
[1] = src
->y
;
134 dst
->win
[2] = src
->ooz
;
135 dst
->win
[3] = src
->oow
;
137 dst
->color
[0] = src
->pargb
[2];
138 dst
->color
[1] = src
->pargb
[1];
139 dst
->color
[2] = src
->pargb
[0];
140 dst
->color
[3] = src
->pargb
[3];
142 dst
->texcoord
[ts0
][0] = fxMesa
->inv_s0scale
* src
->tmuvtx
[0].sow
* w
;
143 dst
->texcoord
[ts0
][1] = fxMesa
->inv_t0scale
* src
->tmuvtx
[0].tow
* w
;
145 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU0
)
146 dst
->texcoord
[ts0
][3] = src
->tmuvtx
[0].oow
* w
;
148 dst
->texcoord
[ts0
][3] = 1.0;
150 if (fxMesa
->SetupIndex
& SETUP_TMU1
) {
151 dst
->texcoord
[ts1
][0] = fxMesa
->inv_s1scale
* src
->tmuvtx
[1].sow
* w
;
152 dst
->texcoord
[ts1
][1] = fxMesa
->inv_t1scale
* src
->tmuvtx
[1].tow
* w
;
154 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU1
)
155 dst
->texcoord
[ts1
][3] = src
->tmuvtx
[1].oow
* w
;
157 dst
->texcoord
[ts1
][3] = 1.0;
160 dst
->pointSize
= ctx
->Point
._Size
;
165 fx_fallback_tri( fxMesaContext fxMesa
,
170 GLcontext
*ctx
= fxMesa
->glCtx
;
173 fx_translate_vertex( ctx
, v0
, &v
[0] );
174 fx_translate_vertex( ctx
, v1
, &v
[1] );
175 fx_translate_vertex( ctx
, v2
, &v
[2] );
176 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
181 fx_fallback_line( fxMesaContext fxMesa
,
185 GLcontext
*ctx
= fxMesa
->glCtx
;
187 fx_translate_vertex( ctx
, v0
, &v
[0] );
188 fx_translate_vertex( ctx
, v1
, &v
[1] );
189 _swrast_Line( ctx
, &v
[0], &v
[1] );
194 fx_fallback_point( fxMesaContext fxMesa
,
197 GLcontext
*ctx
= fxMesa
->glCtx
;
199 fx_translate_vertex( ctx
, v0
, &v
[0] );
200 _swrast_Point( ctx
, &v
[0] );
203 /***********************************************************************
204 * Functions to draw basic primitives *
205 ***********************************************************************/
207 static void fx_print_vertex( GLcontext
*ctx
, const GrVertex
*v
)
209 fprintf(stderr
, "%s:\n", __FUNCTION__
);
211 fprintf(stderr
, "\tvertex at %p\n", (void *) v
);
213 fprintf(stderr
, "\tx %f y %f z %f oow %f\n", v
->x
, v
->y
, v
->ooz
, v
->oow
);
214 fprintf(stderr
, "\tr %d g %d b %d a %d\n", v
->pargb
[2], v
->pargb
[1], v
->pargb
[0], v
->pargb
[3]);
216 fprintf(stderr
, "\n");
219 #define DO_FALLBACK 0
221 /* Need to do clip loop at each triangle when mixing swrast and hw
222 * rendering. These functions are only used when mixed-mode rendering
225 static void fx_draw_quad( fxMesaContext fxMesa
,
232 QUAD( v0
, v1
, v2
, v3
);
236 static void fx_draw_triangle( fxMesaContext fxMesa
,
246 static void fx_draw_line( fxMesaContext fxMesa
,
250 /* No support for wide lines (avoid wide/aa line fallback).
257 static void fx_draw_point( fxMesaContext fxMesa
,
260 /* No support for wide points.
270 #define FX_UNFILLED_BIT 0x1
271 #define FX_OFFSET_BIT 0x2
272 #define FX_TWOSIDE_BIT 0x4
273 #define FX_FLAT_BIT 0x8
274 #define FX_FALLBACK_BIT 0x10
275 #define FX_MAX_TRIFUNC 0x20
280 triangle_func triangle
;
282 } rast_tab
[FX_MAX_TRIFUNC
];
284 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
285 #define DO_OFFSET (IND & FX_OFFSET_BIT)
286 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
287 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
288 #define DO_FLAT (IND & FX_FLAT_BIT)
293 #define DO_FULL_QUAD 1
297 #define HAVE_HW_FLATSHADE 0
298 #define HAVE_BACK_COLORS 0
299 #define VERTEX GrVertex
302 #define DEPTH_SCALE 1.0
303 #define UNFILLED_TRI unfilled_tri
304 #define UNFILLED_QUAD unfilled_quad
305 #define VERT_X(_v) _v->x
306 #define VERT_Y(_v) _v->y
307 #define VERT_Z(_v) _v->ooz
308 #define AREA_IS_CCW( a ) (a < 0)
309 #define GET_VERTEX(e) (fxMesa->verts + e)
311 #define VERT_SET_RGBA( dst, f ) \
313 dst->pargb[2] = f[0]; \
314 dst->pargb[1] = f[1]; \
315 dst->pargb[0] = f[2]; \
316 dst->pargb[3] = f[3]; \
319 #define VERT_COPY_RGBA( v0, v1 ) \
320 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
322 #define VERT_SAVE_RGBA( idx ) \
323 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
326 #define VERT_RESTORE_RGBA( idx ) \
327 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
330 #define LOCAL_VARS(n) \
331 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
332 GLubyte color[n][4]; \
337 /***********************************************************************
338 * Functions to draw basic unfilled primitives *
339 ***********************************************************************/
341 #define RASTERIZE(x) if (fxMesa->raster_primitive != x) \
342 fxRasterPrimitive( ctx, x )
343 #define RENDER_PRIMITIVE fxMesa->render_primitive
344 #define IND FX_FALLBACK_BIT
346 #include "../common/t_dd_unfilled.h"
349 /***********************************************************************
350 * Functions to draw GL primitives *
351 ***********************************************************************/
355 #include "../common/t_dd_tritmp.h"
357 #define IND (FX_OFFSET_BIT)
358 #define TAG(x) x##_offset
359 #include "../common/t_dd_tritmp.h"
361 #define IND (FX_TWOSIDE_BIT)
362 #define TAG(x) x##_twoside
363 #include "../common/t_dd_tritmp.h"
365 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
366 #define TAG(x) x##_twoside_offset
367 #include "../common/t_dd_tritmp.h"
369 #define IND (FX_UNFILLED_BIT)
370 #define TAG(x) x##_unfilled
371 #include "../common/t_dd_tritmp.h"
373 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
374 #define TAG(x) x##_offset_unfilled
375 #include "../common/t_dd_tritmp.h"
377 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
378 #define TAG(x) x##_twoside_unfilled
379 #include "../common/t_dd_tritmp.h"
381 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
382 #define TAG(x) x##_twoside_offset_unfilled
383 #include "../common/t_dd_tritmp.h"
385 #define IND (FX_FALLBACK_BIT)
386 #define TAG(x) x##_fallback
387 #include "../common/t_dd_tritmp.h"
389 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
390 #define TAG(x) x##_offset_fallback
391 #include "../common/t_dd_tritmp.h"
393 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
394 #define TAG(x) x##_twoside_fallback
395 #include "../common/t_dd_tritmp.h"
397 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
398 #define TAG(x) x##_twoside_offset_fallback
399 #include "../common/t_dd_tritmp.h"
401 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
402 #define TAG(x) x##_unfilled_fallback
403 #include "../common/t_dd_tritmp.h"
405 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
406 #define TAG(x) x##_offset_unfilled_fallback
407 #include "../common/t_dd_tritmp.h"
409 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
410 #define TAG(x) x##_twoside_unfilled_fallback
411 #include "../common/t_dd_tritmp.h"
413 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
415 #define TAG(x) x##_twoside_offset_unfilled_fallback
416 #include "../common/t_dd_tritmp.h"
419 /* Fx doesn't support provoking-vertex flat-shading?
421 #define IND (FX_FLAT_BIT)
422 #define TAG(x) x##_flat
423 #include "../common/t_dd_tritmp.h"
425 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
426 #define TAG(x) x##_offset_flat
427 #include "../common/t_dd_tritmp.h"
429 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
430 #define TAG(x) x##_twoside_flat
431 #include "../common/t_dd_tritmp.h"
433 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
434 #define TAG(x) x##_twoside_offset_flat
435 #include "../common/t_dd_tritmp.h"
437 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
438 #define TAG(x) x##_unfilled_flat
439 #include "../common/t_dd_tritmp.h"
441 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
442 #define TAG(x) x##_offset_unfilled_flat
443 #include "../common/t_dd_tritmp.h"
445 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
446 #define TAG(x) x##_twoside_unfilled_flat
447 #include "../common/t_dd_tritmp.h"
449 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
450 #define TAG(x) x##_twoside_offset_unfilled_flat
451 #include "../common/t_dd_tritmp.h"
453 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
454 #define TAG(x) x##_fallback_flat
455 #include "../common/t_dd_tritmp.h"
457 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
458 #define TAG(x) x##_offset_fallback_flat
459 #include "../common/t_dd_tritmp.h"
461 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
462 #define TAG(x) x##_twoside_fallback_flat
463 #include "../common/t_dd_tritmp.h"
465 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
466 #define TAG(x) x##_twoside_offset_fallback_flat
467 #include "../common/t_dd_tritmp.h"
469 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
470 #define TAG(x) x##_unfilled_fallback_flat
471 #include "../common/t_dd_tritmp.h"
473 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
474 #define TAG(x) x##_offset_unfilled_fallback_flat
475 #include "../common/t_dd_tritmp.h"
477 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
478 #define TAG(x) x##_twoside_unfilled_fallback_flat
479 #include "../common/t_dd_tritmp.h"
481 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
482 FX_FALLBACK_BIT|FX_FLAT_BIT)
483 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
484 #include "../common/t_dd_tritmp.h"
487 static void init_rast_tab( void )
492 init_twoside_offset();
494 init_offset_unfilled();
495 init_twoside_unfilled();
496 init_twoside_offset_unfilled();
498 init_offset_fallback();
499 init_twoside_fallback();
500 init_twoside_offset_fallback();
501 init_unfilled_fallback();
502 init_offset_unfilled_fallback();
503 init_twoside_unfilled_fallback();
504 init_twoside_offset_unfilled_fallback();
509 init_twoside_offset_flat();
510 init_unfilled_flat();
511 init_offset_unfilled_flat();
512 init_twoside_unfilled_flat();
513 init_twoside_offset_unfilled_flat();
514 init_fallback_flat();
515 init_offset_fallback_flat();
516 init_twoside_fallback_flat();
517 init_twoside_offset_fallback_flat();
518 init_unfilled_fallback_flat();
519 init_offset_unfilled_fallback_flat();
520 init_twoside_unfilled_fallback_flat();
521 init_twoside_offset_unfilled_fallback_flat();
525 /**********************************************************************/
526 /* Render whole begin/end objects */
527 /**********************************************************************/
530 /* Accelerate vertex buffer rendering when renderindex == 0 and
531 * there is no clipping.
533 #define INIT(x) fxRenderPrimitive( ctx, x )
535 static void fx_render_vb_points( GLcontext
*ctx
,
540 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
541 GrVertex
*fxVB
= fxMesa
->verts
;
545 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
546 fprintf(stderr
, "fx_render_vb_points\n");
551 /* Adjust point coords */
552 for (i
= start
; i
< count
; i
++) {
553 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
554 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
557 grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
558 fxVB
+ start
, sizeof(GrVertex
));
559 /* restore point coords */
560 for (i
= start
; i
< count
; i
++) {
561 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
562 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
566 static void fx_render_vb_line_strip( GLcontext
*ctx
,
571 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
572 GrVertex
*fxVB
= fxMesa
->verts
;
576 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
577 fprintf(stderr
, "fx_render_vb_line_strip\n");
582 /* adjust line coords */
583 for (i
= start
; i
< count
; i
++) {
584 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
585 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
588 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
589 fxVB
+ start
, sizeof(GrVertex
));
591 /* restore line coords */
592 for (i
= start
; i
< count
; i
++) {
593 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
594 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
598 static void fx_render_vb_line_loop( GLcontext
*ctx
,
603 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
604 GrVertex
*fxVB
= fxMesa
->verts
;
609 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
610 fprintf(stderr
, "fx_render_vb_line_loop\n");
615 if (!(flags
& PRIM_BEGIN
)) {
619 /* adjust line coords */
620 for (i
= start
; i
< count
; i
++) {
621 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
622 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
625 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
626 fxVB
+ j
, sizeof(GrVertex
));
628 if (flags
& PRIM_END
)
629 grDrawLine( fxVB
+ (count
- 1),
632 /* restore line coords */
633 for (i
= start
; i
< count
; i
++) {
634 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
635 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
639 static void fx_render_vb_lines( GLcontext
*ctx
,
644 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
645 GrVertex
*fxVB
= fxMesa
->verts
;
649 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
650 fprintf(stderr
, "fx_render_vb_lines\n");
655 /* adjust line coords */
656 for (i
= start
; i
< count
; i
++) {
657 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
658 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
661 grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
662 fxVB
+ start
, sizeof(GrVertex
));
664 /* restore line coords */
665 for (i
= start
; i
< count
; i
++) {
666 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
667 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
671 static void fx_render_vb_triangles( GLcontext
*ctx
,
676 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
677 GrVertex
*fxVB
= fxMesa
->verts
;
680 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
681 fprintf(stderr
, "fx_render_vb_triangles\n");
688 * apparently, this causes troubles with some programs (GLExcess);
689 * might be a bug in Glide... However, "grDrawVertexArrayContiguous"
690 * eventually calls "grDrawTriangle" for GR_TRIANGLES, so we're better
691 * off doing it by hand...
693 grDrawVertexArrayContiguous( GR_TRIANGLES
, count
-start
,
694 fxVB
+ start
, sizeof(GrVertex
));
698 for (j
=start
+2; j
<count
; j
+=3) {
699 grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
706 static void fx_render_vb_tri_strip( GLcontext
*ctx
,
711 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
712 GrVertex
*fxVB
= fxMesa
->verts
;
716 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
717 fprintf(stderr
, "fx_render_vb_tri_strip\n");
720 INIT(GL_TRIANGLE_STRIP
);
722 if (flags
& PRIM_PARITY
)
723 mode
= GR_TRIANGLE_STRIP_CONTINUE
;
725 mode
= GR_TRIANGLE_STRIP
;
727 grDrawVertexArrayContiguous( mode
, count
-start
,
728 fxVB
+ start
, sizeof(GrVertex
));
732 static void fx_render_vb_tri_fan( GLcontext
*ctx
,
737 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
738 GrVertex
*fxVB
= fxMesa
->verts
;
741 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
742 fprintf(stderr
, "fx_render_vb_tri_fan\n");
745 INIT(GL_TRIANGLE_FAN
);
747 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
748 fxVB
+ start
, sizeof(GrVertex
) );
751 static void fx_render_vb_quads( GLcontext
*ctx
,
756 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
757 GrVertex
*fxVB
= fxMesa
->verts
;
761 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
762 fprintf(stderr
, "fx_render_vb_quads\n");
767 for (i
= start
; i
< count
-3 ; i
+= 4 ) {
768 #define VERT(x) (fxVB + (x))
769 grDrawTriangle( VERT(i
), VERT(i
+1), VERT(i
+3) );
770 grDrawTriangle( VERT(i
+1), VERT(i
+2), VERT(i
+3) );
775 static void fx_render_vb_quad_strip( GLcontext
*ctx
,
780 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
781 GrVertex
*fxVB
= fxMesa
->verts
;
784 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
785 fprintf(stderr
, "fx_render_vb_quad_strip\n");
790 count
-= (count
-start
)&1;
792 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
793 count
-start
, fxVB
+ start
, sizeof(GrVertex
));
796 static void fx_render_vb_poly( GLcontext
*ctx
,
801 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
802 GrVertex
*fxVB
= fxMesa
->verts
;
805 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
806 fprintf(stderr
, "fx_render_vb_poly\n");
811 grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
812 fxVB
+ start
, sizeof(GrVertex
));
815 static void fx_render_vb_noop( GLcontext
*ctx
,
820 (void) (ctx
&& start
&& count
&& flags
);
823 static void (*fx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
830 fx_render_vb_line_loop
,
831 fx_render_vb_line_strip
,
832 fx_render_vb_triangles
,
833 fx_render_vb_tri_strip
,
834 fx_render_vb_tri_fan
,
836 fx_render_vb_quad_strip
,
843 /**********************************************************************/
844 /* Render whole (indexed) begin/end objects */
845 /**********************************************************************/
848 #define VERT(x) (vertptr + x)
850 #define RENDER_POINTS( start, count ) \
851 for ( ; start < count ; start++) \
852 grDrawPoint( VERT(ELT(start)) );
854 #define RENDER_LINE( v0, v1 ) \
855 grDrawLine( VERT(v0), VERT(v1) )
857 #define RENDER_TRI( v0, v1, v2 ) \
858 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
860 #define RENDER_QUAD( v0, v1, v2, v3 ) \
861 fx_draw_quad( fxMesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
863 #define INIT(x) fxRenderPrimitive( ctx, x )
867 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
868 GrVertex *vertptr = fxMesa->verts; \
869 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
872 #define RESET_STIPPLE
873 #define RESET_OCCLUSION
874 #define PRESERVE_VB_DEFS
876 /* Elts, no clipping.
880 #define TAG(x) fx_##x##_elts
881 #define ELT(x) elt[x]
882 #include "../common/t_dd_rendertmp.h"
884 /* Verts, no clipping.
888 #define TAG(x) fx_##x##_verts
890 /*#include "../common/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
894 /**********************************************************************/
895 /* Render clipped primitives */
896 /**********************************************************************/
900 static void fxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
903 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
904 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
905 struct vertex_buffer
*VB
= &tnl
->vb
;
906 GLuint prim
= fxMesa
->render_primitive
;
908 /* Render the new vertices as an unclipped polygon.
911 GLuint
*tmp
= VB
->Elts
;
912 VB
->Elts
= (GLuint
*)elts
;
913 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
914 PRIM_BEGIN
|PRIM_END
);
918 /* Restore the render primitive
920 if (prim
!= GL_POLYGON
)
921 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
925 static void fxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
928 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
929 GrVertex
*vertptr
= fxMesa
->verts
;
930 const GrVertex
*start
= VERT(elts
[0]);
932 for (i
= 2 ; i
< n
; i
++) {
933 grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
937 /**********************************************************************/
938 /* Choose render functions */
939 /**********************************************************************/
942 #define POINT_FALLBACK (DD_POINT_SMOOTH)
943 #define LINE_FALLBACK (DD_LINE_STIPPLE)
944 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
945 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
946 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
951 void fxDDChooseRenderState(GLcontext
*ctx
)
953 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
954 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
955 GLuint flags
= ctx
->_TriangleCaps
;
958 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
959 if (flags
& ANY_RASTER_FLAGS
) {
960 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= FX_TWOSIDE_BIT
;
961 if (flags
& DD_TRI_OFFSET
) index
|= FX_OFFSET_BIT
;
962 if (flags
& DD_TRI_UNFILLED
) index
|= FX_UNFILLED_BIT
;
963 if (flags
& DD_FLATSHADE
) index
|= FX_FLAT_BIT
;
966 fxMesa
->draw_point
= fx_draw_point
;
967 fxMesa
->draw_line
= fx_draw_line
;
968 fxMesa
->draw_tri
= fx_draw_triangle
;
970 /* Hook in fallbacks for specific primitives.
971 * [dBorca] Hack alert:
972 * If we're in FSAA mode, we always do anti-aliased primitives.
974 if (flags
& (POINT_FALLBACK
|
978 if (fxMesa
->verbose
) {
979 fprintf(stderr
, "Voodoo ! fallback (%x), raster (%x)\n",
980 flags
& ANY_FALLBACK_FLAGS
, flags
& ANY_RASTER_FLAGS
);
983 if (flags
& POINT_FALLBACK
)
984 fxMesa
->draw_point
= fx_fallback_point
;
986 if (flags
& LINE_FALLBACK
)
987 fxMesa
->draw_line
= fx_fallback_line
;
989 if (flags
& TRI_FALLBACK
)
990 fxMesa
->draw_tri
= fx_fallback_tri
;
992 index
|= FX_FALLBACK_BIT
;
996 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
997 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
998 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
999 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1000 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1003 tnl
->Driver
.Render
.PrimTabVerts
= fx_render_tab_verts
;
1004 tnl
->Driver
.Render
.PrimTabElts
= fx_render_tab_elts
;
1005 tnl
->Driver
.Render
.ClippedPolygon
= fxFastRenderClippedPoly
;
1007 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1008 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1009 tnl
->Driver
.Render
.ClippedPolygon
= fxRenderClippedPoly
;
1012 fxMesa
->render_index
= index
;
1016 /**********************************************************************/
1017 /* Runtime render state and callbacks */
1018 /**********************************************************************/
1020 static void fxRunPipeline( GLcontext
*ctx
)
1022 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1023 GLuint new_gl_state
= fxMesa
->new_gl_state
;
1025 if (TDFX_DEBUG
& VERBOSE_PIPELINE
) {
1026 fprintf(stderr
, "fxRunPipeline()\n");
1030 /* Recalculate fog table on projection matrix changes. This used to
1031 * be triggered by the NearFar callback.
1033 if (new_gl_state
& _NEW_PROJECTION
)
1034 fxMesa
->new_state
|= FX_NEW_FOG
;
1035 /* [dBorca] Hack alert:
1036 * the above _NEW_PROJECTION is not included in the test below,
1037 * so we may end up with fxMesa->new_state still dirty by the end
1038 * of the routine. The fact is, we don't have NearFar callback
1039 * anymore. We could use fxDDDepthRange instead, but it seems
1040 * fog needs to be updated only by a fog-basis.
1041 * Implementing fxDDDepthRange correctly is another story:
1042 * that, together with a presumable fxDDViewport function would set
1043 * fxMesa->SetupNewInputs |= VERT_BIT_CLIP;
1044 * which might be useful in fxBuildVertices...
1048 if (new_gl_state
& (_FX_NEW_IS_IN_HARDWARE
|
1049 _FX_NEW_RENDERSTATE
|
1050 _FX_NEW_SETUP_FUNCTION
|
1053 if (new_gl_state
& _FX_NEW_IS_IN_HARDWARE
)
1054 fxCheckIsInHardware(ctx
);
1056 if (fxMesa
->new_state
)
1057 fxSetupFXUnits(ctx
);
1059 if (!fxMesa
->fallback
) {
1060 if (new_gl_state
& _FX_NEW_RENDERSTATE
)
1061 fxDDChooseRenderState(ctx
);
1063 if (new_gl_state
& _FX_NEW_SETUP_FUNCTION
)
1064 fxChooseVertexState(ctx
);
1067 if (new_gl_state
& _NEW_TEXTURE
) {
1068 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
1069 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
1071 if (t0
&& t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
1072 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
1073 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
1074 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
1075 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
1078 if (t1
&& t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
1079 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
1080 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
1081 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
1082 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
1087 fxMesa
->new_gl_state
= 0;
1089 _tnl_run_pipeline( ctx
);
1093 static GLenum reduced_prim
[GL_POLYGON
+1] = {
1108 /* Always called between RenderStart and RenderFinish --> We already
1111 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1113 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1115 fxMesa
->raster_primitive
= prim
;
1122 /* Determine the rasterized primitive when not drawing unfilled
1125 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1127 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1128 GLuint rprim
= reduced_prim
[prim
];
1130 fxMesa
->render_primitive
= prim
;
1132 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1135 if (fxMesa
->raster_primitive
!= rprim
) {
1136 fxRasterPrimitive( ctx
, rprim
);
1140 static void fxRenderFinish( GLcontext
*ctx
)
1142 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1144 if (fxMesa
->render_index
& FX_FALLBACK_BIT
)
1145 _swrast_flush( ctx
);
1150 /**********************************************************************/
1151 /* Manage total rasterization fallbacks */
1152 /**********************************************************************/
1154 static char *fallbackStrings
[] = {
1155 "1D/3D Texture map",
1156 "glDrawBuffer(GL_FRONT_AND_BACK)",
1157 "Separate specular color",
1158 "glEnable/Disable(GL_STENCIL_TEST)",
1159 "glRenderMode(selection or feedback)",
1169 static char *getFallbackString(GLuint bit
)
1176 return fallbackStrings
[i
];
1180 void fxCheckIsInHardware( GLcontext
*ctx
)
1182 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1183 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1184 GLuint oldfallback
= fxMesa
->fallback
;
1185 GLuint newfallback
= fxMesa
->fallback
= fx_check_IsInHardware( ctx
);
1188 if (oldfallback
== 0) {
1189 if (fxMesa
->verbose
) {
1190 fprintf(stderr
, "Voodoo ! enter SW 0x%08x %s\n", newfallback
, getFallbackString(newfallback
));
1192 _swsetup_Wakeup( ctx
);
1197 _swrast_flush( ctx
);
1198 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1199 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1200 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1201 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1202 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1203 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1204 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1205 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1206 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1207 tnl
->Driver
.Render
.Multipass
= 0;
1208 fxChooseVertexState(ctx
);
1209 fxDDChooseRenderState(ctx
);
1210 if (fxMesa
->verbose
) {
1211 fprintf(stderr
, "Voodoo ! leave SW 0x%08x %s\n", oldfallback
, getFallbackString(oldfallback
));
1217 void fxDDInitTriFuncs( GLcontext
*ctx
)
1219 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1220 static int firsttime
= 1;
1227 tnl
->Driver
.RunPipeline
= fxRunPipeline
;
1228 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1229 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1230 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1231 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1232 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1233 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1234 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1235 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1236 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1237 tnl
->Driver
.Render
.Multipass
= 0;
1239 (void) fx_print_vertex
;
1247 * Need this to provide at least one external definition.
1250 extern int gl_fx_dummy_function_tris(void);
1252 gl_fx_dummy_function_tris(void)