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>
27 * Daniel Borca <dborca@users.sourceforge.net>
38 #include "nvfragprog.h"
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_pipeline.h"
48 GLboolean
fxMultipass_ColorSum (GLcontext
*ctx
, GLuint pass
);
52 * Subpixel offsets to adjust Mesa's (true) window coordinates to
53 * Glide coordinates. We need these to ensure precise rasterization.
54 * Otherwise, we'll fail a bunch of conformance tests.
56 #define TRI_X_OFFSET ( 0.0F)
57 #define TRI_Y_OFFSET ( 0.0F)
58 #define LINE_X_OFFSET ( 0.0F)
59 #define LINE_Y_OFFSET ( 0.125F)
60 #define PNT_X_OFFSET ( 0.375F)
61 #define PNT_Y_OFFSET ( 0.375F)
63 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
);
64 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
66 /***********************************************************************
67 * Macros for t_dd_tritmp.h to draw basic primitives *
68 ***********************************************************************/
70 #define TRI( a, b, c ) \
73 fxMesa->draw_tri( fxMesa, a, b, c ); \
75 grDrawTriangle( a, b, c ); \
78 #define QUAD( a, b, c, d ) \
81 fxMesa->draw_tri( fxMesa, a, b, d ); \
82 fxMesa->draw_tri( fxMesa, b, c, d ); \
89 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
90 /*grDrawTriangle( a, b, d );*/ \
91 /*grDrawTriangle( b, c, d );*/ \
95 #define LINE( v0, v1 ) \
98 fxMesa->draw_line( fxMesa, v0, v1 ); \
100 v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
101 v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
102 v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
103 v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
104 grDrawLine( v0, v1 ); \
105 v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
106 v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
107 v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
108 v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
112 #define POINT( v0 ) \
115 fxMesa->draw_point( fxMesa, v0 ); \
117 v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
118 v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
120 v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
121 v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
126 /***********************************************************************
127 * Fallback to swrast for basic primitives *
128 ***********************************************************************/
130 /* Build an SWvertex from a hardware vertex.
132 * This code is hit only when a mix of accelerated and unaccelerated
133 * primitives are being drawn, and only for the unaccelerated
137 fx_translate_vertex( GLcontext
*ctx
, const GrVertex
*src
, SWvertex
*dst
)
139 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
140 GLuint ts0
= fxMesa
->tmu_source
[0];
141 GLuint ts1
= fxMesa
->tmu_source
[1];
142 GLfloat w
= 1.0 / src
->oow
;
144 dst
->win
[0] = src
->x
;
145 dst
->win
[1] = src
->y
;
146 dst
->win
[2] = src
->ooz
;
147 dst
->win
[3] = src
->oow
;
149 dst
->color
[0] = src
->pargb
[2];
150 dst
->color
[1] = src
->pargb
[1];
151 dst
->color
[2] = src
->pargb
[0];
152 dst
->color
[3] = src
->pargb
[3];
154 dst
->specular
[0] = src
->pspec
[2];
155 dst
->specular
[1] = src
->pspec
[1];
156 dst
->specular
[2] = src
->pspec
[0];
158 dst
->texcoord
[ts0
][0] = fxMesa
->inv_s0scale
* src
->tmuvtx
[0].sow
* w
;
159 dst
->texcoord
[ts0
][1] = fxMesa
->inv_t0scale
* src
->tmuvtx
[0].tow
* w
;
161 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU0
)
162 dst
->texcoord
[ts0
][3] = src
->tmuvtx
[0].oow
* w
;
164 dst
->texcoord
[ts0
][3] = 1.0;
166 if (fxMesa
->SetupIndex
& SETUP_TMU1
) {
167 dst
->texcoord
[ts1
][0] = fxMesa
->inv_s1scale
* src
->tmuvtx
[1].sow
* w
;
168 dst
->texcoord
[ts1
][1] = fxMesa
->inv_t1scale
* src
->tmuvtx
[1].tow
* w
;
170 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU1
)
171 dst
->texcoord
[ts1
][3] = src
->tmuvtx
[1].oow
* w
;
173 dst
->texcoord
[ts1
][3] = 1.0;
176 dst
->pointSize
= src
->psize
;
181 fx_fallback_tri( fxMesaContext fxMesa
,
186 GLcontext
*ctx
= fxMesa
->glCtx
;
189 fx_translate_vertex( ctx
, v0
, &v
[0] );
190 fx_translate_vertex( ctx
, v1
, &v
[1] );
191 fx_translate_vertex( ctx
, v2
, &v
[2] );
192 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
197 fx_fallback_line( fxMesaContext fxMesa
,
201 GLcontext
*ctx
= fxMesa
->glCtx
;
203 fx_translate_vertex( ctx
, v0
, &v
[0] );
204 fx_translate_vertex( ctx
, v1
, &v
[1] );
205 _swrast_Line( ctx
, &v
[0], &v
[1] );
210 fx_fallback_point( fxMesaContext fxMesa
,
213 GLcontext
*ctx
= fxMesa
->glCtx
;
215 fx_translate_vertex( ctx
, v0
, &v
[0] );
216 _swrast_Point( ctx
, &v
[0] );
219 /***********************************************************************
220 * Functions to draw basic primitives *
221 ***********************************************************************/
223 static void fx_print_vertex( GLcontext
*ctx
, const GrVertex
*v
)
225 fprintf(stderr
, "fx_print_vertex:\n");
227 fprintf(stderr
, "\tvertex at %p\n", (void *) v
);
229 fprintf(stderr
, "\tx %f y %f z %f oow %f\n", v
->x
, v
->y
, v
->ooz
, v
->oow
);
230 fprintf(stderr
, "\tr %d g %d b %d a %d\n", v
->pargb
[2], v
->pargb
[1], v
->pargb
[0], v
->pargb
[3]);
232 fprintf(stderr
, "\n");
235 #define DO_FALLBACK 0
237 /* Need to do clip loop at each triangle when mixing swrast and hw
238 * rendering. These functions are only used when mixed-mode rendering
241 static void fx_draw_triangle( fxMesaContext fxMesa
,
251 static void fx_draw_line( fxMesaContext fxMesa
,
255 /* No support for wide lines (avoid wide/aa line fallback).
262 static void fx_draw_point( fxMesaContext fxMesa
,
265 /* No support for wide points.
273 #define M_2PI 6.28318530717958647692528676655901
275 #define __GL_COSF cos
276 #define __GL_SINF sin
277 static void fx_draw_point_sprite ( fxMesaContext fxMesa
,
278 GrVertex
*v0
, GLfloat psize
)
280 const GLcontext
*ctx
= fxMesa
->glCtx
;
284 GLuint ts0
= fxMesa
->tmu_source
[0];
285 GLuint ts1
= fxMesa
->tmu_source
[1];
287 GLfloat u0scale
= fxMesa
->s0scale
* w
;
288 GLfloat v0scale
= fxMesa
->t0scale
* w
;
289 GLfloat u1scale
= fxMesa
->s1scale
* w
;
290 GLfloat v1scale
= fxMesa
->t1scale
* w
;
298 /* point coverage? */
299 /* we don't care about culling here (see fxSetupCull) */
310 if (ctx
->Point
.CoordReplace
[ts0
]) {
311 _v_
[0].tmuvtx
[0].sow
= 0;
312 _v_
[0].tmuvtx
[0].tow
= 0;
313 _v_
[1].tmuvtx
[0].sow
= u0scale
;
314 _v_
[1].tmuvtx
[0].tow
= 0;
315 _v_
[2].tmuvtx
[0].sow
= u0scale
;
316 _v_
[2].tmuvtx
[0].tow
= v0scale
;
317 _v_
[3].tmuvtx
[0].sow
= 0;
318 _v_
[3].tmuvtx
[0].tow
= v0scale
;
320 if (ctx
->Point
.CoordReplace
[ts1
]) {
321 _v_
[0].tmuvtx
[1].sow
= 0;
322 _v_
[0].tmuvtx
[1].tow
= 0;
323 _v_
[1].tmuvtx
[1].sow
= u1scale
;
324 _v_
[1].tmuvtx
[1].tow
= 0;
325 _v_
[2].tmuvtx
[1].sow
= u1scale
;
326 _v_
[2].tmuvtx
[1].tow
= v1scale
;
327 _v_
[3].tmuvtx
[1].sow
= 0;
328 _v_
[3].tmuvtx
[1].tow
= v1scale
;
331 grDrawVertexArrayContiguous(GR_TRIANGLE_FAN
, 4, _v_
, sizeof(GrVertex
));
334 static void fx_draw_point_wide ( fxMesaContext fxMesa
,
338 GLfloat ang
, radius
, oon
;
342 const GLcontext
*ctx
= fxMesa
->glCtx
;
343 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
) ? v0
->psize
: ctx
->Point
.Size
;
345 if (ctx
->Point
.PointSprite
) {
346 fx_draw_point_sprite(fxMesa
, v0
, psize
);
355 n
= IROUND(psize
* 2); /* radius x 4 */
357 oon
= 1.0 / (GLfloat
)n
;
360 /* point coverage? */
361 /* we don't care about culling here (see fxSetupCull) */
368 vtxC
.x
+= radius
* __GL_COSF(ang
);
369 vtxC
.y
+= radius
* __GL_SINF(ang
);
370 grDrawVertexArray(GR_TRIANGLE_FAN
, 3, _v_
);
371 for (i
= 2; i
<= n
; i
++) {
372 ang
= M_2PI
* i
* oon
;
373 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
374 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
375 grDrawVertexArray(GR_TRIANGLE_FAN_CONTINUE
, 1, &_v_
[2]);
379 static void fx_render_pw_verts( GLcontext
*ctx
,
384 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
385 GrVertex
*fxVB
= fxMesa
->verts
;
388 fxRenderPrimitive( ctx
, GL_POINTS
);
390 for ( ; start
< count
; start
++)
391 fx_draw_point_wide(fxMesa
, fxVB
+ start
);
394 static void fx_render_pw_elts ( GLcontext
*ctx
,
399 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
400 GrVertex
*fxVB
= fxMesa
->verts
;
401 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
404 fxRenderPrimitive( ctx
, GL_POINTS
);
406 for ( ; start
< count
; start
++)
407 fx_draw_point_wide(fxMesa
, fxVB
+ elt
[start
]);
410 static void fx_draw_point_wide_aa ( fxMesaContext fxMesa
,
414 GLfloat ang
, radius
, oon
;
417 const GLcontext
*ctx
= fxMesa
->glCtx
;
418 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
) ? v0
->psize
: ctx
->Point
.Size
;
420 if (ctx
->Point
.PointSprite
) {
421 fx_draw_point_sprite(fxMesa
, v0
, psize
);
426 n
= IROUND(psize
* 2); /* radius x 4 */
428 oon
= 1.0 / (GLfloat
)n
;
431 /* point coverage? */
432 /* we don't care about culling here (see fxSetupCull) */
438 for (i
= 1; i
<= n
; i
++) {
439 ang
= M_2PI
* i
* oon
;
440 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
441 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
442 grAADrawTriangle( v0
, &vtxB
, &vtxC
, FXFALSE
, FXTRUE
, FXFALSE
);
443 /*grDrawTriangle( v0, &vtxB, &vtxC);*/
455 #define FX_UNFILLED_BIT 0x1
456 #define FX_OFFSET_BIT 0x2
457 #define FX_TWOSIDE_BIT 0x4
458 #define FX_FLAT_BIT 0x8
459 #define FX_FALLBACK_BIT 0x10
460 #define FX_MAX_TRIFUNC 0x20
463 tnl_points_func points
;
465 tnl_triangle_func triangle
;
467 } rast_tab
[FX_MAX_TRIFUNC
];
469 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
470 #define DO_OFFSET (IND & FX_OFFSET_BIT)
471 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
472 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
473 #define DO_FLAT (IND & FX_FLAT_BIT)
478 #define DO_FULL_QUAD 1
482 #define HAVE_HW_FLATSHADE 0
483 #define HAVE_BACK_COLORS 0
484 #define VERTEX GrVertex
487 #define DEPTH_SCALE 1.0
488 #define UNFILLED_TRI unfilled_tri
489 #define UNFILLED_QUAD unfilled_quad
490 #define VERT_X(_v) _v->x
491 #define VERT_Y(_v) _v->y
492 #define VERT_Z(_v) _v->ooz
493 #define GET_VERTEX(e) (fxMesa->verts + e)
496 #define AREA_IS_CCW( a ) (((fi_type *)&(a))->i < 0)
498 #define AREA_IS_CCW( a ) (a < 0)
502 #define VERT_SET_RGBA( dst, f ) \
504 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[2], f[0]);\
505 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[1], f[1]);\
506 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[0], f[2]);\
507 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[3], f[3]);\
510 #define VERT_COPY_RGBA( v0, v1 ) \
511 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
513 #define VERT_SAVE_RGBA( idx ) \
514 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
516 #define VERT_RESTORE_RGBA( idx ) \
517 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
520 #define VERT_SET_SPEC( dst, f ) \
522 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[2], f[0]);\
523 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[1], f[1]);\
524 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[0], f[2]);\
527 #define VERT_COPY_SPEC( v0, v1 ) \
528 *(GLuint *)&v0->pspec = *(GLuint *)&v1->pspec
530 #define VERT_SAVE_SPEC( idx ) \
531 *(GLuint *)&spec[idx] = *(GLuint *)&v[idx]->pspec
533 #define VERT_RESTORE_SPEC( idx ) \
534 *(GLuint *)&v[idx]->pspec = *(GLuint *)&spec[idx]
537 #define LOCAL_VARS(n) \
538 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
539 GLubyte color[n][4], spec[n][4]; \
540 (void) color; (void) spec;
544 /***********************************************************************
545 * Functions to draw basic unfilled primitives *
546 ***********************************************************************/
548 #define RASTERIZE(x) if (fxMesa->raster_primitive != x) \
549 fxRasterPrimitive( ctx, x )
550 #define RENDER_PRIMITIVE fxMesa->render_primitive
551 #define IND FX_FALLBACK_BIT
553 #include "tnl_dd/t_dd_unfilled.h"
556 /***********************************************************************
557 * Functions to draw GL primitives *
558 ***********************************************************************/
562 #include "tnl_dd/t_dd_tritmp.h"
564 #define IND (FX_OFFSET_BIT)
565 #define TAG(x) x##_offset
566 #include "tnl_dd/t_dd_tritmp.h"
568 #define IND (FX_TWOSIDE_BIT)
569 #define TAG(x) x##_twoside
570 #include "tnl_dd/t_dd_tritmp.h"
572 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
573 #define TAG(x) x##_twoside_offset
574 #include "tnl_dd/t_dd_tritmp.h"
576 #define IND (FX_UNFILLED_BIT)
577 #define TAG(x) x##_unfilled
578 #include "tnl_dd/t_dd_tritmp.h"
580 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
581 #define TAG(x) x##_offset_unfilled
582 #include "tnl_dd/t_dd_tritmp.h"
584 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
585 #define TAG(x) x##_twoside_unfilled
586 #include "tnl_dd/t_dd_tritmp.h"
588 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
589 #define TAG(x) x##_twoside_offset_unfilled
590 #include "tnl_dd/t_dd_tritmp.h"
592 #define IND (FX_FALLBACK_BIT)
593 #define TAG(x) x##_fallback
594 #include "tnl_dd/t_dd_tritmp.h"
596 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
597 #define TAG(x) x##_offset_fallback
598 #include "tnl_dd/t_dd_tritmp.h"
600 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
601 #define TAG(x) x##_twoside_fallback
602 #include "tnl_dd/t_dd_tritmp.h"
604 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
605 #define TAG(x) x##_twoside_offset_fallback
606 #include "tnl_dd/t_dd_tritmp.h"
608 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
609 #define TAG(x) x##_unfilled_fallback
610 #include "tnl_dd/t_dd_tritmp.h"
612 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
613 #define TAG(x) x##_offset_unfilled_fallback
614 #include "tnl_dd/t_dd_tritmp.h"
616 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
617 #define TAG(x) x##_twoside_unfilled_fallback
618 #include "tnl_dd/t_dd_tritmp.h"
620 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
622 #define TAG(x) x##_twoside_offset_unfilled_fallback
623 #include "tnl_dd/t_dd_tritmp.h"
626 /* Fx doesn't support provoking-vertex flat-shading?
628 #define IND (FX_FLAT_BIT)
629 #define TAG(x) x##_flat
630 #include "tnl_dd/t_dd_tritmp.h"
632 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
633 #define TAG(x) x##_offset_flat
634 #include "tnl_dd/t_dd_tritmp.h"
636 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
637 #define TAG(x) x##_twoside_flat
638 #include "tnl_dd/t_dd_tritmp.h"
640 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
641 #define TAG(x) x##_twoside_offset_flat
642 #include "tnl_dd/t_dd_tritmp.h"
644 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
645 #define TAG(x) x##_unfilled_flat
646 #include "tnl_dd/t_dd_tritmp.h"
648 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
649 #define TAG(x) x##_offset_unfilled_flat
650 #include "tnl_dd/t_dd_tritmp.h"
652 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
653 #define TAG(x) x##_twoside_unfilled_flat
654 #include "tnl_dd/t_dd_tritmp.h"
656 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
657 #define TAG(x) x##_twoside_offset_unfilled_flat
658 #include "tnl_dd/t_dd_tritmp.h"
660 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
661 #define TAG(x) x##_fallback_flat
662 #include "tnl_dd/t_dd_tritmp.h"
664 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
665 #define TAG(x) x##_offset_fallback_flat
666 #include "tnl_dd/t_dd_tritmp.h"
668 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
669 #define TAG(x) x##_twoside_fallback_flat
670 #include "tnl_dd/t_dd_tritmp.h"
672 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
673 #define TAG(x) x##_twoside_offset_fallback_flat
674 #include "tnl_dd/t_dd_tritmp.h"
676 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
677 #define TAG(x) x##_unfilled_fallback_flat
678 #include "tnl_dd/t_dd_tritmp.h"
680 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
681 #define TAG(x) x##_offset_unfilled_fallback_flat
682 #include "tnl_dd/t_dd_tritmp.h"
684 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
685 #define TAG(x) x##_twoside_unfilled_fallback_flat
686 #include "tnl_dd/t_dd_tritmp.h"
688 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
689 FX_FALLBACK_BIT|FX_FLAT_BIT)
690 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
691 #include "tnl_dd/t_dd_tritmp.h"
694 static void init_rast_tab( void )
699 init_twoside_offset();
701 init_offset_unfilled();
702 init_twoside_unfilled();
703 init_twoside_offset_unfilled();
705 init_offset_fallback();
706 init_twoside_fallback();
707 init_twoside_offset_fallback();
708 init_unfilled_fallback();
709 init_offset_unfilled_fallback();
710 init_twoside_unfilled_fallback();
711 init_twoside_offset_unfilled_fallback();
716 init_twoside_offset_flat();
717 init_unfilled_flat();
718 init_offset_unfilled_flat();
719 init_twoside_unfilled_flat();
720 init_twoside_offset_unfilled_flat();
721 init_fallback_flat();
722 init_offset_fallback_flat();
723 init_twoside_fallback_flat();
724 init_twoside_offset_fallback_flat();
725 init_unfilled_fallback_flat();
726 init_offset_unfilled_fallback_flat();
727 init_twoside_unfilled_fallback_flat();
728 init_twoside_offset_unfilled_fallback_flat();
732 /**********************************************************************/
733 /* Render whole begin/end objects */
734 /**********************************************************************/
737 /* Accelerate vertex buffer rendering when renderindex == 0 and
738 * there is no clipping.
740 #define INIT(x) fxRenderPrimitive( ctx, x )
742 static void fx_render_vb_points( GLcontext
*ctx
,
747 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
748 GrVertex
*fxVB
= fxMesa
->verts
;
752 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
753 fprintf(stderr
, "fx_render_vb_points\n");
758 /* Adjust point coords */
759 for (i
= start
; i
< count
; i
++) {
760 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
761 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
764 grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
765 fxVB
+ start
, sizeof(GrVertex
));
766 /* restore point coords */
767 for (i
= start
; i
< count
; i
++) {
768 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
769 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
773 static void fx_render_vb_line_strip( GLcontext
*ctx
,
778 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
779 GrVertex
*fxVB
= fxMesa
->verts
;
783 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
784 fprintf(stderr
, "fx_render_vb_line_strip\n");
789 /* adjust line coords */
790 for (i
= start
; i
< count
; i
++) {
791 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
792 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
795 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
796 fxVB
+ start
, sizeof(GrVertex
));
798 /* restore line coords */
799 for (i
= start
; i
< count
; i
++) {
800 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
801 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
805 static void fx_render_vb_line_loop( GLcontext
*ctx
,
810 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
811 GrVertex
*fxVB
= fxMesa
->verts
;
816 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
817 fprintf(stderr
, "fx_render_vb_line_loop\n");
822 if (!(flags
& PRIM_BEGIN
)) {
826 /* adjust line coords */
827 for (i
= start
; i
< count
; i
++) {
828 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
829 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
832 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
833 fxVB
+ j
, sizeof(GrVertex
));
835 if (flags
& PRIM_END
)
836 grDrawLine( fxVB
+ (count
- 1),
839 /* restore line coords */
840 for (i
= start
; i
< count
; i
++) {
841 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
842 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
846 static void fx_render_vb_lines( GLcontext
*ctx
,
851 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
852 GrVertex
*fxVB
= fxMesa
->verts
;
856 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
857 fprintf(stderr
, "fx_render_vb_lines\n");
862 /* adjust line coords */
863 for (i
= start
; i
< count
; i
++) {
864 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
865 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
868 grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
869 fxVB
+ start
, sizeof(GrVertex
));
871 /* restore line coords */
872 for (i
= start
; i
< count
; i
++) {
873 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
874 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
878 static void fx_render_vb_triangles( GLcontext
*ctx
,
883 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
884 GrVertex
*fxVB
= fxMesa
->verts
;
888 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
889 fprintf(stderr
, "fx_render_vb_triangles\n");
894 for (j
=start
+2; j
<count
; j
+=3) {
895 grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
900 static void fx_render_vb_tri_strip( GLcontext
*ctx
,
905 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
906 GrVertex
*fxVB
= fxMesa
->verts
;
910 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
911 fprintf(stderr
, "fx_render_vb_tri_strip\n");
914 INIT(GL_TRIANGLE_STRIP
);
917 if (flags & PRIM_PARITY)
918 mode = GR_TRIANGLE_STRIP_CONTINUE;
920 mode
= GR_TRIANGLE_STRIP
;
922 grDrawVertexArrayContiguous( mode
, count
-start
,
923 fxVB
+ start
, sizeof(GrVertex
));
927 static void fx_render_vb_tri_fan( GLcontext
*ctx
,
932 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
933 GrVertex
*fxVB
= fxMesa
->verts
;
936 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
937 fprintf(stderr
, "fx_render_vb_tri_fan\n");
940 INIT(GL_TRIANGLE_FAN
);
942 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
943 fxVB
+ start
, sizeof(GrVertex
) );
946 static void fx_render_vb_quads( GLcontext
*ctx
,
951 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
952 GrVertex
*fxVB
= fxMesa
->verts
;
956 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
957 fprintf(stderr
, "fx_render_vb_quads\n");
962 for (i
= start
+ 3 ; i
< count
; i
+= 4 ) {
963 #define VERT(x) (fxVB + (x))
969 grDrawVertexArray(GR_TRIANGLE_FAN
, 4, _v_
);
970 /*grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
971 /*grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
976 static void fx_render_vb_quad_strip( GLcontext
*ctx
,
981 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
982 GrVertex
*fxVB
= fxMesa
->verts
;
985 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
986 fprintf(stderr
, "fx_render_vb_quad_strip\n");
991 count
-= (count
-start
)&1;
993 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
994 count
-start
, fxVB
+ start
, sizeof(GrVertex
));
997 static void fx_render_vb_poly( GLcontext
*ctx
,
1002 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1003 GrVertex
*fxVB
= fxMesa
->verts
;
1006 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1007 fprintf(stderr
, "fx_render_vb_poly\n");
1012 grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
1013 fxVB
+ start
, sizeof(GrVertex
));
1016 static void fx_render_vb_noop( GLcontext
*ctx
,
1021 (void) (ctx
&& start
&& count
&& flags
);
1024 static void (*fx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
1029 fx_render_vb_points
,
1031 fx_render_vb_line_loop
,
1032 fx_render_vb_line_strip
,
1033 fx_render_vb_triangles
,
1034 fx_render_vb_tri_strip
,
1035 fx_render_vb_tri_fan
,
1037 fx_render_vb_quad_strip
,
1044 /**********************************************************************/
1045 /* Render whole (indexed) begin/end objects */
1046 /**********************************************************************/
1049 #define VERT(x) (vertptr + x)
1051 #define RENDER_POINTS( start, count ) \
1052 for ( ; start < count ; start++) \
1053 grDrawPoint( VERT(ELT(start)) );
1055 #define RENDER_LINE( v0, v1 ) \
1056 grDrawLine( VERT(v0), VERT(v1) )
1058 #define RENDER_TRI( v0, v1, v2 ) \
1059 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
1061 #define RENDER_QUAD( v0, v1, v2, v3 ) \
1068 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
1069 /*grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
1070 /*grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
1073 #define INIT(x) fxRenderPrimitive( ctx, x )
1076 #define LOCAL_VARS \
1077 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
1078 GrVertex *vertptr = fxMesa->verts; \
1079 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
1082 #define RESET_STIPPLE
1083 #define RESET_OCCLUSION
1084 #define PRESERVE_VB_DEFS
1086 /* Elts, no clipping.
1090 #define TAG(x) fx_##x##_elts
1091 #define ELT(x) elt[x]
1092 #include "tnl_dd/t_dd_rendertmp.h"
1094 /* Verts, no clipping.
1098 #define TAG(x) fx_##x##_verts
1100 /*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
1104 /**********************************************************************/
1105 /* Render clipped primitives */
1106 /**********************************************************************/
1110 static void fxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1113 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1114 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1115 struct vertex_buffer
*VB
= &tnl
->vb
;
1116 GLuint prim
= fxMesa
->render_primitive
;
1118 /* Render the new vertices as an unclipped polygon.
1121 GLuint
*tmp
= VB
->Elts
;
1122 VB
->Elts
= (GLuint
*)elts
;
1123 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
1124 PRIM_BEGIN
|PRIM_END
);
1128 /* Restore the render primitive
1130 if (prim
!= GL_POLYGON
)
1131 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
1135 static void fxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1139 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1140 GrVertex
*vertptr
= fxMesa
->verts
;
1142 grDrawTriangle( VERT(elts
[0]), VERT(elts
[1]), VERT(elts
[2]) );
1143 } else if (n
<= 32) {
1144 GrVertex
*newvptr
[32];
1145 for (i
= 0 ; i
< n
; i
++) {
1146 newvptr
[i
] = VERT(elts
[i
]);
1148 grDrawVertexArray(GR_TRIANGLE_FAN
, n
, newvptr
);
1150 const GrVertex
*start
= VERT(elts
[0]);
1151 for (i
= 2 ; i
< n
; i
++) {
1152 grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
1157 /**********************************************************************/
1158 /* Choose render functions */
1159 /**********************************************************************/
1162 #define POINT_FALLBACK (DD_POINT_SMOOTH)
1163 #define LINE_FALLBACK (DD_LINE_STIPPLE)
1164 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
1165 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
1166 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
1171 void fxDDChooseRenderState(GLcontext
*ctx
)
1173 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1174 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1175 GLuint flags
= ctx
->_TriangleCaps
;
1178 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
1179 if (flags
& ANY_RASTER_FLAGS
) {
1180 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= FX_TWOSIDE_BIT
;
1181 if (flags
& DD_TRI_OFFSET
) index
|= FX_OFFSET_BIT
;
1182 if (flags
& DD_TRI_UNFILLED
) index
|= FX_UNFILLED_BIT
;
1183 if (flags
& DD_FLATSHADE
) index
|= FX_FLAT_BIT
;
1186 fxMesa
->draw_point
= fx_draw_point
;
1187 fxMesa
->draw_line
= fx_draw_line
;
1188 fxMesa
->draw_tri
= fx_draw_triangle
;
1190 /* Hook in fallbacks for specific primitives. */
1191 if (flags
& (POINT_FALLBACK
|
1195 if (fxMesa
->verbose
) {
1196 fprintf(stderr
, "Voodoo ! fallback (%x), raster (%x)\n",
1197 flags
& ANY_FALLBACK_FLAGS
, flags
& ANY_RASTER_FLAGS
);
1200 if (flags
& POINT_FALLBACK
)
1201 fxMesa
->draw_point
= fx_fallback_point
;
1203 if (flags
& LINE_FALLBACK
)
1204 fxMesa
->draw_line
= fx_fallback_line
;
1206 if (flags
& TRI_FALLBACK
)
1207 fxMesa
->draw_tri
= fx_fallback_tri
;
1209 index
|= FX_FALLBACK_BIT
;
1213 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1214 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1215 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
1216 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1217 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1220 tnl
->Driver
.Render
.PrimTabVerts
= fx_render_tab_verts
;
1221 tnl
->Driver
.Render
.PrimTabElts
= fx_render_tab_elts
;
1222 tnl
->Driver
.Render
.ClippedPolygon
= fxFastRenderClippedPoly
;
1224 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1225 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1226 tnl
->Driver
.Render
.ClippedPolygon
= fxRenderClippedPoly
;
1229 fxMesa
->render_index
= index
;
1231 /* [dBorca] Hack alert: more a trick than a real plug-in!!! */
1232 if (flags
& (DD_POINT_SIZE
| DD_POINT_ATTEN
)) {
1233 /* We need to set the point primitive to go through "rast_tab",
1234 * to make sure "POINT" calls "fxMesa->draw_point" instead of
1235 * "grDrawPoint". We can achieve this by using FX_FALLBACK_BIT
1236 * (not really a total rasterization fallback, so we don't alter
1237 * "fxMesa->render_index"). If we get here with DD_POINT_SMOOTH,
1238 * we're done, cos we've already set _tnl_render_tab_{verts|elts}
1239 * above. Otherwise, the T&L engine can optimize point rendering
1240 * by using fx_render_tab_{verts|elts} hence the extra work.
1242 if (flags
& DD_POINT_SMOOTH
) {
1243 fxMesa
->draw_point
= fx_draw_point_wide_aa
;
1245 fxMesa
->draw_point
= fx_draw_point_wide
;
1246 fx_render_tab_verts
[0] = fx_render_pw_verts
;
1247 fx_render_tab_elts
[0] = fx_render_pw_elts
;
1249 tnl
->Driver
.Render
.Points
= rast_tab
[index
|FX_FALLBACK_BIT
].points
;
1251 fx_render_tab_verts
[0] = fx_render_vb_points
;
1252 fx_render_tab_elts
[0] = fx_render_points_elts
;
1257 /**********************************************************************/
1258 /* Runtime render state and callbacks */
1259 /**********************************************************************/
1261 static void fxRunPipeline( GLcontext
*ctx
)
1263 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1264 GLuint new_gl_state
= fxMesa
->new_gl_state
;
1266 if (TDFX_DEBUG
& VERBOSE_PIPELINE
) {
1267 fprintf(stderr
, "fxRunPipeline()\n");
1271 /* Recalculate fog table on projection matrix changes. This used to
1272 * be triggered by the NearFar callback.
1274 if (new_gl_state
& _NEW_PROJECTION
)
1275 fxMesa
->new_state
|= FX_NEW_FOG
;
1276 /* [dBorca] Hack alert:
1277 * the above _NEW_PROJECTION is not included in the test below,
1278 * so we may end up with fxMesa->new_state still dirty by the end
1279 * of the routine. The fact is, we don't have NearFar callback
1280 * anymore. We could use fxDDDepthRange instead, but it seems
1281 * fog needs to be updated only by a fog-basis.
1282 * Implementing fxDDDepthRange correctly is another story:
1283 * that, together with a presumable fxDDViewport function would set
1284 * fxMesa->SetupNewInputs |= VERT_BIT_CLIP;
1285 * which might be useful in fxBuildVertices...
1289 if (new_gl_state
& (_FX_NEW_IS_IN_HARDWARE
|
1290 _FX_NEW_RENDERSTATE
|
1291 _FX_NEW_SETUP_FUNCTION
|
1294 if (new_gl_state
& _FX_NEW_IS_IN_HARDWARE
)
1295 fxCheckIsInHardware(ctx
);
1297 if (fxMesa
->new_state
)
1298 fxSetupFXUnits(ctx
);
1300 if (!fxMesa
->fallback
) {
1301 if (new_gl_state
& _FX_NEW_RENDERSTATE
)
1302 fxDDChooseRenderState(ctx
);
1304 if (new_gl_state
& _FX_NEW_SETUP_FUNCTION
)
1305 fxChooseVertexState(ctx
);
1308 if (new_gl_state
& _NEW_TEXTURE
) {
1309 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
1310 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
1312 if (t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
1313 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
1314 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
1315 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
1316 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
1319 if (t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
1320 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
1321 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
1322 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
1323 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
1328 fxMesa
->new_gl_state
= 0;
1330 _tnl_run_pipeline( ctx
);
1334 static GLenum reduced_prim
[GL_POLYGON
+1] = {
1349 /* Always called between RenderStart and RenderFinish --> We already
1352 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1354 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1356 fxMesa
->raster_primitive
= prim
;
1363 /* Determine the rasterized primitive when not drawing unfilled
1366 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1368 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1369 GLuint rprim
= reduced_prim
[prim
];
1371 fxMesa
->render_primitive
= prim
;
1373 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1376 if (fxMesa
->raster_primitive
!= rprim
) {
1377 fxRasterPrimitive( ctx
, rprim
);
1381 static void fxRenderFinish( GLcontext
*ctx
)
1383 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1385 if (fxMesa
->render_index
& FX_FALLBACK_BIT
)
1386 _swrast_flush( ctx
);
1391 /**********************************************************************/
1392 /* Manage total rasterization fallbacks */
1393 /**********************************************************************/
1395 static char *fallbackStrings
[] = {
1396 "3D/Rect/Cube Texture map",
1397 "glDrawBuffer(GL_FRONT_AND_BACK)",
1398 "Separate specular color",
1399 "glEnable/Disable(GL_STENCIL_TEST)",
1400 "glRenderMode(selection or feedback)",
1410 static char *getFallbackString(GLuint bit
)
1417 return fallbackStrings
[i
];
1421 void fxCheckIsInHardware( GLcontext
*ctx
)
1423 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1424 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1425 GLuint oldfallback
= fxMesa
->fallback
;
1426 GLuint newfallback
= fxMesa
->fallback
= fx_check_IsInHardware( ctx
);
1429 if (oldfallback
== 0) {
1430 if (fxMesa
->verbose
) {
1431 fprintf(stderr
, "Voodoo ! enter SW 0x%08x %s\n", newfallback
, getFallbackString(newfallback
));
1433 _swsetup_Wakeup( ctx
);
1438 _swrast_flush( ctx
);
1439 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1440 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1441 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1442 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1443 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1444 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1445 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1446 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1447 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1448 fxChooseVertexState(ctx
);
1449 fxDDChooseRenderState(ctx
);
1450 if (fxMesa
->verbose
) {
1451 fprintf(stderr
, "Voodoo ! leave SW 0x%08x %s\n", oldfallback
, getFallbackString(oldfallback
));
1454 tnl
->Driver
.Render
.Multipass
= (HAVE_SPEC
&& NEED_SECONDARY_COLOR(ctx
)) ? fxMultipass_ColorSum
: NULL
;
1458 void fxDDInitTriFuncs( GLcontext
*ctx
)
1460 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1461 static int firsttime
= 1;
1468 tnl
->Driver
.RunPipeline
= fxRunPipeline
;
1469 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1470 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1471 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1472 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1473 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1474 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1475 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1476 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1477 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1478 tnl
->Driver
.Render
.Multipass
= NULL
;
1480 (void) fx_print_vertex
;
1484 /* [dBorca] Hack alert:
1485 * doesn't work with blending.
1486 * need to take care of stencil.
1488 GLboolean
fxMultipass_ColorSum (GLcontext
*ctx
, GLuint pass
)
1490 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1496 case 1: /* first pass: the TEXTURED triangles are drawn */
1497 /* save per-pass data */
1498 fxMesa
->restoreUnitsState
= fxMesa
->unitsState
;
1499 /* turn off texturing */
1500 t0
= ctx
->Texture
.Unit
[0]._ReallyEnabled
;
1501 t1
= ctx
->Texture
.Unit
[1]._ReallyEnabled
;
1502 ctx
->Texture
.Unit
[0]._ReallyEnabled
= 0;
1503 ctx
->Texture
.Unit
[1]._ReallyEnabled
= 0;
1504 /* SUM the colors */
1505 fxDDBlendEquationSeparate(ctx
, GL_FUNC_ADD
, GL_FUNC_ADD
);
1506 fxDDBlendFuncSeparate(ctx
, GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
1507 fxDDEnable(ctx
, GL_BLEND
, GL_TRUE
);
1508 /* make sure we draw only where we want to */
1509 if (ctx
->Depth
.Mask
) {
1510 switch (ctx
->Depth
.Func
) {
1515 fxDDDepthFunc( ctx
, GL_EQUAL
);
1518 fxDDDepthMask( ctx
, GL_FALSE
);
1520 /* switch to secondary colors */
1521 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PSPEC_OFFSET
<< 2, GR_PARAM_ENABLE
);
1522 /* don't advertise new state */
1523 fxMesa
->new_state
= 0;
1525 case 2: /* 2nd pass (last): the secondary color is summed over texture */
1526 /* restore original state */
1527 fxMesa
->unitsState
= fxMesa
->restoreUnitsState
;
1528 /* restore texturing */
1529 ctx
->Texture
.Unit
[0]._ReallyEnabled
= t0
;
1530 ctx
->Texture
.Unit
[1]._ReallyEnabled
= t1
;
1531 /* revert to primary colors */
1532 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PARGB_OFFSET
<< 2, GR_PARAM_ENABLE
);
1535 assert(0); /* NOTREACHED */
1538 /* update HW state */
1540 fxSetupDepthTest(ctx
);
1541 fxSetupTexture(ctx
);
1551 * Need this to provide at least one external definition.
1554 extern int gl_fx_dummy_function_tris(void);
1556 gl_fx_dummy_function_tris(void)