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) */
301 if (ctx
->Point
.SpriteOrigin
== GL_UPPER_LEFT
) {
321 if (ctx
->Point
.CoordReplace
[ts0
]) {
322 _v_
[0].tmuvtx
[0].sow
= 0;
323 _v_
[0].tmuvtx
[0].tow
= 0;
324 _v_
[1].tmuvtx
[0].sow
= u0scale
;
325 _v_
[1].tmuvtx
[0].tow
= 0;
326 _v_
[2].tmuvtx
[0].sow
= u0scale
;
327 _v_
[2].tmuvtx
[0].tow
= v0scale
;
328 _v_
[3].tmuvtx
[0].sow
= 0;
329 _v_
[3].tmuvtx
[0].tow
= v0scale
;
331 if (ctx
->Point
.CoordReplace
[ts1
]) {
332 _v_
[0].tmuvtx
[1].sow
= 0;
333 _v_
[0].tmuvtx
[1].tow
= 0;
334 _v_
[1].tmuvtx
[1].sow
= u1scale
;
335 _v_
[1].tmuvtx
[1].tow
= 0;
336 _v_
[2].tmuvtx
[1].sow
= u1scale
;
337 _v_
[2].tmuvtx
[1].tow
= v1scale
;
338 _v_
[3].tmuvtx
[1].sow
= 0;
339 _v_
[3].tmuvtx
[1].tow
= v1scale
;
342 grDrawVertexArrayContiguous(GR_TRIANGLE_FAN
, 4, _v_
, sizeof(GrVertex
));
345 static void fx_draw_point_wide ( fxMesaContext fxMesa
,
349 GLfloat ang
, radius
, oon
;
353 const GLcontext
*ctx
= fxMesa
->glCtx
;
354 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
)
355 ? CLAMP(v0
->psize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
)
356 : ctx
->Point
._Size
; /* clamped */
358 if (ctx
->Point
.PointSprite
) {
359 fx_draw_point_sprite(fxMesa
, v0
, psize
);
368 n
= IROUND(psize
* 2); /* radius x 4 */
370 oon
= 1.0 / (GLfloat
)n
;
373 /* point coverage? */
374 /* we don't care about culling here (see fxSetupCull) */
381 vtxC
.x
+= radius
* __GL_COSF(ang
);
382 vtxC
.y
+= radius
* __GL_SINF(ang
);
383 grDrawVertexArray(GR_TRIANGLE_FAN
, 3, _v_
);
384 for (i
= 2; i
<= n
; i
++) {
385 ang
= M_2PI
* i
* oon
;
386 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
387 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
388 grDrawVertexArray(GR_TRIANGLE_FAN_CONTINUE
, 1, &_v_
[2]);
392 static void fx_render_pw_verts( GLcontext
*ctx
,
397 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
398 GrVertex
*fxVB
= fxMesa
->verts
;
401 fxRenderPrimitive( ctx
, GL_POINTS
);
403 for ( ; start
< count
; start
++)
404 fx_draw_point_wide(fxMesa
, fxVB
+ start
);
407 static void fx_render_pw_elts ( GLcontext
*ctx
,
412 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
413 GrVertex
*fxVB
= fxMesa
->verts
;
414 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
417 fxRenderPrimitive( ctx
, GL_POINTS
);
419 for ( ; start
< count
; start
++)
420 fx_draw_point_wide(fxMesa
, fxVB
+ elt
[start
]);
423 static void fx_draw_point_wide_aa ( fxMesaContext fxMesa
,
427 GLfloat ang
, radius
, oon
;
430 const GLcontext
*ctx
= fxMesa
->glCtx
;
431 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
)
432 ? CLAMP(v0
->psize
, ctx
->Point
.MinSize
, ctx
->Point
.MaxSize
)
433 : ctx
->Point
._Size
; /* clamped */
435 if (ctx
->Point
.PointSprite
) {
436 fx_draw_point_sprite(fxMesa
, v0
, psize
);
441 n
= IROUND(psize
* 2); /* radius x 4 */
443 oon
= 1.0 / (GLfloat
)n
;
446 /* point coverage? */
447 /* we don't care about culling here (see fxSetupCull) */
453 for (i
= 1; i
<= n
; i
++) {
454 ang
= M_2PI
* i
* oon
;
455 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
456 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
457 grAADrawTriangle( v0
, &vtxB
, &vtxC
, FXFALSE
, FXTRUE
, FXFALSE
);
458 /*grDrawTriangle( v0, &vtxB, &vtxC);*/
470 #define FX_UNFILLED_BIT 0x1
471 #define FX_OFFSET_BIT 0x2
472 #define FX_TWOSIDE_BIT 0x4
473 #define FX_FLAT_BIT 0x8
474 #define FX_FALLBACK_BIT 0x10
475 #define FX_MAX_TRIFUNC 0x20
478 tnl_points_func points
;
480 tnl_triangle_func triangle
;
482 } rast_tab
[FX_MAX_TRIFUNC
];
484 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
485 #define DO_OFFSET (IND & FX_OFFSET_BIT)
486 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
487 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
488 #define DO_FLAT (IND & FX_FLAT_BIT)
493 #define DO_FULL_QUAD 1
497 #define HAVE_HW_FLATSHADE 0
498 #define HAVE_BACK_COLORS 0
499 #define VERTEX GrVertex
502 #define DEPTH_SCALE 1.0
503 #define UNFILLED_TRI unfilled_tri
504 #define UNFILLED_QUAD unfilled_quad
505 #define VERT_X(_v) _v->x
506 #define VERT_Y(_v) _v->y
507 #define VERT_Z(_v) _v->ooz
508 #define GET_VERTEX(e) (fxMesa->verts + e)
511 #define AREA_IS_CCW( a ) (((fi_type *)&(a))->i < 0)
513 #define AREA_IS_CCW( a ) (a < 0)
517 #define VERT_SET_RGBA( dst, f ) \
519 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[2], f[0]);\
520 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[1], f[1]);\
521 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[0], f[2]);\
522 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[3], f[3]);\
525 #define VERT_COPY_RGBA( v0, v1 ) \
526 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
528 #define VERT_SAVE_RGBA( idx ) \
529 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
531 #define VERT_RESTORE_RGBA( idx ) \
532 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
535 #define VERT_SET_SPEC( dst, f ) \
537 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[2], f[0]);\
538 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[1], f[1]);\
539 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[0], f[2]);\
542 #define VERT_COPY_SPEC( v0, v1 ) \
543 *(GLuint *)&v0->pspec = *(GLuint *)&v1->pspec
545 #define VERT_SAVE_SPEC( idx ) \
546 *(GLuint *)&spec[idx] = *(GLuint *)&v[idx]->pspec
548 #define VERT_RESTORE_SPEC( idx ) \
549 *(GLuint *)&v[idx]->pspec = *(GLuint *)&spec[idx]
552 #define LOCAL_VARS(n) \
553 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
554 GLubyte color[n][4], spec[n][4]; \
555 (void) color; (void) spec;
559 /***********************************************************************
560 * Functions to draw basic unfilled primitives *
561 ***********************************************************************/
563 #define RASTERIZE(x) if (fxMesa->raster_primitive != x) \
564 fxRasterPrimitive( ctx, x )
565 #define RENDER_PRIMITIVE fxMesa->render_primitive
566 #define IND FX_FALLBACK_BIT
568 #include "tnl_dd/t_dd_unfilled.h"
571 /***********************************************************************
572 * Functions to draw GL primitives *
573 ***********************************************************************/
577 #include "tnl_dd/t_dd_tritmp.h"
579 #define IND (FX_OFFSET_BIT)
580 #define TAG(x) x##_offset
581 #include "tnl_dd/t_dd_tritmp.h"
583 #define IND (FX_TWOSIDE_BIT)
584 #define TAG(x) x##_twoside
585 #include "tnl_dd/t_dd_tritmp.h"
587 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
588 #define TAG(x) x##_twoside_offset
589 #include "tnl_dd/t_dd_tritmp.h"
591 #define IND (FX_UNFILLED_BIT)
592 #define TAG(x) x##_unfilled
593 #include "tnl_dd/t_dd_tritmp.h"
595 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
596 #define TAG(x) x##_offset_unfilled
597 #include "tnl_dd/t_dd_tritmp.h"
599 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
600 #define TAG(x) x##_twoside_unfilled
601 #include "tnl_dd/t_dd_tritmp.h"
603 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
604 #define TAG(x) x##_twoside_offset_unfilled
605 #include "tnl_dd/t_dd_tritmp.h"
607 #define IND (FX_FALLBACK_BIT)
608 #define TAG(x) x##_fallback
609 #include "tnl_dd/t_dd_tritmp.h"
611 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
612 #define TAG(x) x##_offset_fallback
613 #include "tnl_dd/t_dd_tritmp.h"
615 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
616 #define TAG(x) x##_twoside_fallback
617 #include "tnl_dd/t_dd_tritmp.h"
619 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
620 #define TAG(x) x##_twoside_offset_fallback
621 #include "tnl_dd/t_dd_tritmp.h"
623 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
624 #define TAG(x) x##_unfilled_fallback
625 #include "tnl_dd/t_dd_tritmp.h"
627 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
628 #define TAG(x) x##_offset_unfilled_fallback
629 #include "tnl_dd/t_dd_tritmp.h"
631 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
632 #define TAG(x) x##_twoside_unfilled_fallback
633 #include "tnl_dd/t_dd_tritmp.h"
635 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
637 #define TAG(x) x##_twoside_offset_unfilled_fallback
638 #include "tnl_dd/t_dd_tritmp.h"
641 /* Fx doesn't support provoking-vertex flat-shading?
643 #define IND (FX_FLAT_BIT)
644 #define TAG(x) x##_flat
645 #include "tnl_dd/t_dd_tritmp.h"
647 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
648 #define TAG(x) x##_offset_flat
649 #include "tnl_dd/t_dd_tritmp.h"
651 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
652 #define TAG(x) x##_twoside_flat
653 #include "tnl_dd/t_dd_tritmp.h"
655 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
656 #define TAG(x) x##_twoside_offset_flat
657 #include "tnl_dd/t_dd_tritmp.h"
659 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
660 #define TAG(x) x##_unfilled_flat
661 #include "tnl_dd/t_dd_tritmp.h"
663 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
664 #define TAG(x) x##_offset_unfilled_flat
665 #include "tnl_dd/t_dd_tritmp.h"
667 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
668 #define TAG(x) x##_twoside_unfilled_flat
669 #include "tnl_dd/t_dd_tritmp.h"
671 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
672 #define TAG(x) x##_twoside_offset_unfilled_flat
673 #include "tnl_dd/t_dd_tritmp.h"
675 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
676 #define TAG(x) x##_fallback_flat
677 #include "tnl_dd/t_dd_tritmp.h"
679 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
680 #define TAG(x) x##_offset_fallback_flat
681 #include "tnl_dd/t_dd_tritmp.h"
683 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
684 #define TAG(x) x##_twoside_fallback_flat
685 #include "tnl_dd/t_dd_tritmp.h"
687 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
688 #define TAG(x) x##_twoside_offset_fallback_flat
689 #include "tnl_dd/t_dd_tritmp.h"
691 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
692 #define TAG(x) x##_unfilled_fallback_flat
693 #include "tnl_dd/t_dd_tritmp.h"
695 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
696 #define TAG(x) x##_offset_unfilled_fallback_flat
697 #include "tnl_dd/t_dd_tritmp.h"
699 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
700 #define TAG(x) x##_twoside_unfilled_fallback_flat
701 #include "tnl_dd/t_dd_tritmp.h"
703 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
704 FX_FALLBACK_BIT|FX_FLAT_BIT)
705 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
706 #include "tnl_dd/t_dd_tritmp.h"
709 static void init_rast_tab( void )
714 init_twoside_offset();
716 init_offset_unfilled();
717 init_twoside_unfilled();
718 init_twoside_offset_unfilled();
720 init_offset_fallback();
721 init_twoside_fallback();
722 init_twoside_offset_fallback();
723 init_unfilled_fallback();
724 init_offset_unfilled_fallback();
725 init_twoside_unfilled_fallback();
726 init_twoside_offset_unfilled_fallback();
731 init_twoside_offset_flat();
732 init_unfilled_flat();
733 init_offset_unfilled_flat();
734 init_twoside_unfilled_flat();
735 init_twoside_offset_unfilled_flat();
736 init_fallback_flat();
737 init_offset_fallback_flat();
738 init_twoside_fallback_flat();
739 init_twoside_offset_fallback_flat();
740 init_unfilled_fallback_flat();
741 init_offset_unfilled_fallback_flat();
742 init_twoside_unfilled_fallback_flat();
743 init_twoside_offset_unfilled_fallback_flat();
747 /**********************************************************************/
748 /* Render whole begin/end objects */
749 /**********************************************************************/
752 /* Accelerate vertex buffer rendering when renderindex == 0 and
753 * there is no clipping.
755 #define INIT(x) fxRenderPrimitive( ctx, x )
757 static void fx_render_vb_points( GLcontext
*ctx
,
762 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
763 GrVertex
*fxVB
= fxMesa
->verts
;
767 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
768 fprintf(stderr
, "fx_render_vb_points\n");
773 /* Adjust point coords */
774 for (i
= start
; i
< count
; i
++) {
775 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
776 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
779 grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
780 fxVB
+ start
, sizeof(GrVertex
));
781 /* restore point coords */
782 for (i
= start
; i
< count
; i
++) {
783 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
784 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
788 static void fx_render_vb_line_strip( GLcontext
*ctx
,
793 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
794 GrVertex
*fxVB
= fxMesa
->verts
;
798 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
799 fprintf(stderr
, "fx_render_vb_line_strip\n");
804 /* adjust line coords */
805 for (i
= start
; i
< count
; i
++) {
806 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
807 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
810 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
811 fxVB
+ start
, sizeof(GrVertex
));
813 /* restore line coords */
814 for (i
= start
; i
< count
; i
++) {
815 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
816 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
820 static void fx_render_vb_line_loop( GLcontext
*ctx
,
825 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
826 GrVertex
*fxVB
= fxMesa
->verts
;
831 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
832 fprintf(stderr
, "fx_render_vb_line_loop\n");
837 if (!(flags
& PRIM_BEGIN
)) {
841 /* adjust line coords */
842 for (i
= start
; i
< count
; i
++) {
843 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
844 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
847 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
848 fxVB
+ j
, sizeof(GrVertex
));
850 if (flags
& PRIM_END
)
851 grDrawLine( fxVB
+ (count
- 1),
854 /* restore line coords */
855 for (i
= start
; i
< count
; i
++) {
856 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
857 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
861 static void fx_render_vb_lines( GLcontext
*ctx
,
866 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
867 GrVertex
*fxVB
= fxMesa
->verts
;
871 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
872 fprintf(stderr
, "fx_render_vb_lines\n");
877 /* adjust line coords */
878 for (i
= start
; i
< count
; i
++) {
879 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
880 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
883 grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
884 fxVB
+ start
, sizeof(GrVertex
));
886 /* restore line coords */
887 for (i
= start
; i
< count
; i
++) {
888 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
889 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
893 static void fx_render_vb_triangles( GLcontext
*ctx
,
898 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
899 GrVertex
*fxVB
= fxMesa
->verts
;
903 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
904 fprintf(stderr
, "fx_render_vb_triangles\n");
909 for (j
=start
+2; j
<count
; j
+=3) {
910 grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
915 static void fx_render_vb_tri_strip( GLcontext
*ctx
,
920 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
921 GrVertex
*fxVB
= fxMesa
->verts
;
924 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
925 fprintf(stderr
, "fx_render_vb_tri_strip\n");
928 INIT(GL_TRIANGLE_STRIP
);
930 /* no GR_TRIANGLE_STRIP_CONTINUE?!? */
932 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
, count
-start
,
933 fxVB
+ start
, sizeof(GrVertex
));
937 static void fx_render_vb_tri_fan( GLcontext
*ctx
,
942 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
943 GrVertex
*fxVB
= fxMesa
->verts
;
946 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
947 fprintf(stderr
, "fx_render_vb_tri_fan\n");
950 INIT(GL_TRIANGLE_FAN
);
952 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
953 fxVB
+ start
, sizeof(GrVertex
) );
956 static void fx_render_vb_quads( GLcontext
*ctx
,
961 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
962 GrVertex
*fxVB
= fxMesa
->verts
;
966 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
967 fprintf(stderr
, "fx_render_vb_quads\n");
972 for (i
= start
+ 3 ; i
< count
; i
+= 4 ) {
973 #define VERT(x) (fxVB + (x))
979 grDrawVertexArray(GR_TRIANGLE_FAN
, 4, _v_
);
980 /*grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
981 /*grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
986 static void fx_render_vb_quad_strip( GLcontext
*ctx
,
991 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
992 GrVertex
*fxVB
= fxMesa
->verts
;
995 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
996 fprintf(stderr
, "fx_render_vb_quad_strip\n");
1001 count
-= (count
-start
)&1;
1003 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
1004 count
-start
, fxVB
+ start
, sizeof(GrVertex
));
1007 static void fx_render_vb_poly( GLcontext
*ctx
,
1012 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1013 GrVertex
*fxVB
= fxMesa
->verts
;
1016 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
1017 fprintf(stderr
, "fx_render_vb_poly\n");
1022 grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
1023 fxVB
+ start
, sizeof(GrVertex
));
1026 static void fx_render_vb_noop( GLcontext
*ctx
,
1031 (void) (ctx
&& start
&& count
&& flags
);
1034 static void (*fx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
1039 fx_render_vb_points
,
1041 fx_render_vb_line_loop
,
1042 fx_render_vb_line_strip
,
1043 fx_render_vb_triangles
,
1044 fx_render_vb_tri_strip
,
1045 fx_render_vb_tri_fan
,
1047 fx_render_vb_quad_strip
,
1054 /**********************************************************************/
1055 /* Render whole (indexed) begin/end objects */
1056 /**********************************************************************/
1059 #define VERT(x) (vertptr + x)
1061 #define RENDER_POINTS( start, count ) \
1062 for ( ; start < count ; start++) \
1063 grDrawPoint( VERT(ELT(start)) );
1065 #define RENDER_LINE( v0, v1 ) \
1066 grDrawLine( VERT(v0), VERT(v1) )
1068 #define RENDER_TRI( v0, v1, v2 ) \
1069 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
1071 #define RENDER_QUAD( v0, v1, v2, v3 ) \
1078 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
1079 /*grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
1080 /*grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
1083 #define INIT(x) fxRenderPrimitive( ctx, x )
1086 #define LOCAL_VARS \
1087 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
1088 GrVertex *vertptr = fxMesa->verts; \
1089 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
1092 #define RESET_STIPPLE
1093 #define RESET_OCCLUSION
1094 #define PRESERVE_VB_DEFS
1096 /* Elts, no clipping.
1100 #define TAG(x) fx_##x##_elts
1101 #define ELT(x) elt[x]
1102 #include "tnl_dd/t_dd_rendertmp.h"
1104 /* Verts, no clipping.
1108 #define TAG(x) fx_##x##_verts
1110 /*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
1114 /**********************************************************************/
1115 /* Render clipped primitives */
1116 /**********************************************************************/
1120 static void fxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1123 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1124 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1125 struct vertex_buffer
*VB
= &tnl
->vb
;
1126 GLuint prim
= fxMesa
->render_primitive
;
1128 /* Render the new vertices as an unclipped polygon.
1131 GLuint
*tmp
= VB
->Elts
;
1132 VB
->Elts
= (GLuint
*)elts
;
1133 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
1134 PRIM_BEGIN
|PRIM_END
);
1138 /* Restore the render primitive
1140 if (prim
!= GL_POLYGON
)
1141 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
1145 static void fxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1149 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1150 GrVertex
*vertptr
= fxMesa
->verts
;
1152 grDrawTriangle( VERT(elts
[0]), VERT(elts
[1]), VERT(elts
[2]) );
1153 } else if (n
<= 32) {
1154 GrVertex
*newvptr
[32];
1155 for (i
= 0 ; i
< n
; i
++) {
1156 newvptr
[i
] = VERT(elts
[i
]);
1158 grDrawVertexArray(GR_TRIANGLE_FAN
, n
, newvptr
);
1160 const GrVertex
*start
= VERT(elts
[0]);
1161 for (i
= 2 ; i
< n
; i
++) {
1162 grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
1167 /**********************************************************************/
1168 /* Choose render functions */
1169 /**********************************************************************/
1172 #define POINT_FALLBACK (DD_POINT_SMOOTH)
1173 #define LINE_FALLBACK (DD_LINE_STIPPLE)
1174 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
1175 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
1176 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
1181 void fxDDChooseRenderState(GLcontext
*ctx
)
1183 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1184 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1185 GLuint flags
= ctx
->_TriangleCaps
;
1188 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
1189 if (flags
& ANY_RASTER_FLAGS
) {
1190 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= FX_TWOSIDE_BIT
;
1191 if (flags
& DD_TRI_OFFSET
) index
|= FX_OFFSET_BIT
;
1192 if (flags
& DD_TRI_UNFILLED
) index
|= FX_UNFILLED_BIT
;
1193 if (flags
& DD_FLATSHADE
) index
|= FX_FLAT_BIT
;
1196 fxMesa
->draw_point
= fx_draw_point
;
1197 fxMesa
->draw_line
= fx_draw_line
;
1198 fxMesa
->draw_tri
= fx_draw_triangle
;
1200 /* Hook in fallbacks for specific primitives. */
1201 if (flags
& (POINT_FALLBACK
|
1205 if (fxMesa
->verbose
) {
1206 fprintf(stderr
, "Voodoo ! fallback (%x), raster (%x)\n",
1207 flags
& ANY_FALLBACK_FLAGS
, flags
& ANY_RASTER_FLAGS
);
1210 if (flags
& POINT_FALLBACK
)
1211 fxMesa
->draw_point
= fx_fallback_point
;
1213 if (flags
& LINE_FALLBACK
)
1214 fxMesa
->draw_line
= fx_fallback_line
;
1216 if (flags
& TRI_FALLBACK
)
1217 fxMesa
->draw_tri
= fx_fallback_tri
;
1219 index
|= FX_FALLBACK_BIT
;
1223 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1224 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1225 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
1226 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1227 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1230 tnl
->Driver
.Render
.PrimTabVerts
= fx_render_tab_verts
;
1231 tnl
->Driver
.Render
.PrimTabElts
= fx_render_tab_elts
;
1232 tnl
->Driver
.Render
.ClippedPolygon
= fxFastRenderClippedPoly
;
1234 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1235 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1236 tnl
->Driver
.Render
.ClippedPolygon
= fxRenderClippedPoly
;
1239 fxMesa
->render_index
= index
;
1241 /* [dBorca] Hack alert: more a trick than a real plug-in!!! */
1242 if (flags
& (DD_POINT_SIZE
| DD_POINT_ATTEN
)) {
1243 /* We need to set the point primitive to go through "rast_tab",
1244 * to make sure "POINT" calls "fxMesa->draw_point" instead of
1245 * "grDrawPoint". We can achieve this by using FX_FALLBACK_BIT
1246 * (not really a total rasterization fallback, so we don't alter
1247 * "fxMesa->render_index"). If we get here with DD_POINT_SMOOTH,
1248 * we're done, cos we've already set _tnl_render_tab_{verts|elts}
1249 * above. Otherwise, the T&L engine can optimize point rendering
1250 * by using fx_render_tab_{verts|elts} hence the extra work.
1252 if (flags
& DD_POINT_SMOOTH
) {
1253 fxMesa
->draw_point
= fx_draw_point_wide_aa
;
1255 fxMesa
->draw_point
= fx_draw_point_wide
;
1256 fx_render_tab_verts
[0] = fx_render_pw_verts
;
1257 fx_render_tab_elts
[0] = fx_render_pw_elts
;
1259 tnl
->Driver
.Render
.Points
= rast_tab
[index
|FX_FALLBACK_BIT
].points
;
1261 fx_render_tab_verts
[0] = fx_render_vb_points
;
1262 fx_render_tab_elts
[0] = fx_render_points_elts
;
1267 /**********************************************************************/
1268 /* Runtime render state and callbacks */
1269 /**********************************************************************/
1271 static void fxRunPipeline( GLcontext
*ctx
)
1273 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1274 GLuint new_gl_state
= fxMesa
->new_gl_state
;
1276 if (TDFX_DEBUG
& VERBOSE_PIPELINE
) {
1277 fprintf(stderr
, "fxRunPipeline()\n");
1281 /* Recalculate fog table on projection matrix changes. This used to
1282 * be triggered by the NearFar callback.
1284 if (new_gl_state
& _NEW_PROJECTION
)
1285 fxMesa
->new_state
|= FX_NEW_FOG
;
1288 if (new_gl_state
& _FX_NEW_IS_IN_HARDWARE
)
1289 fxCheckIsInHardware(ctx
);
1291 if (fxMesa
->new_state
)
1292 fxSetupFXUnits(ctx
);
1294 if (!fxMesa
->fallback
) {
1295 if (new_gl_state
& _FX_NEW_RENDERSTATE
)
1296 fxDDChooseRenderState(ctx
);
1298 if (new_gl_state
& _FX_NEW_SETUP_FUNCTION
)
1299 fxChooseVertexState(ctx
);
1302 if (new_gl_state
& _NEW_TEXTURE
) {
1303 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
1304 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
1306 if (t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
1307 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
1308 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
1309 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
1310 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
1313 if (t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
1314 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
1315 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
1316 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
1317 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
1321 fxMesa
->new_gl_state
= 0;
1323 _tnl_run_pipeline( ctx
);
1327 static GLenum reduced_prim
[GL_POLYGON
+1] = {
1342 /* Always called between RenderStart and RenderFinish --> We already
1345 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1347 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1349 fxMesa
->raster_primitive
= prim
;
1356 /* Determine the rasterized primitive when not drawing unfilled
1359 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1361 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1362 GLuint rprim
= reduced_prim
[prim
];
1364 fxMesa
->render_primitive
= prim
;
1366 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1369 if (fxMesa
->raster_primitive
!= rprim
) {
1370 fxRasterPrimitive( ctx
, rprim
);
1374 static void fxRenderFinish( GLcontext
*ctx
)
1376 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1378 if (fxMesa
->render_index
& FX_FALLBACK_BIT
)
1379 _swrast_flush( ctx
);
1384 /**********************************************************************/
1385 /* Manage total rasterization fallbacks */
1386 /**********************************************************************/
1388 static char *fallbackStrings
[] = {
1389 "3D/Rect/Cube Texture map",
1390 "glDrawBuffer(GL_FRONT_AND_BACK)",
1391 "Separate specular color",
1392 "glEnable/Disable(GL_STENCIL_TEST)",
1393 "glRenderMode(selection or feedback)",
1403 static char *getFallbackString(GLuint bit
)
1410 return fallbackStrings
[i
];
1414 void fxCheckIsInHardware( GLcontext
*ctx
)
1416 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1417 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1418 GLuint oldfallback
= fxMesa
->fallback
;
1419 GLuint newfallback
= fxMesa
->fallback
= fx_check_IsInHardware( ctx
);
1422 if (oldfallback
== 0) {
1423 if (fxMesa
->verbose
) {
1424 fprintf(stderr
, "Voodoo ! enter SW 0x%08x %s\n", newfallback
, getFallbackString(newfallback
));
1426 _swsetup_Wakeup( ctx
);
1431 _swrast_flush( ctx
);
1432 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1433 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1434 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1435 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1436 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1437 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1438 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1439 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1440 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1441 fxChooseVertexState(ctx
);
1442 fxDDChooseRenderState(ctx
);
1443 if (fxMesa
->verbose
) {
1444 fprintf(stderr
, "Voodoo ! leave SW 0x%08x %s\n", oldfallback
, getFallbackString(oldfallback
));
1447 tnl
->Driver
.Render
.Multipass
= (HAVE_SPEC
&& NEED_SECONDARY_COLOR(ctx
)) ? fxMultipass_ColorSum
: NULL
;
1451 void fxDDInitTriFuncs( GLcontext
*ctx
)
1453 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1454 static int firsttime
= 1;
1461 tnl
->Driver
.RunPipeline
= fxRunPipeline
;
1462 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1463 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1464 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1465 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1466 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1467 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1468 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1469 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1470 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1471 tnl
->Driver
.Render
.Multipass
= NULL
;
1473 (void) fx_print_vertex
;
1477 /* [dBorca] Hack alert:
1478 * doesn't work with blending.
1479 * XXX todo - need to take care of stencil.
1481 GLboolean
fxMultipass_ColorSum (GLcontext
*ctx
, GLuint pass
)
1483 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1489 case 1: /* first pass: the TEXTURED triangles are drawn */
1490 /* save per-pass data */
1491 fxMesa
->restoreUnitsState
= fxMesa
->unitsState
;
1492 /* turn off texturing */
1493 t0
= ctx
->Texture
.Unit
[0]._ReallyEnabled
;
1494 t1
= ctx
->Texture
.Unit
[1]._ReallyEnabled
;
1495 ctx
->Texture
.Unit
[0]._ReallyEnabled
= 0;
1496 ctx
->Texture
.Unit
[1]._ReallyEnabled
= 0;
1497 /* SUM the colors */
1498 fxDDBlendEquationSeparate(ctx
, GL_FUNC_ADD
, GL_FUNC_ADD
);
1499 fxDDBlendFuncSeparate(ctx
, GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
1500 fxDDEnable(ctx
, GL_BLEND
, GL_TRUE
);
1501 /* make sure we draw only where we want to */
1502 if (ctx
->Depth
.Mask
) {
1503 switch (ctx
->Depth
.Func
) {
1508 fxDDDepthFunc( ctx
, GL_EQUAL
);
1511 fxDDDepthMask( ctx
, GL_FALSE
);
1513 /* switch to secondary colors */
1514 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PSPEC_OFFSET
<< 2, GR_PARAM_ENABLE
);
1515 /* don't advertise new state */
1516 fxMesa
->new_state
= 0;
1518 case 2: /* 2nd pass (last): the secondary color is summed over texture */
1519 /* restore original state */
1520 fxMesa
->unitsState
= fxMesa
->restoreUnitsState
;
1521 /* restore texturing */
1522 ctx
->Texture
.Unit
[0]._ReallyEnabled
= t0
;
1523 ctx
->Texture
.Unit
[1]._ReallyEnabled
= t1
;
1524 /* revert to primary colors */
1525 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PARGB_OFFSET
<< 2, GR_PARAM_ENABLE
);
1528 assert(0); /* NOTREACHED */
1531 /* update HW state */
1533 fxSetupDepthTest(ctx
);
1534 fxSetupTexture(ctx
);
1544 * Need this to provide at least one external definition.
1547 extern int gl_fx_dummy_function_tris(void);
1549 gl_fx_dummy_function_tris(void)