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_quad( fxMesaContext fxMesa
,
248 QUAD( v0
, v1
, v2
, v3
);
252 static void fx_draw_triangle( fxMesaContext fxMesa
,
262 static void fx_draw_line( fxMesaContext fxMesa
,
266 /* No support for wide lines (avoid wide/aa line fallback).
273 static void fx_draw_point( fxMesaContext fxMesa
,
276 /* No support for wide points.
284 #define M_2PI 6.28318530717958647692528676655901
286 #define __GL_COSF cos
287 #define __GL_SINF sin
288 static void fx_draw_point_wide ( fxMesaContext fxMesa
,
292 GLfloat ang
, radius
, oon
;
296 const GLcontext
*ctx
= fxMesa
->glCtx
;
297 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
) ? v0
->psize
: ctx
->Point
.Size
;
304 n
= IROUND(psize
* 2); /* radius x 4 */
306 oon
= 1.0 / (GLfloat
)n
;
309 /* point coverage? */
310 /* we don't care about culling here (see fxSetupCull) */
317 vtxC
.x
+= radius
* __GL_COSF(ang
);
318 vtxC
.y
+= radius
* __GL_SINF(ang
);
319 grDrawVertexArray(GR_TRIANGLE_FAN
, 3, _v_
);
320 for (i
= 2; i
<= n
; i
++) {
321 ang
= M_2PI
* i
* oon
;
322 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
323 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
324 grDrawVertexArray(GR_TRIANGLE_FAN_CONTINUE
, 1, &_v_
[2]);
328 static void fx_render_pw_verts( GLcontext
*ctx
,
333 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
334 GrVertex
*fxVB
= fxMesa
->verts
;
337 fxRenderPrimitive( ctx
, GL_POINTS
);
339 for ( ; start
< count
; start
++)
340 fx_draw_point_wide(fxMesa
, fxVB
+ start
);
343 static void fx_render_pw_elts ( GLcontext
*ctx
,
348 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
349 GrVertex
*fxVB
= fxMesa
->verts
;
350 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
353 fxRenderPrimitive( ctx
, GL_POINTS
);
355 for ( ; start
< count
; start
++)
356 fx_draw_point_wide(fxMesa
, fxVB
+ elt
[start
]);
359 static void fx_draw_point_wide_aa ( fxMesaContext fxMesa
,
363 GLfloat ang
, radius
, oon
;
366 const GLcontext
*ctx
= fxMesa
->glCtx
;
367 const GLfloat psize
= (ctx
->_TriangleCaps
& DD_POINT_ATTEN
) ? v0
->psize
: ctx
->Point
.Size
;
370 n
= IROUND(psize
* 2); /* radius x 4 */
372 oon
= 1.0 / (GLfloat
)n
;
375 /* point coverage? */
376 /* we don't care about culling here (see fxSetupCull) */
382 for (i
= 1; i
<= n
; i
++) {
383 ang
= M_2PI
* i
* oon
;
384 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
385 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
386 grAADrawTriangle( v0
, &vtxB
, &vtxC
, FXFALSE
, FXTRUE
, FXFALSE
);
387 /*grDrawTriangle( v0, &vtxB, &vtxC);*/
399 #define FX_UNFILLED_BIT 0x1
400 #define FX_OFFSET_BIT 0x2
401 #define FX_TWOSIDE_BIT 0x4
402 #define FX_FLAT_BIT 0x8
403 #define FX_FALLBACK_BIT 0x10
404 #define FX_MAX_TRIFUNC 0x20
407 tnl_points_func points
;
409 tnl_triangle_func triangle
;
411 } rast_tab
[FX_MAX_TRIFUNC
];
413 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
414 #define DO_OFFSET (IND & FX_OFFSET_BIT)
415 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
416 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
417 #define DO_FLAT (IND & FX_FLAT_BIT)
422 #define DO_FULL_QUAD 1
425 #define HAVE_SPEC 1 /* [dBorca] investigate overhead !!! */
426 #define HAVE_HW_FLATSHADE 0
427 #define HAVE_BACK_COLORS 0
428 #define VERTEX GrVertex
431 #define DEPTH_SCALE 1.0
432 #define UNFILLED_TRI unfilled_tri
433 #define UNFILLED_QUAD unfilled_quad
434 #define VERT_X(_v) _v->x
435 #define VERT_Y(_v) _v->y
436 #define VERT_Z(_v) _v->ooz
437 #define GET_VERTEX(e) (fxMesa->verts + e)
440 #define AREA_IS_CCW( a ) (((fi_type *)&(a))->i < 0)
442 #define AREA_IS_CCW( a ) (a < 0)
446 #define VERT_SET_RGBA( dst, f ) \
448 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[2], f[0]);\
449 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[1], f[1]);\
450 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[0], f[2]);\
451 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[3], f[3]);\
454 #define VERT_COPY_RGBA( v0, v1 ) \
455 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
457 #define VERT_SAVE_RGBA( idx ) \
458 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
460 #define VERT_RESTORE_RGBA( idx ) \
461 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
464 #define VERT_SET_SPEC( dst, f ) \
466 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[2], f[0]);\
467 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[1], f[1]);\
468 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[0], f[2]);\
471 #define VERT_COPY_SPEC( v0, v1 ) \
472 *(GLuint *)&v0->pspec = *(GLuint *)&v1->pspec
474 #define VERT_SAVE_SPEC( idx ) \
475 *(GLuint *)&spec[idx] = *(GLuint *)&v[idx]->pspec
477 #define VERT_RESTORE_SPEC( idx ) \
478 *(GLuint *)&v[idx]->pspec = *(GLuint *)&spec[idx]
481 #define LOCAL_VARS(n) \
482 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
483 GLubyte color[n][4], spec[n][4]; \
484 (void) color; (void) spec;
488 /***********************************************************************
489 * Functions to draw basic unfilled primitives *
490 ***********************************************************************/
492 #define RASTERIZE(x) if (fxMesa->raster_primitive != x) \
493 fxRasterPrimitive( ctx, x )
494 #define RENDER_PRIMITIVE fxMesa->render_primitive
495 #define IND FX_FALLBACK_BIT
497 #include "tnl_dd/t_dd_unfilled.h"
500 /***********************************************************************
501 * Functions to draw GL primitives *
502 ***********************************************************************/
506 #include "tnl_dd/t_dd_tritmp.h"
508 #define IND (FX_OFFSET_BIT)
509 #define TAG(x) x##_offset
510 #include "tnl_dd/t_dd_tritmp.h"
512 #define IND (FX_TWOSIDE_BIT)
513 #define TAG(x) x##_twoside
514 #include "tnl_dd/t_dd_tritmp.h"
516 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
517 #define TAG(x) x##_twoside_offset
518 #include "tnl_dd/t_dd_tritmp.h"
520 #define IND (FX_UNFILLED_BIT)
521 #define TAG(x) x##_unfilled
522 #include "tnl_dd/t_dd_tritmp.h"
524 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
525 #define TAG(x) x##_offset_unfilled
526 #include "tnl_dd/t_dd_tritmp.h"
528 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
529 #define TAG(x) x##_twoside_unfilled
530 #include "tnl_dd/t_dd_tritmp.h"
532 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
533 #define TAG(x) x##_twoside_offset_unfilled
534 #include "tnl_dd/t_dd_tritmp.h"
536 #define IND (FX_FALLBACK_BIT)
537 #define TAG(x) x##_fallback
538 #include "tnl_dd/t_dd_tritmp.h"
540 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
541 #define TAG(x) x##_offset_fallback
542 #include "tnl_dd/t_dd_tritmp.h"
544 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
545 #define TAG(x) x##_twoside_fallback
546 #include "tnl_dd/t_dd_tritmp.h"
548 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
549 #define TAG(x) x##_twoside_offset_fallback
550 #include "tnl_dd/t_dd_tritmp.h"
552 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
553 #define TAG(x) x##_unfilled_fallback
554 #include "tnl_dd/t_dd_tritmp.h"
556 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
557 #define TAG(x) x##_offset_unfilled_fallback
558 #include "tnl_dd/t_dd_tritmp.h"
560 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
561 #define TAG(x) x##_twoside_unfilled_fallback
562 #include "tnl_dd/t_dd_tritmp.h"
564 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
566 #define TAG(x) x##_twoside_offset_unfilled_fallback
567 #include "tnl_dd/t_dd_tritmp.h"
570 /* Fx doesn't support provoking-vertex flat-shading?
572 #define IND (FX_FLAT_BIT)
573 #define TAG(x) x##_flat
574 #include "tnl_dd/t_dd_tritmp.h"
576 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
577 #define TAG(x) x##_offset_flat
578 #include "tnl_dd/t_dd_tritmp.h"
580 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
581 #define TAG(x) x##_twoside_flat
582 #include "tnl_dd/t_dd_tritmp.h"
584 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
585 #define TAG(x) x##_twoside_offset_flat
586 #include "tnl_dd/t_dd_tritmp.h"
588 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
589 #define TAG(x) x##_unfilled_flat
590 #include "tnl_dd/t_dd_tritmp.h"
592 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
593 #define TAG(x) x##_offset_unfilled_flat
594 #include "tnl_dd/t_dd_tritmp.h"
596 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
597 #define TAG(x) x##_twoside_unfilled_flat
598 #include "tnl_dd/t_dd_tritmp.h"
600 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
601 #define TAG(x) x##_twoside_offset_unfilled_flat
602 #include "tnl_dd/t_dd_tritmp.h"
604 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
605 #define TAG(x) x##_fallback_flat
606 #include "tnl_dd/t_dd_tritmp.h"
608 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
609 #define TAG(x) x##_offset_fallback_flat
610 #include "tnl_dd/t_dd_tritmp.h"
612 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
613 #define TAG(x) x##_twoside_fallback_flat
614 #include "tnl_dd/t_dd_tritmp.h"
616 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
617 #define TAG(x) x##_twoside_offset_fallback_flat
618 #include "tnl_dd/t_dd_tritmp.h"
620 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
621 #define TAG(x) x##_unfilled_fallback_flat
622 #include "tnl_dd/t_dd_tritmp.h"
624 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
625 #define TAG(x) x##_offset_unfilled_fallback_flat
626 #include "tnl_dd/t_dd_tritmp.h"
628 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
629 #define TAG(x) x##_twoside_unfilled_fallback_flat
630 #include "tnl_dd/t_dd_tritmp.h"
632 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
633 FX_FALLBACK_BIT|FX_FLAT_BIT)
634 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
635 #include "tnl_dd/t_dd_tritmp.h"
638 static void init_rast_tab( void )
643 init_twoside_offset();
645 init_offset_unfilled();
646 init_twoside_unfilled();
647 init_twoside_offset_unfilled();
649 init_offset_fallback();
650 init_twoside_fallback();
651 init_twoside_offset_fallback();
652 init_unfilled_fallback();
653 init_offset_unfilled_fallback();
654 init_twoside_unfilled_fallback();
655 init_twoside_offset_unfilled_fallback();
660 init_twoside_offset_flat();
661 init_unfilled_flat();
662 init_offset_unfilled_flat();
663 init_twoside_unfilled_flat();
664 init_twoside_offset_unfilled_flat();
665 init_fallback_flat();
666 init_offset_fallback_flat();
667 init_twoside_fallback_flat();
668 init_twoside_offset_fallback_flat();
669 init_unfilled_fallback_flat();
670 init_offset_unfilled_fallback_flat();
671 init_twoside_unfilled_fallback_flat();
672 init_twoside_offset_unfilled_fallback_flat();
676 /**********************************************************************/
677 /* Render whole begin/end objects */
678 /**********************************************************************/
681 /* Accelerate vertex buffer rendering when renderindex == 0 and
682 * there is no clipping.
684 #define INIT(x) fxRenderPrimitive( ctx, x )
686 static void fx_render_vb_points( GLcontext
*ctx
,
691 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
692 GrVertex
*fxVB
= fxMesa
->verts
;
696 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
697 fprintf(stderr
, "fx_render_vb_points\n");
702 /* Adjust point coords */
703 for (i
= start
; i
< count
; i
++) {
704 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
705 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
708 grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
709 fxVB
+ start
, sizeof(GrVertex
));
710 /* restore point coords */
711 for (i
= start
; i
< count
; i
++) {
712 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
713 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
717 static void fx_render_vb_line_strip( GLcontext
*ctx
,
722 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
723 GrVertex
*fxVB
= fxMesa
->verts
;
727 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
728 fprintf(stderr
, "fx_render_vb_line_strip\n");
733 /* adjust line coords */
734 for (i
= start
; i
< count
; i
++) {
735 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
736 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
739 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
740 fxVB
+ start
, sizeof(GrVertex
));
742 /* restore line coords */
743 for (i
= start
; i
< count
; i
++) {
744 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
745 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
749 static void fx_render_vb_line_loop( GLcontext
*ctx
,
754 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
755 GrVertex
*fxVB
= fxMesa
->verts
;
760 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
761 fprintf(stderr
, "fx_render_vb_line_loop\n");
766 if (!(flags
& PRIM_BEGIN
)) {
770 /* adjust line coords */
771 for (i
= start
; i
< count
; i
++) {
772 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
773 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
776 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
777 fxVB
+ j
, sizeof(GrVertex
));
779 if (flags
& PRIM_END
)
780 grDrawLine( fxVB
+ (count
- 1),
783 /* restore line coords */
784 for (i
= start
; i
< count
; i
++) {
785 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
786 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
790 static void fx_render_vb_lines( GLcontext
*ctx
,
795 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
796 GrVertex
*fxVB
= fxMesa
->verts
;
800 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
801 fprintf(stderr
, "fx_render_vb_lines\n");
806 /* adjust line coords */
807 for (i
= start
; i
< count
; i
++) {
808 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
809 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
812 grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
813 fxVB
+ start
, sizeof(GrVertex
));
815 /* restore line coords */
816 for (i
= start
; i
< count
; i
++) {
817 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
818 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
822 static void fx_render_vb_triangles( GLcontext
*ctx
,
827 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
828 GrVertex
*fxVB
= fxMesa
->verts
;
831 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
832 fprintf(stderr
, "fx_render_vb_triangles\n");
839 * apparently, this causes troubles with some programs (GLExcess);
840 * might be a bug in Glide... However, "grDrawVertexArrayContiguous"
841 * eventually calls "grDrawTriangle" for GR_TRIANGLES, so we're better
842 * off doing it by hand...
844 grDrawVertexArrayContiguous( GR_TRIANGLES
, count
-start
,
845 fxVB
+ start
, sizeof(GrVertex
));
849 for (j
=start
+2; j
<count
; j
+=3) {
850 grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
857 static void fx_render_vb_tri_strip( GLcontext
*ctx
,
862 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
863 GrVertex
*fxVB
= fxMesa
->verts
;
867 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
868 fprintf(stderr
, "fx_render_vb_tri_strip\n");
871 INIT(GL_TRIANGLE_STRIP
);
874 if (flags & PRIM_PARITY)
875 mode = GR_TRIANGLE_STRIP_CONTINUE;
877 mode
= GR_TRIANGLE_STRIP
;
879 grDrawVertexArrayContiguous( mode
, count
-start
,
880 fxVB
+ start
, sizeof(GrVertex
));
884 static void fx_render_vb_tri_fan( GLcontext
*ctx
,
889 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
890 GrVertex
*fxVB
= fxMesa
->verts
;
893 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
894 fprintf(stderr
, "fx_render_vb_tri_fan\n");
897 INIT(GL_TRIANGLE_FAN
);
899 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
900 fxVB
+ start
, sizeof(GrVertex
) );
903 static void fx_render_vb_quads( GLcontext
*ctx
,
908 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
909 GrVertex
*fxVB
= fxMesa
->verts
;
913 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
914 fprintf(stderr
, "fx_render_vb_quads\n");
920 /* [dBorca] Hack alert:
921 * since VTX-0-2 we get here with start = 0, count = 2,
922 * causing around 4 billion triangles. Revise this after
930 for (i
= start
; i
< count
-3 ; i
+= 4 ) {
931 #define VERT(x) (fxVB + (x))
937 grDrawVertexArray(GR_TRIANGLE_FAN
, 4, _v_
);
938 /*grDrawTriangle( VERT(i), VERT(i+1), VERT(i+3) );*/
939 /*grDrawTriangle( VERT(i+1), VERT(i+2), VERT(i+3) );*/
944 static void fx_render_vb_quad_strip( GLcontext
*ctx
,
949 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
950 GrVertex
*fxVB
= fxMesa
->verts
;
953 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
954 fprintf(stderr
, "fx_render_vb_quad_strip\n");
959 count
-= (count
-start
)&1;
961 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
962 count
-start
, fxVB
+ start
, sizeof(GrVertex
));
965 static void fx_render_vb_poly( GLcontext
*ctx
,
970 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
971 GrVertex
*fxVB
= fxMesa
->verts
;
974 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
975 fprintf(stderr
, "fx_render_vb_poly\n");
980 grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
981 fxVB
+ start
, sizeof(GrVertex
));
984 static void fx_render_vb_noop( GLcontext
*ctx
,
989 (void) (ctx
&& start
&& count
&& flags
);
992 static void (*fx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
999 fx_render_vb_line_loop
,
1000 fx_render_vb_line_strip
,
1001 fx_render_vb_triangles
,
1002 fx_render_vb_tri_strip
,
1003 fx_render_vb_tri_fan
,
1005 fx_render_vb_quad_strip
,
1012 /**********************************************************************/
1013 /* Render whole (indexed) begin/end objects */
1014 /**********************************************************************/
1017 #define VERT(x) (vertptr + x)
1019 #define RENDER_POINTS( start, count ) \
1020 for ( ; start < count ; start++) \
1021 grDrawPoint( VERT(ELT(start)) );
1023 #define RENDER_LINE( v0, v1 ) \
1024 grDrawLine( VERT(v0), VERT(v1) )
1026 #define RENDER_TRI( v0, v1, v2 ) \
1027 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
1029 #define RENDER_QUAD( v0, v1, v2, v3 ) \
1030 fx_draw_quad( fxMesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
1032 #define INIT(x) fxRenderPrimitive( ctx, x )
1035 #define LOCAL_VARS \
1036 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
1037 GrVertex *vertptr = fxMesa->verts; \
1038 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
1041 #define RESET_STIPPLE
1042 #define RESET_OCCLUSION
1043 #define PRESERVE_VB_DEFS
1045 /* Elts, no clipping.
1049 #define TAG(x) fx_##x##_elts
1050 #define ELT(x) elt[x]
1051 #include "tnl_dd/t_dd_rendertmp.h"
1053 /* Verts, no clipping.
1057 #define TAG(x) fx_##x##_verts
1059 /*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
1063 /**********************************************************************/
1064 /* Render clipped primitives */
1065 /**********************************************************************/
1069 static void fxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1072 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1073 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1074 struct vertex_buffer
*VB
= &tnl
->vb
;
1075 GLuint prim
= fxMesa
->render_primitive
;
1077 /* Render the new vertices as an unclipped polygon.
1080 GLuint
*tmp
= VB
->Elts
;
1081 VB
->Elts
= (GLuint
*)elts
;
1082 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
1083 PRIM_BEGIN
|PRIM_END
);
1087 /* Restore the render primitive
1089 if (prim
!= GL_POLYGON
)
1090 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
1094 static void fxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1097 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1098 GrVertex
*vertptr
= fxMesa
->verts
;
1099 const GrVertex
*start
= VERT(elts
[0]);
1101 for (i
= 2 ; i
< n
; i
++) {
1102 grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
1106 /**********************************************************************/
1107 /* Choose render functions */
1108 /**********************************************************************/
1111 #define POINT_FALLBACK (DD_POINT_SMOOTH)
1112 #define LINE_FALLBACK (DD_LINE_STIPPLE)
1113 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
1114 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
1115 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
1120 void fxDDChooseRenderState(GLcontext
*ctx
)
1122 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1123 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1124 GLuint flags
= ctx
->_TriangleCaps
;
1127 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
1128 if (flags
& ANY_RASTER_FLAGS
) {
1129 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= FX_TWOSIDE_BIT
;
1130 if (flags
& DD_TRI_OFFSET
) index
|= FX_OFFSET_BIT
;
1131 if (flags
& DD_TRI_UNFILLED
) index
|= FX_UNFILLED_BIT
;
1132 if (flags
& DD_FLATSHADE
) index
|= FX_FLAT_BIT
;
1135 fxMesa
->draw_point
= fx_draw_point
;
1136 fxMesa
->draw_line
= fx_draw_line
;
1137 fxMesa
->draw_tri
= fx_draw_triangle
;
1139 /* Hook in fallbacks for specific primitives.
1140 * [dBorca] Hack alert:
1141 * If we're in FSAA mode, we always do anti-aliased primitives.
1143 if (flags
& (POINT_FALLBACK
|
1147 if (fxMesa
->verbose
) {
1148 fprintf(stderr
, "Voodoo ! fallback (%x), raster (%x)\n",
1149 flags
& ANY_FALLBACK_FLAGS
, flags
& ANY_RASTER_FLAGS
);
1152 if (flags
& POINT_FALLBACK
)
1153 fxMesa
->draw_point
= fx_fallback_point
;
1155 if (flags
& LINE_FALLBACK
)
1156 fxMesa
->draw_line
= fx_fallback_line
;
1158 if (flags
& TRI_FALLBACK
)
1159 fxMesa
->draw_tri
= fx_fallback_tri
;
1161 index
|= FX_FALLBACK_BIT
;
1165 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1166 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1167 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
1168 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1169 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1172 tnl
->Driver
.Render
.PrimTabVerts
= fx_render_tab_verts
;
1173 tnl
->Driver
.Render
.PrimTabElts
= fx_render_tab_elts
;
1174 tnl
->Driver
.Render
.ClippedPolygon
= fxFastRenderClippedPoly
;
1176 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1177 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1178 tnl
->Driver
.Render
.ClippedPolygon
= fxRenderClippedPoly
;
1181 fxMesa
->render_index
= index
;
1183 /* [dBorca] Hack alert: more a trick than a real plug-in!!! */
1184 if (flags
& (DD_POINT_SIZE
| DD_POINT_ATTEN
)) {
1185 /* We need to set the point primitive to go through "rast_tab",
1186 * to make sure "POINT" calls "fxMesa->draw_point" instead of
1187 * "grDrawPoint". We can achieve this by using FX_FALLBACK_BIT
1188 * (not really a total rasterization fallback, so we don't alter
1189 * "fxMesa->render_index"). If we get here with DD_POINT_SMOOTH,
1190 * we're done, cos we've already set _tnl_render_tab_{verts|elts}
1191 * above. Otherwise, the T&L engine can optimize point rendering
1192 * by using fx_render_tab_{verts|elts} hence the extra work.
1194 if (flags
& DD_POINT_SMOOTH
) {
1195 fxMesa
->draw_point
= fx_draw_point_wide_aa
;
1197 fxMesa
->draw_point
= fx_draw_point_wide
;
1198 fx_render_tab_verts
[0] = fx_render_pw_verts
;
1199 fx_render_tab_elts
[0] = fx_render_pw_elts
;
1201 tnl
->Driver
.Render
.Points
= rast_tab
[FX_FALLBACK_BIT
].points
;
1203 fx_render_tab_verts
[0] = fx_render_vb_points
;
1204 fx_render_tab_elts
[0] = fx_render_points_elts
;
1209 /**********************************************************************/
1210 /* Runtime render state and callbacks */
1211 /**********************************************************************/
1213 static void fxRunPipeline( GLcontext
*ctx
)
1215 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1216 GLuint new_gl_state
= fxMesa
->new_gl_state
;
1218 if (TDFX_DEBUG
& VERBOSE_PIPELINE
) {
1219 fprintf(stderr
, "fxRunPipeline()\n");
1223 /* Recalculate fog table on projection matrix changes. This used to
1224 * be triggered by the NearFar callback.
1226 if (new_gl_state
& _NEW_PROJECTION
)
1227 fxMesa
->new_state
|= FX_NEW_FOG
;
1228 /* [dBorca] Hack alert:
1229 * the above _NEW_PROJECTION is not included in the test below,
1230 * so we may end up with fxMesa->new_state still dirty by the end
1231 * of the routine. The fact is, we don't have NearFar callback
1232 * anymore. We could use fxDDDepthRange instead, but it seems
1233 * fog needs to be updated only by a fog-basis.
1234 * Implementing fxDDDepthRange correctly is another story:
1235 * that, together with a presumable fxDDViewport function would set
1236 * fxMesa->SetupNewInputs |= VERT_BIT_CLIP;
1237 * which might be useful in fxBuildVertices...
1241 if (new_gl_state
& (_FX_NEW_IS_IN_HARDWARE
|
1242 _FX_NEW_RENDERSTATE
|
1243 _FX_NEW_SETUP_FUNCTION
|
1246 if (new_gl_state
& _FX_NEW_IS_IN_HARDWARE
)
1247 fxCheckIsInHardware(ctx
);
1249 if (fxMesa
->new_state
)
1250 fxSetupFXUnits(ctx
);
1252 if (!fxMesa
->fallback
) {
1253 if (new_gl_state
& _FX_NEW_RENDERSTATE
)
1254 fxDDChooseRenderState(ctx
);
1256 if (new_gl_state
& _FX_NEW_SETUP_FUNCTION
)
1257 fxChooseVertexState(ctx
);
1260 if (new_gl_state
& _NEW_TEXTURE
) {
1261 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
1262 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
1264 if (t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
1265 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
1266 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
1267 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
1268 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
1271 if (t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
1272 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
1273 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
1274 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
1275 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
1280 fxMesa
->new_gl_state
= 0;
1282 _tnl_run_pipeline( ctx
);
1286 static GLenum reduced_prim
[GL_POLYGON
+1] = {
1301 /* Always called between RenderStart and RenderFinish --> We already
1304 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1306 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1308 fxMesa
->raster_primitive
= prim
;
1315 /* Determine the rasterized primitive when not drawing unfilled
1318 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1320 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1321 GLuint rprim
= reduced_prim
[prim
];
1323 fxMesa
->render_primitive
= prim
;
1325 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1328 if (fxMesa
->raster_primitive
!= rprim
) {
1329 fxRasterPrimitive( ctx
, rprim
);
1333 static void fxRenderFinish( GLcontext
*ctx
)
1335 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1337 if (fxMesa
->render_index
& FX_FALLBACK_BIT
)
1338 _swrast_flush( ctx
);
1343 /**********************************************************************/
1344 /* Manage total rasterization fallbacks */
1345 /**********************************************************************/
1347 static char *fallbackStrings
[] = {
1348 "3D/Rect/Cube Texture map",
1349 "glDrawBuffer(GL_FRONT_AND_BACK)",
1350 "Separate specular color",
1351 "glEnable/Disable(GL_STENCIL_TEST)",
1352 "glRenderMode(selection or feedback)",
1362 static char *getFallbackString(GLuint bit
)
1369 return fallbackStrings
[i
];
1373 void fxCheckIsInHardware( GLcontext
*ctx
)
1375 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1376 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1377 GLuint oldfallback
= fxMesa
->fallback
;
1378 GLuint newfallback
= fxMesa
->fallback
= fx_check_IsInHardware( ctx
);
1381 if (oldfallback
== 0) {
1382 if (fxMesa
->verbose
) {
1383 fprintf(stderr
, "Voodoo ! enter SW 0x%08x %s\n", newfallback
, getFallbackString(newfallback
));
1385 _swsetup_Wakeup( ctx
);
1390 _swrast_flush( ctx
);
1391 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1392 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1393 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1394 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1395 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1396 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1397 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1398 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1399 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1400 fxChooseVertexState(ctx
);
1401 fxDDChooseRenderState(ctx
);
1402 if (fxMesa
->verbose
) {
1403 fprintf(stderr
, "Voodoo ! leave SW 0x%08x %s\n", oldfallback
, getFallbackString(oldfallback
));
1406 tnl
->Driver
.Render
.Multipass
= (HAVE_SPEC
&& NEED_SECONDARY_COLOR(ctx
)) ? fxMultipass_ColorSum
: NULL
;
1410 void fxDDInitTriFuncs( GLcontext
*ctx
)
1412 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1413 static int firsttime
= 1;
1420 tnl
->Driver
.RunPipeline
= fxRunPipeline
;
1421 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1422 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1423 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1424 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1425 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1426 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1427 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1428 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1429 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1430 tnl
->Driver
.Render
.Multipass
= NULL
;
1432 (void) fx_print_vertex
;
1436 GLboolean
fxMultipass_ColorSum (GLcontext
*ctx
, GLuint pass
)
1438 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1444 case 1: /* first pass: the TEXTURED triangles are drawn */
1445 /* save per-pass data */
1446 fxMesa
->restoreUnitsState
= fxMesa
->unitsState
;
1447 /* turn off texturing */
1448 t0
= ctx
->Texture
.Unit
[0]._ReallyEnabled
;
1449 t1
= ctx
->Texture
.Unit
[1]._ReallyEnabled
;
1450 ctx
->Texture
.Unit
[0]._ReallyEnabled
= 0;
1451 ctx
->Texture
.Unit
[1]._ReallyEnabled
= 0;
1452 /* SUM the colors */
1453 fxDDBlendEquationSeparate(ctx
, GL_FUNC_ADD
, GL_FUNC_ADD
);
1454 fxDDBlendFuncSeparate(ctx
, GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
1455 fxDDEnable(ctx
, GL_BLEND
, GL_TRUE
);
1456 /* make sure we draw only where we want to */
1457 if (ctx
->Depth
.Mask
) {
1458 switch (ctx
->Depth
.Func
) {
1463 fxDDDepthFunc( ctx
, GL_EQUAL
);
1466 fxDDDepthMask( ctx
, GL_FALSE
);
1468 /* switch to secondary colors */
1469 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PSPEC_OFFSET
<< 2, GR_PARAM_ENABLE
);
1470 /* don't advertise new state */
1471 fxMesa
->new_state
= 0;
1473 case 2: /* 2nd pass (last): the secondary color is summed over texture */
1474 /* restore original state */
1475 fxMesa
->unitsState
= fxMesa
->restoreUnitsState
;
1476 /* restore texturing */
1477 ctx
->Texture
.Unit
[0]._ReallyEnabled
= t0
;
1478 ctx
->Texture
.Unit
[1]._ReallyEnabled
= t1
;
1479 /* revert to primary colors */
1480 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PARGB_OFFSET
<< 2, GR_PARAM_ENABLE
);
1483 assert(0); /* NOTREACHED */
1486 /* update HW state */
1488 fxSetupDepthTest(ctx
);
1489 fxSetupTexture(ctx
);
1499 * Need this to provide at least one external definition.
1502 extern int gl_fx_dummy_function_tris(void);
1504 gl_fx_dummy_function_tris(void)