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 static GLenum reduced_prim
[GL_POLYGON
+1] = {
79 /***********************************************************************
80 * Macros for t_dd_tritmp.h to draw basic primitives *
81 ***********************************************************************/
83 #define TRI( a, b, c ) \
86 fxMesa->draw_tri( fxMesa, a, b, c ); \
88 grDrawTriangle( a, b, c ); \
91 #define QUAD( a, b, c, d ) \
94 fxMesa->draw_tri( fxMesa, a, b, d ); \
95 fxMesa->draw_tri( fxMesa, b, c, d ); \
102 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
103 /*grDrawTriangle( a, b, d );*/ \
104 /*grDrawTriangle( b, c, d );*/ \
108 #define LINE( v0, v1 ) \
111 fxMesa->draw_line( fxMesa, v0, v1 ); \
113 v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
114 v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
115 v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
116 v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
117 grDrawLine( v0, v1 ); \
118 v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
119 v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
120 v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
121 v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
125 #define POINT( v0 ) \
128 fxMesa->draw_point( fxMesa, v0 ); \
130 v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
131 v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
133 v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
134 v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
139 /***********************************************************************
140 * Fallback to swrast for basic primitives *
141 ***********************************************************************/
143 /* Build an SWvertex from a hardware vertex.
145 * This code is hit only when a mix of accelerated and unaccelerated
146 * primitives are being drawn, and only for the unaccelerated
150 fx_translate_vertex( GLcontext
*ctx
, const GrVertex
*src
, SWvertex
*dst
)
152 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
153 GLuint ts0
= fxMesa
->tmu_source
[0];
154 GLuint ts1
= fxMesa
->tmu_source
[1];
155 GLfloat w
= 1.0 / src
->oow
;
157 dst
->win
[0] = src
->x
;
158 dst
->win
[1] = src
->y
;
159 dst
->win
[2] = src
->ooz
;
160 dst
->win
[3] = src
->oow
;
163 dst
->color
[0] = src
->pargb
[2];
164 dst
->color
[1] = src
->pargb
[1];
165 dst
->color
[2] = src
->pargb
[0];
166 dst
->color
[3] = src
->pargb
[3];
168 dst
->specular
[0] = src
->pspec
[2];
169 dst
->specular
[1] = src
->pspec
[1];
170 dst
->specular
[2] = src
->pspec
[0];
171 #else /* !FX_PACKEDCOLOR */
172 dst
->color
[0] = src
->r
;
173 dst
->color
[1] = src
->g
;
174 dst
->color
[2] = src
->b
;
175 dst
->color
[3] = src
->a
;
177 dst
->specular
[0] = src
->r1
;
178 dst
->specular
[1] = src
->g1
;
179 dst
->specular
[2] = src
->g1
;
180 #endif /* !FX_PACKEDCOLOR */
182 dst
->texcoord
[ts0
][0] = fxMesa
->inv_s0scale
* src
->tmuvtx
[0].sow
* w
;
183 dst
->texcoord
[ts0
][1] = fxMesa
->inv_t0scale
* src
->tmuvtx
[0].tow
* w
;
185 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU0
)
186 dst
->texcoord
[ts0
][3] = src
->tmuvtx
[0].oow
* w
;
188 dst
->texcoord
[ts0
][3] = 1.0;
190 if (fxMesa
->SetupIndex
& SETUP_TMU1
) {
191 dst
->texcoord
[ts1
][0] = fxMesa
->inv_s1scale
* src
->tmuvtx
[1].sow
* w
;
192 dst
->texcoord
[ts1
][1] = fxMesa
->inv_t1scale
* src
->tmuvtx
[1].tow
* w
;
194 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU1
)
195 dst
->texcoord
[ts1
][3] = src
->tmuvtx
[1].oow
* w
;
197 dst
->texcoord
[ts1
][3] = 1.0;
200 dst
->pointSize
= src
->psize
;
205 fx_fallback_tri( fxMesaContext fxMesa
,
210 GLcontext
*ctx
= fxMesa
->glCtx
;
213 fx_translate_vertex( ctx
, v0
, &v
[0] );
214 fx_translate_vertex( ctx
, v1
, &v
[1] );
215 fx_translate_vertex( ctx
, v2
, &v
[2] );
216 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
221 fx_fallback_line( fxMesaContext fxMesa
,
225 GLcontext
*ctx
= fxMesa
->glCtx
;
227 fx_translate_vertex( ctx
, v0
, &v
[0] );
228 fx_translate_vertex( ctx
, v1
, &v
[1] );
229 _swrast_Line( ctx
, &v
[0], &v
[1] );
234 fx_fallback_point( fxMesaContext fxMesa
,
237 GLcontext
*ctx
= fxMesa
->glCtx
;
239 fx_translate_vertex( ctx
, v0
, &v
[0] );
240 _swrast_Point( ctx
, &v
[0] );
243 /***********************************************************************
244 * Functions to draw basic primitives *
245 ***********************************************************************/
247 static void fx_print_vertex( GLcontext
*ctx
, const GrVertex
*v
)
249 fprintf(stderr
, "fx_print_vertex:\n");
251 fprintf(stderr
, "\tvertex at %p\n", (void *) v
);
253 fprintf(stderr
, "\tx %f y %f z %f oow %f\n", v
->x
, v
->y
, v
->ooz
, v
->oow
);
255 fprintf(stderr
, "\tr %d g %d b %d a %d\n", v
->pargb
[2], v
->pargb
[1], v
->pargb
[0], v
->pargb
[3]);
256 #else /* !FX_PACKEDCOLOR */
257 fprintf(stderr
, "\tr %f g %f b %f a %f\n", v
->r
, v
->g
, v
->b
, v
->a
);
258 #endif /* !FX_PACKEDCOLOR */
260 fprintf(stderr
, "\n");
263 #define DO_FALLBACK 0
265 /* Need to do clip loop at each triangle when mixing swrast and hw
266 * rendering. These functions are only used when mixed-mode rendering
269 static void fx_draw_triangle( fxMesaContext fxMesa
,
279 static void fx_draw_line( fxMesaContext fxMesa
,
283 /* No support for wide lines (avoid wide/aa line fallback).
290 static void fx_draw_point( fxMesaContext fxMesa
,
293 /* No support for wide points.
301 #define M_2PI 6.28318530717958647692528676655901
303 #define __GL_COSF cos
304 #define __GL_SINF sin
305 static void fx_draw_point_sprite ( fxMesaContext fxMesa
,
306 GrVertex
*v0
, GLfloat psize
)
308 const GLcontext
*ctx
= fxMesa
->glCtx
;
312 GLuint ts0
= fxMesa
->tmu_source
[0];
313 GLuint ts1
= fxMesa
->tmu_source
[1];
315 GLfloat u0scale
= fxMesa
->s0scale
* w
;
316 GLfloat v0scale
= fxMesa
->t0scale
* w
;
317 GLfloat u1scale
= fxMesa
->s1scale
* w
;
318 GLfloat v1scale
= fxMesa
->t1scale
* w
;
326 /* point coverage? */
327 /* we don't care about culling here (see fxSetupCull) */
329 if (ctx
->Point
.SpriteOrigin
== GL_UPPER_LEFT
) {
349 if (ctx
->Point
.CoordReplace
[ts0
]) {
350 _v_
[0].tmuvtx
[0].sow
= 0;
351 _v_
[0].tmuvtx
[0].tow
= 0;
352 _v_
[1].tmuvtx
[0].sow
= u0scale
;
353 _v_
[1].tmuvtx
[0].tow
= 0;
354 _v_
[2].tmuvtx
[0].sow
= u0scale
;
355 _v_
[2].tmuvtx
[0].tow
= v0scale
;
356 _v_
[3].tmuvtx
[0].sow
= 0;
357 _v_
[3].tmuvtx
[0].tow
= v0scale
;
359 if (ctx
->Point
.CoordReplace
[ts1
]) {
360 _v_
[0].tmuvtx
[1].sow
= 0;
361 _v_
[0].tmuvtx
[1].tow
= 0;
362 _v_
[1].tmuvtx
[1].sow
= u1scale
;
363 _v_
[1].tmuvtx
[1].tow
= 0;
364 _v_
[2].tmuvtx
[1].sow
= u1scale
;
365 _v_
[2].tmuvtx
[1].tow
= v1scale
;
366 _v_
[3].tmuvtx
[1].sow
= 0;
367 _v_
[3].tmuvtx
[1].tow
= v1scale
;
370 grDrawVertexArrayContiguous(GR_TRIANGLE_FAN
, 4, _v_
, sizeof(GrVertex
));
373 static void fx_draw_point_wide ( fxMesaContext fxMesa
,
377 GLfloat ang
, radius
, oon
;
381 const GLcontext
*ctx
= fxMesa
->glCtx
;
382 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
)
383 ? CLAMP(v0
->psize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
)
384 : ctx
->Point
._Size
; /* clamped */
386 if (ctx
->Point
.PointSprite
) {
387 fx_draw_point_sprite(fxMesa
, v0
, psize
);
396 n
= IROUND(psize
* 2); /* radius x 4 */
398 oon
= 1.0 / (GLfloat
)n
;
401 /* point coverage? */
402 /* we don't care about culling here (see fxSetupCull) */
409 vtxC
.x
+= radius
* __GL_COSF(ang
);
410 vtxC
.y
+= radius
* __GL_SINF(ang
);
411 grDrawVertexArray(GR_TRIANGLE_FAN
, 3, _v_
);
412 for (i
= 2; i
<= n
; i
++) {
413 ang
= M_2PI
* i
* oon
;
414 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
415 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
416 grDrawVertexArray(GR_TRIANGLE_FAN_CONTINUE
, 1, &_v_
[2]);
420 static void fx_render_pw_verts( GLcontext
*ctx
,
425 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
426 GrVertex
*fxVB
= fxMesa
->verts
;
429 fxRenderPrimitive( ctx
, GL_POINTS
);
431 for ( ; start
< count
; start
++)
432 fx_draw_point_wide(fxMesa
, fxVB
+ start
);
435 static void fx_render_pw_elts ( GLcontext
*ctx
,
440 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
441 GrVertex
*fxVB
= fxMesa
->verts
;
442 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
445 fxRenderPrimitive( ctx
, GL_POINTS
);
447 for ( ; start
< count
; start
++)
448 fx_draw_point_wide(fxMesa
, fxVB
+ elt
[start
]);
451 static void fx_draw_point_wide_aa ( fxMesaContext fxMesa
,
455 GLfloat ang
, radius
, oon
;
458 const GLcontext
*ctx
= fxMesa
->glCtx
;
459 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
)
460 ? CLAMP(v0
->psize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
)
461 : ctx
->Point
._Size
; /* clamped */
463 if (ctx
->Point
.PointSprite
) {
464 fx_draw_point_sprite(fxMesa
, v0
, psize
);
469 n
= IROUND(psize
* 2); /* radius x 4 */
471 oon
= 1.0 / (GLfloat
)n
;
474 /* point coverage? */
475 /* we don't care about culling here (see fxSetupCull) */
481 for (i
= 1; i
<= n
; i
++) {
482 ang
= M_2PI
* i
* oon
;
483 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
484 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
485 grAADrawTriangle( v0
, &vtxB
, &vtxC
, FXFALSE
, FXTRUE
, FXFALSE
);
486 /*grDrawTriangle( v0, &vtxB, &vtxC);*/
498 #define FX_UNFILLED_BIT 0x1
499 #define FX_OFFSET_BIT 0x2
500 #define FX_TWOSIDE_BIT 0x4
501 #define FX_FLAT_BIT 0x8
502 #define FX_FALLBACK_BIT 0x10
503 #define FX_MAX_TRIFUNC 0x20
506 tnl_points_func points
;
508 tnl_triangle_func triangle
;
510 } rast_tab
[FX_MAX_TRIFUNC
];
512 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
513 #define DO_OFFSET (IND & FX_OFFSET_BIT)
514 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
515 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
516 #define DO_FLAT (IND & FX_FLAT_BIT)
521 #define DO_FULL_QUAD 1
525 #define HAVE_HW_FLATSHADE 0
526 #define HAVE_BACK_COLORS 0
527 #define VERTEX GrVertex
530 #define DEPTH_SCALE 1.0
531 #define UNFILLED_TRI unfilled_tri
532 #define UNFILLED_QUAD unfilled_quad
533 #define VERT_X(_v) _v->x
534 #define VERT_Y(_v) _v->y
535 #define VERT_Z(_v) _v->ooz
536 #define GET_VERTEX(e) (fxMesa->verts + e)
539 #define AREA_IS_CCW( a ) (((fi_type *)&(a))->i < 0)
541 #define AREA_IS_CCW( a ) (a < 0)
546 #define VERT_SET_RGBA( dst, f ) \
548 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[2], f[0]);\
549 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[1], f[1]);\
550 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[0], f[2]);\
551 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[3], f[3]);\
554 #define VERT_COPY_RGBA( v0, v1 ) \
555 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
557 #define VERT_SAVE_RGBA( idx ) \
558 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
560 #define VERT_RESTORE_RGBA( idx ) \
561 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
564 #define VERT_SET_SPEC( dst, f ) \
566 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[2], f[0]);\
567 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[1], f[1]);\
568 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[0], f[2]);\
571 #define VERT_COPY_SPEC( v0, v1 ) \
572 *(GLuint *)&v0->pspec = *(GLuint *)&v1->pspec
574 #define VERT_SAVE_SPEC( idx ) \
575 *(GLuint *)&spec[idx] = *(GLuint *)&v[idx]->pspec
577 #define VERT_RESTORE_SPEC( idx ) \
578 *(GLuint *)&v[idx]->pspec = *(GLuint *)&spec[idx]
581 #define LOCAL_VARS(n) \
582 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
583 GLubyte color[n][4], spec[n][4]; \
584 (void) color; (void) spec;
585 #else /* !FX_PACKEDCOLOR */
586 #define VERT_SET_RGBA( dst, f ) \
588 CNORM(dst->r, f[0]); \
589 CNORM(dst->g, f[1]); \
590 CNORM(dst->b, f[2]); \
591 CNORM(dst->a, f[3]); \
594 #define VERT_COPY_RGBA( v0, v1 ) \
596 *(GLuint *)&v0->r = *(GLuint *)&v1->r; \
597 *(GLuint *)&v0->g = *(GLuint *)&v1->g; \
598 *(GLuint *)&v0->b = *(GLuint *)&v1->b; \
599 *(GLuint *)&v0->a = *(GLuint *)&v1->a; \
602 #define VERT_SAVE_RGBA( idx ) \
604 *(GLuint *)&color[idx][0] = *(GLuint *)&v[idx]->r;\
605 *(GLuint *)&color[idx][1] = *(GLuint *)&v[idx]->g;\
606 *(GLuint *)&color[idx][2] = *(GLuint *)&v[idx]->b;\
607 *(GLuint *)&color[idx][3] = *(GLuint *)&v[idx]->a;\
610 #define VERT_RESTORE_RGBA( idx ) \
612 *(GLuint *)&v[idx]->r = *(GLuint *)&color[idx][0];\
613 *(GLuint *)&v[idx]->g = *(GLuint *)&color[idx][1];\
614 *(GLuint *)&v[idx]->b = *(GLuint *)&color[idx][2];\
615 *(GLuint *)&v[idx]->a = *(GLuint *)&color[idx][3];\
619 #define VERT_SET_SPEC( dst, f ) \
621 CNORM(dst->r1, f[0]); \
622 CNORM(dst->g1, f[1]); \
623 CNORM(dst->b1, f[2]); \
626 #define VERT_COPY_SPEC( v0, v1 ) \
628 *(GLuint *)&v0->r1 = *(GLuint *)&v1->r1; \
629 *(GLuint *)&v0->g1 = *(GLuint *)&v1->g1; \
630 *(GLuint *)&v0->b1 = *(GLuint *)&v1->b1; \
633 #define VERT_SAVE_SPEC( idx ) \
635 *(GLuint *)&spec[idx][0] = *(GLuint *)&v[idx]->r1;\
636 *(GLuint *)&spec[idx][1] = *(GLuint *)&v[idx]->g1;\
637 *(GLuint *)&spec[idx][2] = *(GLuint *)&v[idx]->b1;\
640 #define VERT_RESTORE_SPEC( idx ) \
642 *(GLuint *)&v[idx]->r1 = *(GLuint *)&spec[idx][0];\
643 *(GLuint *)&v[idx]->g1 = *(GLuint *)&spec[idx][1];\
644 *(GLuint *)&v[idx]->b1 = *(GLuint *)&spec[idx][2];\
648 #define LOCAL_VARS(n) \
649 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
650 GLuint color[n][4], spec[n][4]; \
651 (void) color; (void) spec;
652 #endif /* !FX_PACKEDCOLOR */
656 /***********************************************************************
657 * Functions to draw basic unfilled primitives *
658 ***********************************************************************/
660 #define RASTERIZE(x) if (fxMesa->raster_primitive != reduced_prim[x]) \
661 fxRasterPrimitive( ctx, reduced_prim[x] )
662 #define RENDER_PRIMITIVE fxMesa->render_primitive
663 #define IND FX_FALLBACK_BIT
665 #include "tnl_dd/t_dd_unfilled.h"
668 /***********************************************************************
669 * Functions to draw GL primitives *
670 ***********************************************************************/
674 #include "tnl_dd/t_dd_tritmp.h"
676 #define IND (FX_OFFSET_BIT)
677 #define TAG(x) x##_offset
678 #include "tnl_dd/t_dd_tritmp.h"
680 #define IND (FX_TWOSIDE_BIT)
681 #define TAG(x) x##_twoside
682 #include "tnl_dd/t_dd_tritmp.h"
684 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
685 #define TAG(x) x##_twoside_offset
686 #include "tnl_dd/t_dd_tritmp.h"
688 #define IND (FX_UNFILLED_BIT)
689 #define TAG(x) x##_unfilled
690 #include "tnl_dd/t_dd_tritmp.h"
692 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
693 #define TAG(x) x##_offset_unfilled
694 #include "tnl_dd/t_dd_tritmp.h"
696 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
697 #define TAG(x) x##_twoside_unfilled
698 #include "tnl_dd/t_dd_tritmp.h"
700 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
701 #define TAG(x) x##_twoside_offset_unfilled
702 #include "tnl_dd/t_dd_tritmp.h"
704 #define IND (FX_FALLBACK_BIT)
705 #define TAG(x) x##_fallback
706 #include "tnl_dd/t_dd_tritmp.h"
708 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
709 #define TAG(x) x##_offset_fallback
710 #include "tnl_dd/t_dd_tritmp.h"
712 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
713 #define TAG(x) x##_twoside_fallback
714 #include "tnl_dd/t_dd_tritmp.h"
716 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
717 #define TAG(x) x##_twoside_offset_fallback
718 #include "tnl_dd/t_dd_tritmp.h"
720 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
721 #define TAG(x) x##_unfilled_fallback
722 #include "tnl_dd/t_dd_tritmp.h"
724 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
725 #define TAG(x) x##_offset_unfilled_fallback
726 #include "tnl_dd/t_dd_tritmp.h"
728 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
729 #define TAG(x) x##_twoside_unfilled_fallback
730 #include "tnl_dd/t_dd_tritmp.h"
732 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
734 #define TAG(x) x##_twoside_offset_unfilled_fallback
735 #include "tnl_dd/t_dd_tritmp.h"
738 /* Fx doesn't support provoking-vertex flat-shading?
740 #define IND (FX_FLAT_BIT)
741 #define TAG(x) x##_flat
742 #include "tnl_dd/t_dd_tritmp.h"
744 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
745 #define TAG(x) x##_offset_flat
746 #include "tnl_dd/t_dd_tritmp.h"
748 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
749 #define TAG(x) x##_twoside_flat
750 #include "tnl_dd/t_dd_tritmp.h"
752 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
753 #define TAG(x) x##_twoside_offset_flat
754 #include "tnl_dd/t_dd_tritmp.h"
756 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
757 #define TAG(x) x##_unfilled_flat
758 #include "tnl_dd/t_dd_tritmp.h"
760 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
761 #define TAG(x) x##_offset_unfilled_flat
762 #include "tnl_dd/t_dd_tritmp.h"
764 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
765 #define TAG(x) x##_twoside_unfilled_flat
766 #include "tnl_dd/t_dd_tritmp.h"
768 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
769 #define TAG(x) x##_twoside_offset_unfilled_flat
770 #include "tnl_dd/t_dd_tritmp.h"
772 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
773 #define TAG(x) x##_fallback_flat
774 #include "tnl_dd/t_dd_tritmp.h"
776 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
777 #define TAG(x) x##_offset_fallback_flat
778 #include "tnl_dd/t_dd_tritmp.h"
780 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
781 #define TAG(x) x##_twoside_fallback_flat
782 #include "tnl_dd/t_dd_tritmp.h"
784 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
785 #define TAG(x) x##_twoside_offset_fallback_flat
786 #include "tnl_dd/t_dd_tritmp.h"
788 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
789 #define TAG(x) x##_unfilled_fallback_flat
790 #include "tnl_dd/t_dd_tritmp.h"
792 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
793 #define TAG(x) x##_offset_unfilled_fallback_flat
794 #include "tnl_dd/t_dd_tritmp.h"
796 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
797 #define TAG(x) x##_twoside_unfilled_fallback_flat
798 #include "tnl_dd/t_dd_tritmp.h"
800 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
801 FX_FALLBACK_BIT|FX_FLAT_BIT)
802 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
803 #include "tnl_dd/t_dd_tritmp.h"
806 static void init_rast_tab( void )
811 init_twoside_offset();
813 init_offset_unfilled();
814 init_twoside_unfilled();
815 init_twoside_offset_unfilled();
817 init_offset_fallback();
818 init_twoside_fallback();
819 init_twoside_offset_fallback();
820 init_unfilled_fallback();
821 init_offset_unfilled_fallback();
822 init_twoside_unfilled_fallback();
823 init_twoside_offset_unfilled_fallback();
828 init_twoside_offset_flat();
829 init_unfilled_flat();
830 init_offset_unfilled_flat();
831 init_twoside_unfilled_flat();
832 init_twoside_offset_unfilled_flat();
833 init_fallback_flat();
834 init_offset_fallback_flat();
835 init_twoside_fallback_flat();
836 init_twoside_offset_fallback_flat();
837 init_unfilled_fallback_flat();
838 init_offset_unfilled_fallback_flat();
839 init_twoside_unfilled_fallback_flat();
840 init_twoside_offset_unfilled_fallback_flat();
844 /**********************************************************************/
845 /* Render whole begin/end objects */
846 /**********************************************************************/
849 /* Accelerate vertex buffer rendering when renderindex == 0 and
850 * there is no clipping.
852 #define INIT(x) fxRenderPrimitive( ctx, x )
854 static void fx_render_vb_points( GLcontext
*ctx
,
859 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
860 GrVertex
*fxVB
= fxMesa
->verts
;
864 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
865 fprintf(stderr
, "fx_render_vb_points\n");
870 /* Adjust point coords */
871 for (i
= start
; i
< count
; i
++) {
872 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
873 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
876 grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
877 fxVB
+ start
, sizeof(GrVertex
));
878 /* restore point coords */
879 for (i
= start
; i
< count
; i
++) {
880 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
881 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
885 static void fx_render_vb_line_strip( GLcontext
*ctx
,
890 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
891 GrVertex
*fxVB
= fxMesa
->verts
;
895 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
896 fprintf(stderr
, "fx_render_vb_line_strip\n");
901 /* adjust line coords */
902 for (i
= start
; i
< count
; i
++) {
903 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
904 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
907 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
908 fxVB
+ start
, sizeof(GrVertex
));
910 /* restore line coords */
911 for (i
= start
; i
< count
; i
++) {
912 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
913 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
917 static void fx_render_vb_line_loop( GLcontext
*ctx
,
922 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
923 GrVertex
*fxVB
= fxMesa
->verts
;
928 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
929 fprintf(stderr
, "fx_render_vb_line_loop\n");
934 if (!(flags
& PRIM_BEGIN
)) {
938 /* adjust line coords */
939 for (i
= start
; i
< count
; i
++) {
940 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
941 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
944 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
945 fxVB
+ j
, sizeof(GrVertex
));
947 if (flags
& PRIM_END
)
948 grDrawLine( fxVB
+ (count
- 1),
951 /* restore line coords */
952 for (i
= start
; i
< count
; i
++) {
953 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
954 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
958 static void fx_render_vb_lines( GLcontext
*ctx
,
963 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
964 GrVertex
*fxVB
= fxMesa
->verts
;
968 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
969 fprintf(stderr
, "fx_render_vb_lines\n");
974 /* adjust line coords */
975 for (i
= start
; i
< count
; i
++) {
976 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
977 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
980 grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
981 fxVB
+ start
, sizeof(GrVertex
));
983 /* restore line coords */
984 for (i
= start
; i
< count
; i
++) {
985 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
986 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
990 static void fx_render_vb_triangles( GLcontext
*ctx
,
995 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
996 GrVertex
*fxVB
= fxMesa
->verts
;
1000 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1001 fprintf(stderr
, "fx_render_vb_triangles\n");
1006 for (j
=start
+2; j
<count
; j
+=3) {
1007 grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
1012 static void fx_render_vb_tri_strip( GLcontext
*ctx
,
1017 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1018 GrVertex
*fxVB
= fxMesa
->verts
;
1021 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1022 fprintf(stderr
, "fx_render_vb_tri_strip\n");
1025 INIT(GL_TRIANGLE_STRIP
);
1027 /* no GR_TRIANGLE_STRIP_CONTINUE?!? */
1029 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
, count
-start
,
1030 fxVB
+ start
, sizeof(GrVertex
));
1034 static void fx_render_vb_tri_fan( GLcontext
*ctx
,
1039 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1040 GrVertex
*fxVB
= fxMesa
->verts
;
1043 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1044 fprintf(stderr
, "fx_render_vb_tri_fan\n");
1047 INIT(GL_TRIANGLE_FAN
);
1049 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
1050 fxVB
+ start
, sizeof(GrVertex
) );
1053 static void fx_render_vb_quads( GLcontext
*ctx
,
1058 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1059 GrVertex
*fxVB
= fxMesa
->verts
;
1063 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1064 fprintf(stderr
, "fx_render_vb_quads\n");
1069 for (i
= start
+ 3 ; i
< count
; i
+= 4 ) {
1070 #define VERT(x) (fxVB + (x))
1076 grDrawVertexArray(GR_TRIANGLE_FAN
, 4, _v_
);
1077 /*grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
1078 /*grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
1083 static void fx_render_vb_quad_strip( GLcontext
*ctx
,
1088 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1089 GrVertex
*fxVB
= fxMesa
->verts
;
1092 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1093 fprintf(stderr
, "fx_render_vb_quad_strip\n");
1096 INIT(GL_QUAD_STRIP
);
1098 count
-= (count
-start
)&1;
1100 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
1101 count
-start
, fxVB
+ start
, sizeof(GrVertex
));
1104 static void fx_render_vb_poly( GLcontext
*ctx
,
1109 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1110 GrVertex
*fxVB
= fxMesa
->verts
;
1113 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1114 fprintf(stderr
, "fx_render_vb_poly\n");
1119 grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
1120 fxVB
+ start
, sizeof(GrVertex
));
1123 static void fx_render_vb_noop( GLcontext
*ctx
,
1128 (void) (ctx
&& start
&& count
&& flags
);
1131 static void (*fx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
1136 fx_render_vb_points
,
1138 fx_render_vb_line_loop
,
1139 fx_render_vb_line_strip
,
1140 fx_render_vb_triangles
,
1141 fx_render_vb_tri_strip
,
1142 fx_render_vb_tri_fan
,
1144 fx_render_vb_quad_strip
,
1151 /**********************************************************************/
1152 /* Render whole (indexed) begin/end objects */
1153 /**********************************************************************/
1156 #define VERT(x) (vertptr + x)
1158 #define RENDER_POINTS( start, count ) \
1159 for ( ; start < count ; start++) \
1160 grDrawPoint( VERT(ELT(start)) );
1162 #define RENDER_LINE( v0, v1 ) \
1163 grDrawLine( VERT(v0), VERT(v1) )
1165 #define RENDER_TRI( v0, v1, v2 ) \
1166 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
1168 #define RENDER_QUAD( v0, v1, v2, v3 ) \
1175 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
1176 /*grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
1177 /*grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
1180 #define INIT(x) fxRenderPrimitive( ctx, x )
1183 #define LOCAL_VARS \
1184 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
1185 GrVertex *vertptr = fxMesa->verts; \
1186 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
1189 #define RESET_STIPPLE
1190 #define RESET_OCCLUSION
1191 #define PRESERVE_VB_DEFS
1193 /* Elts, no clipping.
1197 #define TAG(x) fx_##x##_elts
1198 #define ELT(x) elt[x]
1199 #include "tnl_dd/t_dd_rendertmp.h"
1201 /* Verts, no clipping.
1205 #define TAG(x) fx_##x##_verts
1207 /*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
1211 /**********************************************************************/
1212 /* Render clipped primitives */
1213 /**********************************************************************/
1217 static void fxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1220 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1221 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1222 struct vertex_buffer
*VB
= &tnl
->vb
;
1223 GLuint prim
= fxMesa
->render_primitive
;
1225 /* Render the new vertices as an unclipped polygon.
1228 GLuint
*tmp
= VB
->Elts
;
1229 VB
->Elts
= (GLuint
*)elts
;
1230 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
1231 PRIM_BEGIN
|PRIM_END
);
1235 /* Restore the render primitive
1237 if (prim
!= GL_POLYGON
)
1238 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
1242 static void fxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1246 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1247 GrVertex
*vertptr
= fxMesa
->verts
;
1249 grDrawTriangle( VERT(elts
[0]), VERT(elts
[1]), VERT(elts
[2]) );
1250 } else if (n
<= 32) {
1251 GrVertex
*newvptr
[32];
1252 for (i
= 0 ; i
< n
; i
++) {
1253 newvptr
[i
] = VERT(elts
[i
]);
1255 grDrawVertexArray(GR_TRIANGLE_FAN
, n
, newvptr
);
1257 const GrVertex
*start
= VERT(elts
[0]);
1258 for (i
= 2 ; i
< n
; i
++) {
1259 grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
1264 /**********************************************************************/
1265 /* Choose render functions */
1266 /**********************************************************************/
1269 #define POINT_FALLBACK (DD_POINT_SMOOTH)
1270 #define LINE_FALLBACK (DD_LINE_STIPPLE)
1271 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
1272 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
1273 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
1278 void fxDDChooseRenderState(GLcontext
*ctx
)
1280 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1281 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1282 GLuint flags
= ctx
->_TriangleCaps
;
1285 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
1286 if (flags
& ANY_RASTER_FLAGS
) {
1287 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= FX_TWOSIDE_BIT
;
1288 if (flags
& DD_TRI_OFFSET
) index
|= FX_OFFSET_BIT
;
1289 if (flags
& DD_TRI_UNFILLED
) index
|= FX_UNFILLED_BIT
;
1290 if (flags
& DD_FLATSHADE
) index
|= FX_FLAT_BIT
;
1293 fxMesa
->draw_point
= fx_draw_point
;
1294 fxMesa
->draw_line
= fx_draw_line
;
1295 fxMesa
->draw_tri
= fx_draw_triangle
;
1297 /* Hook in fallbacks for specific primitives. */
1298 if (flags
& (POINT_FALLBACK
|
1302 if (fxMesa
->verbose
) {
1303 fprintf(stderr
, "Voodoo ! fallback (%x), raster (%x)\n",
1304 flags
& ANY_FALLBACK_FLAGS
, flags
& ANY_RASTER_FLAGS
);
1307 if (flags
& POINT_FALLBACK
)
1308 fxMesa
->draw_point
= fx_fallback_point
;
1310 if (flags
& LINE_FALLBACK
)
1311 fxMesa
->draw_line
= fx_fallback_line
;
1313 if (flags
& TRI_FALLBACK
)
1314 fxMesa
->draw_tri
= fx_fallback_tri
;
1316 index
|= FX_FALLBACK_BIT
;
1320 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1321 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1322 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
1323 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1324 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1327 tnl
->Driver
.Render
.PrimTabVerts
= fx_render_tab_verts
;
1328 tnl
->Driver
.Render
.PrimTabElts
= fx_render_tab_elts
;
1329 tnl
->Driver
.Render
.ClippedPolygon
= fxFastRenderClippedPoly
;
1331 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1332 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1333 tnl
->Driver
.Render
.ClippedPolygon
= fxRenderClippedPoly
;
1336 fxMesa
->render_index
= index
;
1338 /* [dBorca] Hack alert: more a trick than a real plug-in!!! */
1339 if (flags
& (DD_POINT_SIZE
| DD_POINT_ATTEN
)) {
1340 /* We need to set the point primitive to go through "rast_tab",
1341 * to make sure "POINT" calls "fxMesa->draw_point" instead of
1342 * "grDrawPoint". We can achieve this by using FX_FALLBACK_BIT
1343 * (not really a total rasterization fallback, so we don't alter
1344 * "fxMesa->render_index"). If we get here with DD_POINT_SMOOTH,
1345 * we're done, cos we've already set _tnl_render_tab_{verts|elts}
1346 * above. Otherwise, the T&L engine can optimize point rendering
1347 * by using fx_render_tab_{verts|elts} hence the extra work.
1349 if (flags
& DD_POINT_SMOOTH
) {
1350 fxMesa
->draw_point
= fx_draw_point_wide_aa
;
1352 fxMesa
->draw_point
= fx_draw_point_wide
;
1353 fx_render_tab_verts
[0] = fx_render_pw_verts
;
1354 fx_render_tab_elts
[0] = fx_render_pw_elts
;
1356 tnl
->Driver
.Render
.Points
= rast_tab
[index
|FX_FALLBACK_BIT
].points
;
1358 fx_render_tab_verts
[0] = fx_render_vb_points
;
1359 fx_render_tab_elts
[0] = fx_render_points_elts
;
1364 /**********************************************************************/
1365 /* Runtime render state and callbacks */
1366 /**********************************************************************/
1368 static void fxRunPipeline( GLcontext
*ctx
)
1370 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1371 GLuint new_gl_state
= fxMesa
->new_gl_state
;
1373 if (TDFX_DEBUG
& VERBOSE_PIPELINE
) {
1374 fprintf(stderr
, "fxRunPipeline()\n");
1378 /* Recalculate fog table on projection matrix changes. This used to
1379 * be triggered by the NearFar callback.
1381 if (new_gl_state
& _NEW_PROJECTION
)
1382 fxMesa
->new_state
|= FX_NEW_FOG
;
1385 if (new_gl_state
& _FX_NEW_IS_IN_HARDWARE
)
1386 fxCheckIsInHardware(ctx
);
1388 if (fxMesa
->new_state
)
1389 fxSetupFXUnits(ctx
);
1391 if (!fxMesa
->fallback
) {
1392 if (new_gl_state
& _FX_NEW_RENDERSTATE
)
1393 fxDDChooseRenderState(ctx
);
1395 if (new_gl_state
& _FX_NEW_SETUP_FUNCTION
)
1396 fxChooseVertexState(ctx
);
1399 if (new_gl_state
& _NEW_TEXTURE
) {
1400 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
1401 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
1403 if (t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
1404 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
1405 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
1406 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
1407 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
1410 if (t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
1411 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
1412 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
1413 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
1414 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
1418 fxMesa
->new_gl_state
= 0;
1420 _tnl_run_pipeline( ctx
);
1425 /* Always called between RenderStart and RenderFinish --> We already
1428 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1430 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1432 fxMesa
->raster_primitive
= prim
;
1439 /* Determine the rasterized primitive when not drawing unfilled
1442 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1444 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1445 GLuint rprim
= reduced_prim
[prim
];
1447 fxMesa
->render_primitive
= prim
;
1449 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1452 if (fxMesa
->raster_primitive
!= rprim
) {
1453 fxRasterPrimitive( ctx
, rprim
);
1457 static void fxRenderFinish( GLcontext
*ctx
)
1459 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1461 if (fxMesa
->render_index
& FX_FALLBACK_BIT
)
1462 _swrast_flush( ctx
);
1467 /**********************************************************************/
1468 /* Manage total rasterization fallbacks */
1469 /**********************************************************************/
1471 static char *fallbackStrings
[] = {
1472 "3D/Rect/Cube Texture map",
1473 "glDrawBuffer(GL_FRONT_AND_BACK)",
1474 "Separate specular color",
1475 "glEnable/Disable(GL_STENCIL_TEST)",
1476 "glRenderMode(selection or feedback)",
1486 static char *getFallbackString(GLuint bit
)
1493 return fallbackStrings
[i
];
1497 void fxCheckIsInHardware( GLcontext
*ctx
)
1499 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1500 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1501 GLuint oldfallback
= fxMesa
->fallback
;
1502 GLuint newfallback
= fxMesa
->fallback
= fx_check_IsInHardware( ctx
);
1505 if (oldfallback
== 0) {
1506 if (fxMesa
->verbose
) {
1507 fprintf(stderr
, "Voodoo ! enter SW 0x%08x %s\n", newfallback
, getFallbackString(newfallback
));
1509 _swsetup_Wakeup( ctx
);
1514 _swrast_flush( ctx
);
1515 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1516 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1517 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1518 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1519 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1520 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1521 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1522 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1523 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1524 fxChooseVertexState(ctx
);
1525 fxDDChooseRenderState(ctx
);
1526 if (fxMesa
->verbose
) {
1527 fprintf(stderr
, "Voodoo ! leave SW 0x%08x %s\n", oldfallback
, getFallbackString(oldfallback
));
1530 tnl
->Driver
.Render
.Multipass
= (HAVE_SPEC
&& NEED_SECONDARY_COLOR(ctx
)) ? fxMultipass_ColorSum
: NULL
;
1534 void fxDDInitTriFuncs( GLcontext
*ctx
)
1536 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1537 static int firsttime
= 1;
1544 tnl
->Driver
.RunPipeline
= fxRunPipeline
;
1545 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1546 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1547 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1548 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1549 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1550 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1551 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1552 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1553 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1554 tnl
->Driver
.Render
.Multipass
= NULL
;
1556 (void) fx_print_vertex
;
1560 /* [dBorca] Hack alert:
1561 * doesn't work with blending.
1562 * XXX todo - need to take care of stencil.
1564 GLboolean
fxMultipass_ColorSum (GLcontext
*ctx
, GLuint pass
)
1566 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1572 case 1: /* first pass: the TEXTURED triangles are drawn */
1573 /* save per-pass data */
1574 fxMesa
->restoreUnitsState
= fxMesa
->unitsState
;
1575 /* turn off texturing */
1576 t0
= ctx
->Texture
.Unit
[0]._ReallyEnabled
;
1577 t1
= ctx
->Texture
.Unit
[1]._ReallyEnabled
;
1578 ctx
->Texture
.Unit
[0]._ReallyEnabled
= 0;
1579 ctx
->Texture
.Unit
[1]._ReallyEnabled
= 0;
1580 /* SUM the colors */
1581 fxDDBlendEquationSeparate(ctx
, GL_FUNC_ADD
, GL_FUNC_ADD
);
1582 fxDDBlendFuncSeparate(ctx
, GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
1583 fxDDEnable(ctx
, GL_BLEND
, GL_TRUE
);
1584 /* make sure we draw only where we want to */
1585 if (ctx
->Depth
.Mask
) {
1586 switch (ctx
->Depth
.Func
) {
1591 fxDDDepthFunc( ctx
, GL_EQUAL
);
1594 fxDDDepthMask( ctx
, GL_FALSE
);
1596 /* switch to secondary colors */
1598 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PSPEC_OFFSET
<< 2, GR_PARAM_ENABLE
);
1599 #else /* !FX_PACKEDCOLOR */
1600 grVertexLayout(GR_PARAM_RGB
, GR_VERTEX_SPEC_OFFSET
<< 2, GR_PARAM_ENABLE
);
1601 #endif /* !FX_PACKEDCOLOR */
1602 /* don't advertise new state */
1603 fxMesa
->new_state
= 0;
1605 case 2: /* 2nd pass (last): the secondary color is summed over texture */
1606 /* restore original state */
1607 fxMesa
->unitsState
= fxMesa
->restoreUnitsState
;
1608 /* restore texturing */
1609 ctx
->Texture
.Unit
[0]._ReallyEnabled
= t0
;
1610 ctx
->Texture
.Unit
[1]._ReallyEnabled
= t1
;
1611 /* revert to primary colors */
1613 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PARGB_OFFSET
<< 2, GR_PARAM_ENABLE
);
1614 #else /* !FX_PACKEDCOLOR */
1615 grVertexLayout(GR_PARAM_RGB
, GR_VERTEX_RGB_OFFSET
<< 2, GR_PARAM_ENABLE
);
1616 #endif /* !FX_PACKEDCOLOR */
1619 assert(0); /* NOTREACHED */
1622 /* update HW state */
1624 fxSetupDepthTest(ctx
);
1625 fxSetupTexture(ctx
);
1635 * Need this to provide at least one external definition.
1638 extern int gl_fx_dummy_function_tris(void);
1640 gl_fx_dummy_function_tris(void)