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
;
300 radius
= v0
->psize
/ 2.;
301 n
= IROUND(v0
->psize
* 2); /* radius x 4 */
303 oon
= 1.0 / (GLfloat
)n
;
306 /* point coverage? */
307 /* we don't care about culling here (see fxSetupCull) */
314 vtxC
.x
+= radius
* __GL_COSF(ang
);
315 vtxC
.y
+= radius
* __GL_SINF(ang
);
316 grDrawVertexArray(GR_TRIANGLE_FAN
, 3, _v_
);
317 for (i
= 2; i
<= n
; i
++) {
318 ang
= M_2PI
* i
* oon
;
319 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
320 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
321 grDrawVertexArray(GR_TRIANGLE_FAN_CONTINUE
, 1, &_v_
[2]);
325 static void fx_draw_point_wide_aa ( fxMesaContext fxMesa
,
329 GLfloat ang
, radius
, oon
;
332 radius
= v0
->psize
/ 2.;
333 n
= IROUND(v0
->psize
* 2); /* radius x 4 */
335 oon
= 1.0 / (GLfloat
)n
;
338 /* point coverage? */
339 /* we don't care about culling here (see fxSetupCull) */
345 for (i
= 1; i
<= n
; i
++) {
346 ang
= M_2PI
* i
* oon
;
347 vtxC
.x
= v0
->x
+ radius
* __GL_COSF(ang
);
348 vtxC
.y
= v0
->y
+ radius
* __GL_SINF(ang
);
349 grAADrawTriangle( v0
, &vtxB
, &vtxC
, FXFALSE
, FXTRUE
, FXFALSE
);
350 /*grDrawTriangle( v0, &vtxB, &vtxC);*/
362 #define FX_UNFILLED_BIT 0x1
363 #define FX_OFFSET_BIT 0x2
364 #define FX_TWOSIDE_BIT 0x4
365 #define FX_FLAT_BIT 0x8
366 #define FX_FALLBACK_BIT 0x10
367 #define FX_MAX_TRIFUNC 0x20
372 triangle_func triangle
;
374 } rast_tab
[FX_MAX_TRIFUNC
];
376 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
377 #define DO_OFFSET (IND & FX_OFFSET_BIT)
378 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
379 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
380 #define DO_FLAT (IND & FX_FLAT_BIT)
385 #define DO_FULL_QUAD 1
388 #define HAVE_SPEC 1 /* [dBorca] investigate overhead !!! */
389 #define HAVE_HW_FLATSHADE 0
390 #define HAVE_BACK_COLORS 0
391 #define VERTEX GrVertex
394 #define DEPTH_SCALE 1.0
395 #define UNFILLED_TRI unfilled_tri
396 #define UNFILLED_QUAD unfilled_quad
397 #define VERT_X(_v) _v->x
398 #define VERT_Y(_v) _v->y
399 #define VERT_Z(_v) _v->ooz
400 #define GET_VERTEX(e) (fxMesa->verts + e)
403 #define AREA_IS_CCW( a ) (((fi_type *)&(a))->i < 0)
405 #define AREA_IS_CCW( a ) (a < 0)
409 #define VERT_SET_RGBA( dst, f ) \
411 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[2], f[0]);\
412 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[1], f[1]);\
413 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[0], f[2]);\
414 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[3], f[3]);\
417 #define VERT_COPY_RGBA( v0, v1 ) \
418 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
420 #define VERT_SAVE_RGBA( idx ) \
421 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
423 #define VERT_RESTORE_RGBA( idx ) \
424 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
427 #define VERT_SET_SPEC( dst, f ) \
429 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[2], f[0]);\
430 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[1], f[1]);\
431 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[0], f[2]);\
434 #define VERT_COPY_SPEC( v0, v1 ) \
435 *(GLuint *)&v0->pspec = *(GLuint *)&v1->pspec
437 #define VERT_SAVE_SPEC( idx ) \
438 *(GLuint *)&spec[idx] = *(GLuint *)&v[idx]->pspec
440 #define VERT_RESTORE_SPEC( idx ) \
441 *(GLuint *)&v[idx]->pspec = *(GLuint *)&spec[idx]
444 #define LOCAL_VARS(n) \
445 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
446 GLubyte color[n][4], spec[n][4]; \
447 (void) color; (void) spec;
451 /***********************************************************************
452 * Functions to draw basic unfilled primitives *
453 ***********************************************************************/
455 #define RASTERIZE(x) if (fxMesa->raster_primitive != x) \
456 fxRasterPrimitive( ctx, x )
457 #define RENDER_PRIMITIVE fxMesa->render_primitive
458 #define IND FX_FALLBACK_BIT
460 #include "tnl_dd/t_dd_unfilled.h"
463 /***********************************************************************
464 * Functions to draw GL primitives *
465 ***********************************************************************/
469 #include "tnl_dd/t_dd_tritmp.h"
471 #define IND (FX_OFFSET_BIT)
472 #define TAG(x) x##_offset
473 #include "tnl_dd/t_dd_tritmp.h"
475 #define IND (FX_TWOSIDE_BIT)
476 #define TAG(x) x##_twoside
477 #include "tnl_dd/t_dd_tritmp.h"
479 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
480 #define TAG(x) x##_twoside_offset
481 #include "tnl_dd/t_dd_tritmp.h"
483 #define IND (FX_UNFILLED_BIT)
484 #define TAG(x) x##_unfilled
485 #include "tnl_dd/t_dd_tritmp.h"
487 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
488 #define TAG(x) x##_offset_unfilled
489 #include "tnl_dd/t_dd_tritmp.h"
491 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
492 #define TAG(x) x##_twoside_unfilled
493 #include "tnl_dd/t_dd_tritmp.h"
495 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
496 #define TAG(x) x##_twoside_offset_unfilled
497 #include "tnl_dd/t_dd_tritmp.h"
499 #define IND (FX_FALLBACK_BIT)
500 #define TAG(x) x##_fallback
501 #include "tnl_dd/t_dd_tritmp.h"
503 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
504 #define TAG(x) x##_offset_fallback
505 #include "tnl_dd/t_dd_tritmp.h"
507 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
508 #define TAG(x) x##_twoside_fallback
509 #include "tnl_dd/t_dd_tritmp.h"
511 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
512 #define TAG(x) x##_twoside_offset_fallback
513 #include "tnl_dd/t_dd_tritmp.h"
515 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
516 #define TAG(x) x##_unfilled_fallback
517 #include "tnl_dd/t_dd_tritmp.h"
519 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
520 #define TAG(x) x##_offset_unfilled_fallback
521 #include "tnl_dd/t_dd_tritmp.h"
523 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
524 #define TAG(x) x##_twoside_unfilled_fallback
525 #include "tnl_dd/t_dd_tritmp.h"
527 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
529 #define TAG(x) x##_twoside_offset_unfilled_fallback
530 #include "tnl_dd/t_dd_tritmp.h"
533 /* Fx doesn't support provoking-vertex flat-shading?
535 #define IND (FX_FLAT_BIT)
536 #define TAG(x) x##_flat
537 #include "tnl_dd/t_dd_tritmp.h"
539 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
540 #define TAG(x) x##_offset_flat
541 #include "tnl_dd/t_dd_tritmp.h"
543 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
544 #define TAG(x) x##_twoside_flat
545 #include "tnl_dd/t_dd_tritmp.h"
547 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
548 #define TAG(x) x##_twoside_offset_flat
549 #include "tnl_dd/t_dd_tritmp.h"
551 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
552 #define TAG(x) x##_unfilled_flat
553 #include "tnl_dd/t_dd_tritmp.h"
555 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
556 #define TAG(x) x##_offset_unfilled_flat
557 #include "tnl_dd/t_dd_tritmp.h"
559 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
560 #define TAG(x) x##_twoside_unfilled_flat
561 #include "tnl_dd/t_dd_tritmp.h"
563 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
564 #define TAG(x) x##_twoside_offset_unfilled_flat
565 #include "tnl_dd/t_dd_tritmp.h"
567 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
568 #define TAG(x) x##_fallback_flat
569 #include "tnl_dd/t_dd_tritmp.h"
571 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
572 #define TAG(x) x##_offset_fallback_flat
573 #include "tnl_dd/t_dd_tritmp.h"
575 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
576 #define TAG(x) x##_twoside_fallback_flat
577 #include "tnl_dd/t_dd_tritmp.h"
579 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
580 #define TAG(x) x##_twoside_offset_fallback_flat
581 #include "tnl_dd/t_dd_tritmp.h"
583 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
584 #define TAG(x) x##_unfilled_fallback_flat
585 #include "tnl_dd/t_dd_tritmp.h"
587 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
588 #define TAG(x) x##_offset_unfilled_fallback_flat
589 #include "tnl_dd/t_dd_tritmp.h"
591 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
592 #define TAG(x) x##_twoside_unfilled_fallback_flat
593 #include "tnl_dd/t_dd_tritmp.h"
595 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
596 FX_FALLBACK_BIT|FX_FLAT_BIT)
597 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
598 #include "tnl_dd/t_dd_tritmp.h"
601 static void init_rast_tab( void )
606 init_twoside_offset();
608 init_offset_unfilled();
609 init_twoside_unfilled();
610 init_twoside_offset_unfilled();
612 init_offset_fallback();
613 init_twoside_fallback();
614 init_twoside_offset_fallback();
615 init_unfilled_fallback();
616 init_offset_unfilled_fallback();
617 init_twoside_unfilled_fallback();
618 init_twoside_offset_unfilled_fallback();
623 init_twoside_offset_flat();
624 init_unfilled_flat();
625 init_offset_unfilled_flat();
626 init_twoside_unfilled_flat();
627 init_twoside_offset_unfilled_flat();
628 init_fallback_flat();
629 init_offset_fallback_flat();
630 init_twoside_fallback_flat();
631 init_twoside_offset_fallback_flat();
632 init_unfilled_fallback_flat();
633 init_offset_unfilled_fallback_flat();
634 init_twoside_unfilled_fallback_flat();
635 init_twoside_offset_unfilled_fallback_flat();
639 /**********************************************************************/
640 /* Render whole begin/end objects */
641 /**********************************************************************/
644 /* Accelerate vertex buffer rendering when renderindex == 0 and
645 * there is no clipping.
647 #define INIT(x) fxRenderPrimitive( ctx, x )
649 static void fx_render_vb_points( GLcontext
*ctx
,
654 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
655 GrVertex
*fxVB
= fxMesa
->verts
;
659 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
660 fprintf(stderr
, "fx_render_vb_points\n");
665 /* Adjust point coords */
666 for (i
= start
; i
< count
; i
++) {
667 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
668 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
671 grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
672 fxVB
+ start
, sizeof(GrVertex
));
673 /* restore point coords */
674 for (i
= start
; i
< count
; i
++) {
675 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
676 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
680 static void fx_render_vb_line_strip( GLcontext
*ctx
,
685 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
686 GrVertex
*fxVB
= fxMesa
->verts
;
690 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
691 fprintf(stderr
, "fx_render_vb_line_strip\n");
696 /* adjust line coords */
697 for (i
= start
; i
< count
; i
++) {
698 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
699 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
702 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
703 fxVB
+ start
, sizeof(GrVertex
));
705 /* restore line coords */
706 for (i
= start
; i
< count
; i
++) {
707 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
708 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
712 static void fx_render_vb_line_loop( GLcontext
*ctx
,
717 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
718 GrVertex
*fxVB
= fxMesa
->verts
;
723 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
724 fprintf(stderr
, "fx_render_vb_line_loop\n");
729 if (!(flags
& PRIM_BEGIN
)) {
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
-j
,
740 fxVB
+ j
, sizeof(GrVertex
));
742 if (flags
& PRIM_END
)
743 grDrawLine( fxVB
+ (count
- 1),
746 /* restore line coords */
747 for (i
= start
; i
< count
; i
++) {
748 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
749 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
753 static void fx_render_vb_lines( GLcontext
*ctx
,
758 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
759 GrVertex
*fxVB
= fxMesa
->verts
;
763 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
764 fprintf(stderr
, "fx_render_vb_lines\n");
769 /* adjust line coords */
770 for (i
= start
; i
< count
; i
++) {
771 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
772 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
775 grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
776 fxVB
+ start
, sizeof(GrVertex
));
778 /* restore line coords */
779 for (i
= start
; i
< count
; i
++) {
780 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
781 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
785 static void fx_render_vb_triangles( GLcontext
*ctx
,
790 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
791 GrVertex
*fxVB
= fxMesa
->verts
;
794 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
795 fprintf(stderr
, "fx_render_vb_triangles\n");
802 * apparently, this causes troubles with some programs (GLExcess);
803 * might be a bug in Glide... However, "grDrawVertexArrayContiguous"
804 * eventually calls "grDrawTriangle" for GR_TRIANGLES, so we're better
805 * off doing it by hand...
807 grDrawVertexArrayContiguous( GR_TRIANGLES
, count
-start
,
808 fxVB
+ start
, sizeof(GrVertex
));
812 for (j
=start
+2; j
<count
; j
+=3) {
813 grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
820 static void fx_render_vb_tri_strip( GLcontext
*ctx
,
825 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
826 GrVertex
*fxVB
= fxMesa
->verts
;
830 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
831 fprintf(stderr
, "fx_render_vb_tri_strip\n");
834 INIT(GL_TRIANGLE_STRIP
);
837 if (flags & PRIM_PARITY)
838 mode = GR_TRIANGLE_STRIP_CONTINUE;
840 mode
= GR_TRIANGLE_STRIP
;
842 grDrawVertexArrayContiguous( mode
, count
-start
,
843 fxVB
+ start
, sizeof(GrVertex
));
847 static void fx_render_vb_tri_fan( GLcontext
*ctx
,
852 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
853 GrVertex
*fxVB
= fxMesa
->verts
;
856 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
857 fprintf(stderr
, "fx_render_vb_tri_fan\n");
860 INIT(GL_TRIANGLE_FAN
);
862 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
863 fxVB
+ start
, sizeof(GrVertex
) );
866 static void fx_render_vb_quads( GLcontext
*ctx
,
871 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
872 GrVertex
*fxVB
= fxMesa
->verts
;
876 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
877 fprintf(stderr
, "fx_render_vb_quads\n");
883 /* [dBorca] Hack alert:
884 * since VTX-0-2 we get here with start = 0, count = 2,
885 * causing around 4 billion triangles. Revise this after
893 for (i
= start
; i
< count
-3 ; i
+= 4 ) {
894 #define VERT(x) (fxVB + (x))
900 grDrawVertexArray(GR_TRIANGLE_FAN
, 4, _v_
);
901 /*grDrawTriangle( VERT(i), VERT(i+1), VERT(i+3) );*/
902 /*grDrawTriangle( VERT(i+1), VERT(i+2), VERT(i+3) );*/
907 static void fx_render_vb_quad_strip( GLcontext
*ctx
,
912 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
913 GrVertex
*fxVB
= fxMesa
->verts
;
916 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
917 fprintf(stderr
, "fx_render_vb_quad_strip\n");
922 count
-= (count
-start
)&1;
924 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
925 count
-start
, fxVB
+ start
, sizeof(GrVertex
));
928 static void fx_render_vb_poly( GLcontext
*ctx
,
933 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
934 GrVertex
*fxVB
= fxMesa
->verts
;
937 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
938 fprintf(stderr
, "fx_render_vb_poly\n");
943 grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
944 fxVB
+ start
, sizeof(GrVertex
));
947 static void fx_render_vb_noop( GLcontext
*ctx
,
952 (void) (ctx
&& start
&& count
&& flags
);
955 static void (*fx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
962 fx_render_vb_line_loop
,
963 fx_render_vb_line_strip
,
964 fx_render_vb_triangles
,
965 fx_render_vb_tri_strip
,
966 fx_render_vb_tri_fan
,
968 fx_render_vb_quad_strip
,
975 /**********************************************************************/
976 /* Render whole (indexed) begin/end objects */
977 /**********************************************************************/
980 #define VERT(x) (vertptr + x)
982 #define RENDER_POINTS( start, count ) \
983 for ( ; start < count ; start++) \
984 grDrawPoint( VERT(ELT(start)) );
986 #define RENDER_LINE( v0, v1 ) \
987 grDrawLine( VERT(v0), VERT(v1) )
989 #define RENDER_TRI( v0, v1, v2 ) \
990 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
992 #define RENDER_QUAD( v0, v1, v2, v3 ) \
993 fx_draw_quad( fxMesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
995 #define INIT(x) fxRenderPrimitive( ctx, x )
999 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
1000 GrVertex *vertptr = fxMesa->verts; \
1001 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
1004 #define RESET_STIPPLE
1005 #define RESET_OCCLUSION
1006 #define PRESERVE_VB_DEFS
1008 /* Elts, no clipping.
1012 #define TAG(x) fx_##x##_elts
1013 #define ELT(x) elt[x]
1014 #include "tnl_dd/t_dd_rendertmp.h"
1016 /* Verts, no clipping.
1020 #define TAG(x) fx_##x##_verts
1022 /*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
1026 /**********************************************************************/
1027 /* Render clipped primitives */
1028 /**********************************************************************/
1032 static void fxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1035 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1036 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1037 struct vertex_buffer
*VB
= &tnl
->vb
;
1038 GLuint prim
= fxMesa
->render_primitive
;
1040 /* Render the new vertices as an unclipped polygon.
1043 GLuint
*tmp
= VB
->Elts
;
1044 VB
->Elts
= (GLuint
*)elts
;
1045 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
1046 PRIM_BEGIN
|PRIM_END
);
1050 /* Restore the render primitive
1052 if (prim
!= GL_POLYGON
)
1053 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
1057 static void fxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
1060 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1061 GrVertex
*vertptr
= fxMesa
->verts
;
1062 const GrVertex
*start
= VERT(elts
[0]);
1064 for (i
= 2 ; i
< n
; i
++) {
1065 grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
1069 /**********************************************************************/
1070 /* Choose render functions */
1071 /**********************************************************************/
1074 #define POINT_FALLBACK (DD_POINT_SMOOTH)
1075 #define LINE_FALLBACK (DD_LINE_STIPPLE)
1076 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
1077 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
1078 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
1083 void fxDDChooseRenderState(GLcontext
*ctx
)
1085 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1086 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1087 GLuint flags
= ctx
->_TriangleCaps
;
1090 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
1091 if (flags
& ANY_RASTER_FLAGS
) {
1092 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= FX_TWOSIDE_BIT
;
1093 if (flags
& DD_TRI_OFFSET
) index
|= FX_OFFSET_BIT
;
1094 if (flags
& DD_TRI_UNFILLED
) index
|= FX_UNFILLED_BIT
;
1095 if (flags
& DD_FLATSHADE
) index
|= FX_FLAT_BIT
;
1098 fxMesa
->draw_point
= fx_draw_point
;
1099 fxMesa
->draw_line
= fx_draw_line
;
1100 fxMesa
->draw_tri
= fx_draw_triangle
;
1102 /* Hook in fallbacks for specific primitives.
1103 * [dBorca] Hack alert:
1104 * If we're in FSAA mode, we always do anti-aliased primitives.
1106 if (flags
& (POINT_FALLBACK
|
1110 if (fxMesa
->verbose
) {
1111 fprintf(stderr
, "Voodoo ! fallback (%x), raster (%x)\n",
1112 flags
& ANY_FALLBACK_FLAGS
, flags
& ANY_RASTER_FLAGS
);
1115 if (flags
& POINT_FALLBACK
)
1116 fxMesa
->draw_point
= fx_fallback_point
;
1118 if (flags
& LINE_FALLBACK
)
1119 fxMesa
->draw_line
= fx_fallback_line
;
1121 if (flags
& TRI_FALLBACK
)
1122 fxMesa
->draw_tri
= fx_fallback_tri
;
1124 index
|= FX_FALLBACK_BIT
;
1128 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1129 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1130 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
1131 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1132 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1135 tnl
->Driver
.Render
.PrimTabVerts
= fx_render_tab_verts
;
1136 tnl
->Driver
.Render
.PrimTabElts
= fx_render_tab_elts
;
1137 tnl
->Driver
.Render
.ClippedPolygon
= fxFastRenderClippedPoly
;
1139 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1140 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1141 tnl
->Driver
.Render
.ClippedPolygon
= fxRenderClippedPoly
;
1144 fxMesa
->render_index
= index
;
1146 /* [dBorca] Hack alert: more a trick than a real plug-in!!!
1147 * FX_FALLBACK_BIT is for total rasterization fallbacks; since
1148 * this is not the case, we don't alter "fxMesa->render_index".
1149 * But we still need to go through "rast_tab", to make sure
1150 * "POINT" calls "fxMesa->draw_point" instead of "grDrawPoint"
1152 if (flags
& (DD_POINT_SIZE
| DD_POINT_ATTEN
)) {
1153 if (flags
& DD_POINT_SMOOTH
) {
1154 fxMesa
->draw_point
= fx_draw_point_wide_aa
;
1156 fxMesa
->draw_point
= fx_draw_point_wide
;
1158 tnl
->Driver
.Render
.Points
= rast_tab
[FX_FALLBACK_BIT
].points
;
1163 /**********************************************************************/
1164 /* Runtime render state and callbacks */
1165 /**********************************************************************/
1167 static void fxRunPipeline( GLcontext
*ctx
)
1169 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1170 GLuint new_gl_state
= fxMesa
->new_gl_state
;
1172 if (TDFX_DEBUG
& VERBOSE_PIPELINE
) {
1173 fprintf(stderr
, "fxRunPipeline()\n");
1177 /* Recalculate fog table on projection matrix changes. This used to
1178 * be triggered by the NearFar callback.
1180 if (new_gl_state
& _NEW_PROJECTION
)
1181 fxMesa
->new_state
|= FX_NEW_FOG
;
1182 /* [dBorca] Hack alert:
1183 * the above _NEW_PROJECTION is not included in the test below,
1184 * so we may end up with fxMesa->new_state still dirty by the end
1185 * of the routine. The fact is, we don't have NearFar callback
1186 * anymore. We could use fxDDDepthRange instead, but it seems
1187 * fog needs to be updated only by a fog-basis.
1188 * Implementing fxDDDepthRange correctly is another story:
1189 * that, together with a presumable fxDDViewport function would set
1190 * fxMesa->SetupNewInputs |= VERT_BIT_CLIP;
1191 * which might be useful in fxBuildVertices...
1195 if (new_gl_state
& (_FX_NEW_IS_IN_HARDWARE
|
1196 _FX_NEW_RENDERSTATE
|
1197 _FX_NEW_SETUP_FUNCTION
|
1200 if (new_gl_state
& _FX_NEW_IS_IN_HARDWARE
)
1201 fxCheckIsInHardware(ctx
);
1203 if (fxMesa
->new_state
)
1204 fxSetupFXUnits(ctx
);
1206 if (!fxMesa
->fallback
) {
1207 if (new_gl_state
& _FX_NEW_RENDERSTATE
)
1208 fxDDChooseRenderState(ctx
);
1210 if (new_gl_state
& _FX_NEW_SETUP_FUNCTION
)
1211 fxChooseVertexState(ctx
);
1214 if (new_gl_state
& _NEW_TEXTURE
) {
1215 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
1216 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
1218 if (t0
&& t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
1219 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
1220 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
1221 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
1222 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
1225 if (t1
&& t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
1226 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
1227 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
1228 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
1229 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
1234 fxMesa
->new_gl_state
= 0;
1236 _tnl_run_pipeline( ctx
);
1240 static GLenum reduced_prim
[GL_POLYGON
+1] = {
1255 /* Always called between RenderStart and RenderFinish --> We already
1258 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1260 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1262 fxMesa
->raster_primitive
= prim
;
1269 /* Determine the rasterized primitive when not drawing unfilled
1272 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1274 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1275 GLuint rprim
= reduced_prim
[prim
];
1277 fxMesa
->render_primitive
= prim
;
1279 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1282 if (fxMesa
->raster_primitive
!= rprim
) {
1283 fxRasterPrimitive( ctx
, rprim
);
1287 static void fxRenderFinish( GLcontext
*ctx
)
1289 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1291 if (fxMesa
->render_index
& FX_FALLBACK_BIT
)
1292 _swrast_flush( ctx
);
1297 /**********************************************************************/
1298 /* Manage total rasterization fallbacks */
1299 /**********************************************************************/
1301 static char *fallbackStrings
[] = {
1302 "1D/3D Texture map",
1303 "glDrawBuffer(GL_FRONT_AND_BACK)",
1304 "Separate specular color",
1305 "glEnable/Disable(GL_STENCIL_TEST)",
1306 "glRenderMode(selection or feedback)",
1316 static char *getFallbackString(GLuint bit
)
1323 return fallbackStrings
[i
];
1327 void fxCheckIsInHardware( GLcontext
*ctx
)
1329 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1330 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1331 GLuint oldfallback
= fxMesa
->fallback
;
1332 GLuint newfallback
= fxMesa
->fallback
= fx_check_IsInHardware( ctx
);
1335 if (oldfallback
== 0) {
1336 if (fxMesa
->verbose
) {
1337 fprintf(stderr
, "Voodoo ! enter SW 0x%08x %s\n", newfallback
, getFallbackString(newfallback
));
1339 _swsetup_Wakeup( ctx
);
1344 _swrast_flush( ctx
);
1345 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1346 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1347 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1348 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1349 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1350 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1351 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1352 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1353 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1354 fxChooseVertexState(ctx
);
1355 fxDDChooseRenderState(ctx
);
1356 if (fxMesa
->verbose
) {
1357 fprintf(stderr
, "Voodoo ! leave SW 0x%08x %s\n", oldfallback
, getFallbackString(oldfallback
));
1360 tnl
->Driver
.Render
.Multipass
= (HAVE_SPEC
&& NEED_SECONDARY_COLOR(ctx
)) ? fxMultipass_ColorSum
: NULL
;
1364 void fxDDInitTriFuncs( GLcontext
*ctx
)
1366 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1367 static int firsttime
= 1;
1374 tnl
->Driver
.RunPipeline
= fxRunPipeline
;
1375 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1376 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1377 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1378 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1379 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1380 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1381 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1382 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1383 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1384 tnl
->Driver
.Render
.Multipass
= NULL
;
1386 (void) fx_print_vertex
;
1390 /* [dBorca] Hack alert:
1391 * does this approach work with multitex?
1393 GLboolean
fxMultipass_ColorSum (GLcontext
*ctx
, GLuint pass
)
1395 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1401 case 1: /* first pass: the TEXTURED triangles are drawn */
1402 /* save per-pass data */
1403 fxMesa
->restoreUnitsState
= fxMesa
->unitsState
;
1404 /* turn off texturing */
1405 t0
= ctx
->Texture
.Unit
[0]._ReallyEnabled
;
1406 t1
= ctx
->Texture
.Unit
[1]._ReallyEnabled
;
1407 ctx
->Texture
.Unit
[0]._ReallyEnabled
= 0;
1408 ctx
->Texture
.Unit
[1]._ReallyEnabled
= 0;
1409 /* SUM the colors */
1410 fxDDBlendEquation(ctx
, GL_FUNC_ADD_EXT
);
1411 fxDDBlendFuncSeparate(ctx
, GL_ONE
, GL_ONE
, GL_ZERO
, GL_ONE
);
1412 fxDDEnable(ctx
, GL_BLEND
, GL_TRUE
);
1413 /* make sure we draw only where we want to */
1414 if (ctx
->Depth
.Mask
) {
1415 switch (ctx
->Depth
.Func
) {
1420 fxDDDepthFunc( ctx
, GL_EQUAL
);
1423 fxDDDepthMask( ctx
, GL_FALSE
);
1425 /* switch to secondary colors */
1426 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PSPEC_OFFSET
<< 2, GR_PARAM_ENABLE
);
1427 /* don't advertise new state */
1428 fxMesa
->new_state
= 0;
1430 case 2: /* 2nd pass (last): the secondary color is summed over texture */
1431 /* restore original state */
1432 fxMesa
->unitsState
= fxMesa
->restoreUnitsState
;
1433 /* restore texturing */
1434 ctx
->Texture
.Unit
[0]._ReallyEnabled
= t0
;
1435 ctx
->Texture
.Unit
[1]._ReallyEnabled
= t1
;
1436 /* revert to primary colors */
1437 grVertexLayout(GR_PARAM_PARGB
, GR_VERTEX_PARGB_OFFSET
<< 2, GR_PARAM_ENABLE
);
1440 assert(0); /* NOTREACHED */
1443 /* update HW state */
1445 fxSetupDepthTest(ctx
);
1446 fxSetupTexture(ctx
);
1456 * Need this to provide at least one external definition.
1459 extern int gl_fx_dummy_function_tris(void);
1461 gl_fx_dummy_function_tris(void)