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>
37 #include "swrast/swrast.h"
38 #include "swrast_setup/swrast_setup.h"
39 #include "tnl/t_context.h"
40 #include "tnl/t_pipeline.h"
46 * Subpixel offsets to adjust Mesa's (true) window coordinates to
47 * Glide coordinates. We need these to ensure precise rasterization.
48 * Otherwise, we'll fail a bunch of conformance tests.
50 #define TRI_X_OFFSET ( 0.0F)
51 #define TRI_Y_OFFSET ( 0.0F)
52 #define LINE_X_OFFSET ( 0.0F)
53 #define LINE_Y_OFFSET ( 0.125F)
54 #define PNT_X_OFFSET ( 0.375F)
55 #define PNT_Y_OFFSET ( 0.375F)
57 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
);
58 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
60 /***********************************************************************
61 * Macros for t_dd_tritmp.h to draw basic primitives *
62 ***********************************************************************/
64 #define TRI( a, b, c ) \
67 fxMesa->draw_tri( fxMesa, a, b, c ); \
69 grDrawTriangle( a, b, c ); \
72 #define QUAD( a, b, c, d ) \
75 fxMesa->draw_tri( fxMesa, a, b, d ); \
76 fxMesa->draw_tri( fxMesa, b, c, d ); \
78 grDrawTriangle( a, b, d ); \
79 grDrawTriangle( b, c, d ); \
83 #define LINE( v0, v1 ) \
86 fxMesa->draw_line( fxMesa, v0, v1 ); \
88 v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
89 v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
90 v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
91 v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
92 grDrawLine( v0, v1 ); \
93 v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
94 v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
95 v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
96 v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
100 #define POINT( v0 ) \
103 fxMesa->draw_point( fxMesa, v0 ); \
105 v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
106 v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
108 v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
109 v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
114 /***********************************************************************
115 * Fallback to swrast for basic primitives *
116 ***********************************************************************/
118 /* Build an SWvertex from a hardware vertex.
120 * This code is hit only when a mix of accelerated and unaccelerated
121 * primitives are being drawn, and only for the unaccelerated
125 fx_translate_vertex( GLcontext
*ctx
, const GrVertex
*src
, SWvertex
*dst
)
127 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
128 GLuint ts0
= fxMesa
->tmu_source
[0];
129 GLuint ts1
= fxMesa
->tmu_source
[1];
130 GLfloat w
= 1.0 / src
->oow
;
132 dst
->win
[0] = src
->x
;
133 dst
->win
[1] = src
->y
;
134 dst
->win
[2] = src
->ooz
;
135 dst
->win
[3] = src
->oow
;
137 dst
->color
[0] = src
->pargb
[2];
138 dst
->color
[1] = src
->pargb
[1];
139 dst
->color
[2] = src
->pargb
[0];
140 dst
->color
[3] = src
->pargb
[3];
142 dst
->texcoord
[ts0
][0] = fxMesa
->inv_s0scale
* src
->tmuvtx
[0].sow
* w
;
143 dst
->texcoord
[ts0
][1] = fxMesa
->inv_t0scale
* src
->tmuvtx
[0].tow
* w
;
145 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU0
)
146 dst
->texcoord
[ts0
][3] = src
->tmuvtx
[0].oow
* w
;
148 dst
->texcoord
[ts0
][3] = 1.0;
150 if (fxMesa
->SetupIndex
& SETUP_TMU1
) {
151 dst
->texcoord
[ts1
][0] = fxMesa
->inv_s1scale
* src
->tmuvtx
[1].sow
* w
;
152 dst
->texcoord
[ts1
][1] = fxMesa
->inv_t1scale
* src
->tmuvtx
[1].tow
* w
;
154 if (fxMesa
->stw_hint_state
& GR_STWHINT_W_DIFF_TMU1
)
155 dst
->texcoord
[ts1
][3] = src
->tmuvtx
[1].oow
* w
;
157 dst
->texcoord
[ts1
][3] = 1.0;
160 dst
->pointSize
= ctx
->Point
._Size
;
165 fx_fallback_tri( fxMesaContext fxMesa
,
170 GLcontext
*ctx
= fxMesa
->glCtx
;
173 fx_translate_vertex( ctx
, v0
, &v
[0] );
174 fx_translate_vertex( ctx
, v1
, &v
[1] );
175 fx_translate_vertex( ctx
, v2
, &v
[2] );
176 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
181 fx_fallback_line( fxMesaContext fxMesa
,
185 GLcontext
*ctx
= fxMesa
->glCtx
;
187 fx_translate_vertex( ctx
, v0
, &v
[0] );
188 fx_translate_vertex( ctx
, v1
, &v
[1] );
189 _swrast_Line( ctx
, &v
[0], &v
[1] );
194 fx_fallback_point( fxMesaContext fxMesa
,
197 GLcontext
*ctx
= fxMesa
->glCtx
;
199 fx_translate_vertex( ctx
, v0
, &v
[0] );
200 _swrast_Point( ctx
, &v
[0] );
203 /***********************************************************************
204 * Functions to draw basic primitives *
205 ***********************************************************************/
207 static void fx_print_vertex( GLcontext
*ctx
, const GrVertex
*v
)
209 fprintf(stderr
, "%s:\n", __FUNCTION__
);
211 fprintf(stderr
, "\tvertex at %p\n", (void *) v
);
213 fprintf(stderr
, "\tx %f y %f z %f oow %f\n", v
->x
, v
->y
, v
->ooz
, v
->oow
);
214 fprintf(stderr
, "\tr %d g %d b %d a %d\n", v
->pargb
[2], v
->pargb
[1], v
->pargb
[0], v
->pargb
[3]);
216 fprintf(stderr
, "\n");
219 #define DO_FALLBACK 0
221 /* Need to do clip loop at each triangle when mixing swrast and hw
222 * rendering. These functions are only used when mixed-mode rendering
225 static void fx_draw_quad( fxMesaContext fxMesa
,
232 QUAD( v0
, v1
, v2
, v3
);
236 static void fx_draw_triangle( fxMesaContext fxMesa
,
246 static void fx_draw_line( fxMesaContext fxMesa
,
250 /* No support for wide lines (avoid wide/aa line fallback).
257 static void fx_draw_point( fxMesaContext fxMesa
,
260 /* No support for wide points.
270 #define FX_UNFILLED_BIT 0x1
271 #define FX_OFFSET_BIT 0x2
272 #define FX_TWOSIDE_BIT 0x4
273 #define FX_FLAT_BIT 0x8
274 #define FX_FALLBACK_BIT 0x10
275 #define FX_MAX_TRIFUNC 0x20
280 triangle_func triangle
;
282 } rast_tab
[FX_MAX_TRIFUNC
];
284 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
285 #define DO_OFFSET (IND & FX_OFFSET_BIT)
286 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
287 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
288 #define DO_FLAT (IND & FX_FLAT_BIT)
293 #define DO_FULL_QUAD 1
297 #define HAVE_HW_FLATSHADE 0
298 #define HAVE_BACK_COLORS 0
299 #define VERTEX GrVertex
302 #define DEPTH_SCALE 1.0
303 #define UNFILLED_TRI unfilled_tri
304 #define UNFILLED_QUAD unfilled_quad
305 #define VERT_X(_v) _v->x
306 #define VERT_Y(_v) _v->y
307 #define VERT_Z(_v) _v->ooz
308 #define AREA_IS_CCW( a ) (a < 0)
309 #define GET_VERTEX(e) (fxMesa->verts + e)
311 #define VERT_SET_RGBA( dst, f ) \
313 dst->pargb[2] = f[0]; \
314 dst->pargb[1] = f[1]; \
315 dst->pargb[0] = f[2]; \
316 dst->pargb[3] = f[3]; \
319 #define VERT_COPY_RGBA( v0, v1 ) \
320 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
322 #define VERT_SAVE_RGBA( idx ) \
323 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
326 #define VERT_RESTORE_RGBA( idx ) \
327 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
330 #define LOCAL_VARS(n) \
331 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
332 GLubyte color[n][4]; \
337 /***********************************************************************
338 * Functions to draw basic unfilled primitives *
339 ***********************************************************************/
341 #define RASTERIZE(x) if (fxMesa->raster_primitive != x) \
342 fxRasterPrimitive( ctx, x )
343 #define RENDER_PRIMITIVE fxMesa->render_primitive
344 #define IND FX_FALLBACK_BIT
346 #include "../common/t_dd_unfilled.h"
349 /***********************************************************************
350 * Functions to draw GL primitives *
351 ***********************************************************************/
355 #include "../common/t_dd_tritmp.h"
357 #define IND (FX_OFFSET_BIT)
358 #define TAG(x) x##_offset
359 #include "../common/t_dd_tritmp.h"
361 #define IND (FX_TWOSIDE_BIT)
362 #define TAG(x) x##_twoside
363 #include "../common/t_dd_tritmp.h"
365 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
366 #define TAG(x) x##_twoside_offset
367 #include "../common/t_dd_tritmp.h"
369 #define IND (FX_UNFILLED_BIT)
370 #define TAG(x) x##_unfilled
371 #include "../common/t_dd_tritmp.h"
373 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
374 #define TAG(x) x##_offset_unfilled
375 #include "../common/t_dd_tritmp.h"
377 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
378 #define TAG(x) x##_twoside_unfilled
379 #include "../common/t_dd_tritmp.h"
381 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
382 #define TAG(x) x##_twoside_offset_unfilled
383 #include "../common/t_dd_tritmp.h"
385 #define IND (FX_FALLBACK_BIT)
386 #define TAG(x) x##_fallback
387 #include "../common/t_dd_tritmp.h"
389 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
390 #define TAG(x) x##_offset_fallback
391 #include "../common/t_dd_tritmp.h"
393 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
394 #define TAG(x) x##_twoside_fallback
395 #include "../common/t_dd_tritmp.h"
397 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
398 #define TAG(x) x##_twoside_offset_fallback
399 #include "../common/t_dd_tritmp.h"
401 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
402 #define TAG(x) x##_unfilled_fallback
403 #include "../common/t_dd_tritmp.h"
405 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
406 #define TAG(x) x##_offset_unfilled_fallback
407 #include "../common/t_dd_tritmp.h"
409 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
410 #define TAG(x) x##_twoside_unfilled_fallback
411 #include "../common/t_dd_tritmp.h"
413 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
415 #define TAG(x) x##_twoside_offset_unfilled_fallback
416 #include "../common/t_dd_tritmp.h"
419 /* Fx doesn't support provoking-vertex flat-shading?
421 #define IND (FX_FLAT_BIT)
422 #define TAG(x) x##_flat
423 #include "../common/t_dd_tritmp.h"
425 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
426 #define TAG(x) x##_offset_flat
427 #include "../common/t_dd_tritmp.h"
429 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
430 #define TAG(x) x##_twoside_flat
431 #include "../common/t_dd_tritmp.h"
433 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
434 #define TAG(x) x##_twoside_offset_flat
435 #include "../common/t_dd_tritmp.h"
437 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
438 #define TAG(x) x##_unfilled_flat
439 #include "../common/t_dd_tritmp.h"
441 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
442 #define TAG(x) x##_offset_unfilled_flat
443 #include "../common/t_dd_tritmp.h"
445 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
446 #define TAG(x) x##_twoside_unfilled_flat
447 #include "../common/t_dd_tritmp.h"
449 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
450 #define TAG(x) x##_twoside_offset_unfilled_flat
451 #include "../common/t_dd_tritmp.h"
453 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
454 #define TAG(x) x##_fallback_flat
455 #include "../common/t_dd_tritmp.h"
457 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
458 #define TAG(x) x##_offset_fallback_flat
459 #include "../common/t_dd_tritmp.h"
461 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
462 #define TAG(x) x##_twoside_fallback_flat
463 #include "../common/t_dd_tritmp.h"
465 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
466 #define TAG(x) x##_twoside_offset_fallback_flat
467 #include "../common/t_dd_tritmp.h"
469 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
470 #define TAG(x) x##_unfilled_fallback_flat
471 #include "../common/t_dd_tritmp.h"
473 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
474 #define TAG(x) x##_offset_unfilled_fallback_flat
475 #include "../common/t_dd_tritmp.h"
477 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
478 #define TAG(x) x##_twoside_unfilled_fallback_flat
479 #include "../common/t_dd_tritmp.h"
481 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
482 FX_FALLBACK_BIT|FX_FLAT_BIT)
483 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
484 #include "../common/t_dd_tritmp.h"
487 static void init_rast_tab( void )
492 init_twoside_offset();
494 init_offset_unfilled();
495 init_twoside_unfilled();
496 init_twoside_offset_unfilled();
498 init_offset_fallback();
499 init_twoside_fallback();
500 init_twoside_offset_fallback();
501 init_unfilled_fallback();
502 init_offset_unfilled_fallback();
503 init_twoside_unfilled_fallback();
504 init_twoside_offset_unfilled_fallback();
509 init_twoside_offset_flat();
510 init_unfilled_flat();
511 init_offset_unfilled_flat();
512 init_twoside_unfilled_flat();
513 init_twoside_offset_unfilled_flat();
514 init_fallback_flat();
515 init_offset_fallback_flat();
516 init_twoside_fallback_flat();
517 init_twoside_offset_fallback_flat();
518 init_unfilled_fallback_flat();
519 init_offset_unfilled_fallback_flat();
520 init_twoside_unfilled_fallback_flat();
521 init_twoside_offset_unfilled_fallback_flat();
525 /**********************************************************************/
526 /* Render whole begin/end objects */
527 /**********************************************************************/
530 /* Accelerate vertex buffer rendering when renderindex == 0 and
531 * there is no clipping.
534 static void fx_render_vb_points( GLcontext
*ctx
,
539 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
540 GrVertex
*fxVB
= fxMesa
->verts
;
544 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
545 fprintf(stderr
, "fx_render_vb_points\n");
548 fxRenderPrimitive(ctx
, GL_POINTS
);
550 /* Adjust point coords */
551 for (i
= start
; i
< count
; i
++) {
552 fxVB
[i
].x
+= PNT_X_OFFSET
- TRI_X_OFFSET
;
553 fxVB
[i
].y
+= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
556 grDrawVertexArrayContiguous( GR_POINTS
, count
-start
,
557 fxVB
+ start
, sizeof(GrVertex
));
558 /* restore point coords */
559 for (i
= start
; i
< count
; i
++) {
560 fxVB
[i
].x
-= PNT_X_OFFSET
- TRI_X_OFFSET
;
561 fxVB
[i
].y
-= PNT_Y_OFFSET
- TRI_Y_OFFSET
;
565 static void fx_render_vb_line_strip( GLcontext
*ctx
,
570 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
571 GrVertex
*fxVB
= fxMesa
->verts
;
575 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
576 fprintf(stderr
, "fx_render_vb_line_strip\n");
579 fxRenderPrimitive(ctx
, GL_LINE_STRIP
);
581 /* adjust line coords */
582 for (i
= start
; i
< count
; i
++) {
583 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
584 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
587 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-start
,
588 fxVB
+ start
, sizeof(GrVertex
));
590 /* restore line coords */
591 for (i
= start
; i
< count
; i
++) {
592 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
593 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
597 static void fx_render_vb_line_loop( GLcontext
*ctx
,
602 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
603 GrVertex
*fxVB
= fxMesa
->verts
;
608 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
609 fprintf(stderr
, "fx_render_vb_line_loop\n");
612 fxRenderPrimitive(ctx
, GL_LINE_LOOP
);
614 if (!(flags
& PRIM_BEGIN
)) {
618 /* adjust line coords */
619 for (i
= start
; i
< count
; i
++) {
620 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
621 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
624 grDrawVertexArrayContiguous( GR_LINE_STRIP
, count
-j
,
625 fxVB
+ j
, sizeof(GrVertex
));
627 if (flags
& PRIM_END
)
628 grDrawLine( fxVB
+ (count
- 1),
631 /* restore line coords */
632 for (i
= start
; i
< count
; i
++) {
633 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
634 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
638 static void fx_render_vb_lines( GLcontext
*ctx
,
643 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
644 GrVertex
*fxVB
= fxMesa
->verts
;
648 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
649 fprintf(stderr
, "fx_render_vb_lines\n");
652 fxRenderPrimitive(ctx
, GL_LINES
);
654 /* adjust line coords */
655 for (i
= start
; i
< count
; i
++) {
656 fxVB
[i
].x
+= LINE_X_OFFSET
- TRI_X_OFFSET
;
657 fxVB
[i
].y
+= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
660 grDrawVertexArrayContiguous( GR_LINES
, count
-start
,
661 fxVB
+ start
, sizeof(GrVertex
));
663 /* restore line coords */
664 for (i
= start
; i
< count
; i
++) {
665 fxVB
[i
].x
-= LINE_X_OFFSET
- TRI_X_OFFSET
;
666 fxVB
[i
].y
-= LINE_Y_OFFSET
- TRI_Y_OFFSET
;
670 static void fx_render_vb_triangles( GLcontext
*ctx
,
675 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
676 GrVertex
*fxVB
= fxMesa
->verts
;
679 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
680 fprintf(stderr
, "fx_render_vb_triangles\n");
683 fxRenderPrimitive(ctx
, GL_TRIANGLES
);
687 * apparently, this causes troubles with some programs (GLExcess);
688 * might be a bug in Glide... However, "grDrawVertexArrayContiguous"
689 * eventually calls "grDrawTriangle" for GR_TRIANGLES, so we're better
690 * off doing it by hand...
692 grDrawVertexArrayContiguous( GR_TRIANGLES
, count
-start
,
693 fxVB
+ start
, sizeof(GrVertex
));
697 for (j
=start
+2; j
<count
; j
+=3) {
698 grDrawTriangle(fxVB
+ (j
-2), fxVB
+ (j
-1), fxVB
+ j
);
705 static void fx_render_vb_tri_strip( GLcontext
*ctx
,
710 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
711 GrVertex
*fxVB
= fxMesa
->verts
;
715 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
716 fprintf(stderr
, "fx_render_vb_tri_strip\n");
719 fxRenderPrimitive(ctx
, GL_TRIANGLE_STRIP
);
721 if (flags
& PRIM_PARITY
)
722 mode
= GR_TRIANGLE_STRIP_CONTINUE
;
724 mode
= GR_TRIANGLE_STRIP
;
726 grDrawVertexArrayContiguous( mode
, count
-start
,
727 fxVB
+ start
, sizeof(GrVertex
));
731 static void fx_render_vb_tri_fan( GLcontext
*ctx
,
736 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
737 GrVertex
*fxVB
= fxMesa
->verts
;
740 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
741 fprintf(stderr
, "fx_render_vb_tri_fan\n");
744 fxRenderPrimitive(ctx
, GL_TRIANGLE_FAN
);
746 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN
, count
-start
,
747 fxVB
+ start
, sizeof(GrVertex
) );
750 static void fx_render_vb_quads( GLcontext
*ctx
,
755 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
756 GrVertex
*fxVB
= fxMesa
->verts
;
760 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
761 fprintf(stderr
, "fx_render_vb_quads\n");
764 fxRenderPrimitive(ctx
, GL_QUADS
);
766 for (i
= start
; i
< count
-3 ; i
+= 4 ) {
767 #define VERT(x) (fxVB + (x))
768 grDrawTriangle( VERT(i
), VERT(i
+1), VERT(i
+3) );
769 grDrawTriangle( VERT(i
+1), VERT(i
+2), VERT(i
+3) );
774 static void fx_render_vb_quad_strip( GLcontext
*ctx
,
779 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
780 GrVertex
*fxVB
= fxMesa
->verts
;
783 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
784 fprintf(stderr
, "fx_render_vb_quad_strip\n");
787 fxRenderPrimitive(ctx
, GL_QUAD_STRIP
);
789 count
-= (count
-start
)&1;
791 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP
,
792 count
-start
, fxVB
+ start
, sizeof(GrVertex
));
795 static void fx_render_vb_poly( GLcontext
*ctx
,
800 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
801 GrVertex
*fxVB
= fxMesa
->verts
;
804 if (TDFX_DEBUG
& VERBOSE_VARRAY
) {
805 fprintf(stderr
, "fx_render_vb_poly\n");
808 fxRenderPrimitive(ctx
, GL_POLYGON
);
810 grDrawVertexArrayContiguous( GR_POLYGON
, count
-start
,
811 fxVB
+ start
, sizeof(GrVertex
));
814 static void fx_render_vb_noop( GLcontext
*ctx
,
819 (void) (ctx
&& start
&& count
&& flags
);
822 static void (*fx_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
829 fx_render_vb_line_loop
,
830 fx_render_vb_line_strip
,
831 fx_render_vb_triangles
,
832 fx_render_vb_tri_strip
,
833 fx_render_vb_tri_fan
,
835 fx_render_vb_quad_strip
,
841 /**********************************************************************/
842 /* Render whole (indexed) begin/end objects */
843 /**********************************************************************/
846 #define VERT(x) (vertptr + x)
848 #define RENDER_POINTS( start, count ) \
849 for ( ; start < count ; start++) \
850 grDrawPoint( VERT(ELT(start)) );
852 #define RENDER_LINE( v0, v1 ) \
853 grDrawLine( VERT(v0), VERT(v1) )
855 #define RENDER_TRI( v0, v1, v2 ) \
856 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
858 #define RENDER_QUAD( v0, v1, v2, v3 ) \
859 fx_draw_quad( fxMesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
861 #define INIT(x) fxRenderPrimitive( ctx, x )
865 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
866 GrVertex *vertptr = fxMesa->verts; \
867 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
870 #define RESET_STIPPLE
871 #define RESET_OCCLUSION
872 #define PRESERVE_VB_DEFS
874 /* Elts, no clipping.
878 #define TAG(x) fx_##x##_elts
879 #define ELT(x) elt[x]
880 #include "../common/t_dd_rendertmp.h"
882 /* Verts, no clipping.
886 #define TAG(x) fx_##x##_verts
888 /*#include "../common/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
892 /**********************************************************************/
893 /* Render clipped primitives */
894 /**********************************************************************/
898 static void fxRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
901 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
902 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
903 struct vertex_buffer
*VB
= &tnl
->vb
;
904 GLuint prim
= fxMesa
->render_primitive
;
906 /* Render the new vertices as an unclipped polygon.
909 GLuint
*tmp
= VB
->Elts
;
910 VB
->Elts
= (GLuint
*)elts
;
911 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
912 PRIM_BEGIN
|PRIM_END
);
916 /* Restore the render primitive
918 if (prim
!= GL_POLYGON
)
919 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
923 static void fxFastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
926 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
927 GrVertex
*vertptr
= fxMesa
->verts
;
928 const GrVertex
*start
= VERT(elts
[0]);
930 for (i
= 2 ; i
< n
; i
++) {
931 grDrawTriangle( start
, VERT(elts
[i
-1]), VERT(elts
[i
]) );
935 /**********************************************************************/
936 /* Choose render functions */
937 /**********************************************************************/
940 #define POINT_FALLBACK (DD_POINT_SMOOTH)
941 #define LINE_FALLBACK (DD_LINE_STIPPLE)
942 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
943 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
944 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
949 void fxDDChooseRenderState(GLcontext
*ctx
)
951 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
952 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
953 GLuint flags
= ctx
->_TriangleCaps
;
956 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
957 if (flags
& ANY_RASTER_FLAGS
) {
958 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= FX_TWOSIDE_BIT
;
959 if (flags
& DD_TRI_OFFSET
) index
|= FX_OFFSET_BIT
;
960 if (flags
& DD_TRI_UNFILLED
) index
|= FX_UNFILLED_BIT
;
961 if (flags
& DD_FLATSHADE
) index
|= FX_FLAT_BIT
;
964 fxMesa
->draw_point
= fx_draw_point
;
965 fxMesa
->draw_line
= fx_draw_line
;
966 fxMesa
->draw_tri
= fx_draw_triangle
;
968 /* Hook in fallbacks for specific primitives.
969 * [dBorca] Hack alert:
970 * If we're in FSAA mode, we always do anti-aliased primitives.
972 if (flags
& (POINT_FALLBACK
|
976 if (fxMesa
->verbose
) {
977 fprintf(stderr
, "Voodoo ! fallback (%x), raster (%x)\n",
978 flags
& ANY_FALLBACK_FLAGS
, flags
& ANY_RASTER_FLAGS
);
981 if (flags
& POINT_FALLBACK
)
982 fxMesa
->draw_point
= fx_fallback_point
;
984 if (flags
& LINE_FALLBACK
)
985 fxMesa
->draw_line
= fx_fallback_line
;
987 if (flags
& TRI_FALLBACK
)
988 fxMesa
->draw_tri
= fx_fallback_tri
;
990 index
|= FX_FALLBACK_BIT
;
994 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
995 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
996 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
997 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
998 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1001 tnl
->Driver
.Render
.PrimTabVerts
= fx_render_tab_verts
;
1002 tnl
->Driver
.Render
.PrimTabElts
= fx_render_tab_elts
;
1003 tnl
->Driver
.Render
.ClippedPolygon
= fxFastRenderClippedPoly
;
1005 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1006 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1007 tnl
->Driver
.Render
.ClippedPolygon
= fxRenderClippedPoly
;
1010 fxMesa
->render_index
= index
;
1014 /**********************************************************************/
1015 /* Runtime render state and callbacks */
1016 /**********************************************************************/
1018 static void fxRunPipeline( GLcontext
*ctx
)
1020 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1021 GLuint new_gl_state
= fxMesa
->new_gl_state
;
1023 if (TDFX_DEBUG
& VERBOSE_PIPELINE
) {
1024 fprintf(stderr
, "fxRunPipeline()\n");
1028 /* Recalculate fog table on projection matrix changes. This used to
1029 * be triggered by the NearFar callback.
1031 if (new_gl_state
& _NEW_PROJECTION
)
1032 fxMesa
->new_state
|= FX_NEW_FOG
;
1033 /* [dBorca] Hack alert:
1034 * the above _NEW_PROJECTION is not included in the test below,
1035 * so we may end up with fxMesa->new_state still dirty by the end
1036 * of the routine. The fact is, we don't have NearFar callback
1037 * anymore. We could use fxDDDepthRange instead, but it seems
1038 * fog needs to be updated only by a fog-basis.
1039 * Implementing fxDDDepthRange correctly is another story:
1040 * that, together with a presumable fxDDViewport function would set
1041 * fxMesa->SetupNewInputs |= VERT_BIT_CLIP;
1042 * which might be useful in fxBuildVertices...
1046 if (new_gl_state
& (_FX_NEW_IS_IN_HARDWARE
|
1047 _FX_NEW_RENDERSTATE
|
1048 _FX_NEW_SETUP_FUNCTION
|
1051 if (new_gl_state
& _FX_NEW_IS_IN_HARDWARE
)
1052 fxCheckIsInHardware(ctx
);
1054 if (fxMesa
->new_state
)
1055 fxSetupFXUnits(ctx
);
1057 if (!fxMesa
->fallback
) {
1058 if (new_gl_state
& _FX_NEW_RENDERSTATE
)
1059 fxDDChooseRenderState(ctx
);
1061 if (new_gl_state
& _FX_NEW_SETUP_FUNCTION
)
1062 fxChooseVertexState(ctx
);
1065 if (new_gl_state
& _NEW_TEXTURE
) {
1066 struct gl_texture_unit
*t0
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[0]];
1067 struct gl_texture_unit
*t1
= &ctx
->Texture
.Unit
[fxMesa
->tmu_source
[1]];
1069 if (t0
&& t0
->_Current
&& FX_TEXTURE_DATA(t0
)) {
1070 fxMesa
->s0scale
= FX_TEXTURE_DATA(t0
)->sScale
;
1071 fxMesa
->t0scale
= FX_TEXTURE_DATA(t0
)->tScale
;
1072 fxMesa
->inv_s0scale
= 1.0 / fxMesa
->s0scale
;
1073 fxMesa
->inv_t0scale
= 1.0 / fxMesa
->t0scale
;
1076 if (t1
&& t1
->_Current
&& FX_TEXTURE_DATA(t1
)) {
1077 fxMesa
->s1scale
= FX_TEXTURE_DATA(t1
)->sScale
;
1078 fxMesa
->t1scale
= FX_TEXTURE_DATA(t1
)->tScale
;
1079 fxMesa
->inv_s1scale
= 1.0 / fxMesa
->s1scale
;
1080 fxMesa
->inv_t1scale
= 1.0 / fxMesa
->t1scale
;
1085 fxMesa
->new_gl_state
= 0;
1087 _tnl_run_pipeline( ctx
);
1091 static GLenum reduced_prim
[GL_POLYGON
+1] = {
1106 /* Always called between RenderStart and RenderFinish --> We already
1109 static void fxRasterPrimitive( GLcontext
*ctx
, GLenum prim
)
1111 fxMesaContext fxMesa
= FX_CONTEXT( ctx
);
1113 fxMesa
->raster_primitive
= prim
;
1120 /* Determine the rasterized primitive when not drawing unfilled
1123 static void fxRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1125 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1126 GLuint rprim
= reduced_prim
[prim
];
1128 fxMesa
->render_primitive
= prim
;
1130 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1133 if (fxMesa
->raster_primitive
!= rprim
) {
1134 fxRasterPrimitive( ctx
, rprim
);
1138 static void fxRenderFinish( GLcontext
*ctx
)
1140 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1142 if (fxMesa
->render_index
& FX_FALLBACK_BIT
)
1143 _swrast_flush( ctx
);
1148 /**********************************************************************/
1149 /* Manage total rasterization fallbacks */
1150 /**********************************************************************/
1152 static char *fallbackStrings
[] = {
1153 "1D/3D Texture map",
1154 "glDrawBuffer(GL_FRONT_AND_BACK)",
1155 "Separate specular color",
1156 "glEnable/Disable(GL_STENCIL_TEST)",
1157 "glRenderMode(selection or feedback)",
1167 static char *getFallbackString(GLuint bit
)
1174 return fallbackStrings
[i
];
1178 void fxCheckIsInHardware( GLcontext
*ctx
)
1180 fxMesaContext fxMesa
= FX_CONTEXT(ctx
);
1181 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1182 GLuint oldfallback
= fxMesa
->fallback
;
1183 GLuint newfallback
= fxMesa
->fallback
= fx_check_IsInHardware( ctx
);
1186 if (oldfallback
== 0) {
1187 if (fxMesa
->verbose
) {
1188 fprintf(stderr
, "Voodoo ! enter SW 0x%08x %s\n", newfallback
, getFallbackString(newfallback
));
1190 _swsetup_Wakeup( ctx
);
1195 _swrast_flush( ctx
);
1196 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1197 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1198 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1199 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1200 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1201 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1202 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1203 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1204 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1205 tnl
->Driver
.Render
.Multipass
= 0;
1206 fxChooseVertexState(ctx
);
1207 fxDDChooseRenderState(ctx
);
1208 if (fxMesa
->verbose
) {
1209 fprintf(stderr
, "Voodoo ! leave SW 0x%08x %s\n", oldfallback
, getFallbackString(oldfallback
));
1215 void fxDDInitTriFuncs( GLcontext
*ctx
)
1217 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1218 static int firsttime
= 1;
1225 tnl
->Driver
.RunPipeline
= fxRunPipeline
;
1226 tnl
->Driver
.Render
.Start
= fxCheckTexSizes
;
1227 tnl
->Driver
.Render
.Finish
= fxRenderFinish
;
1228 tnl
->Driver
.Render
.PrimitiveNotify
= fxRenderPrimitive
;
1229 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1230 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1231 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1232 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1233 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1234 tnl
->Driver
.Render
.BuildVertices
= fxBuildVertices
;
1235 tnl
->Driver
.Render
.Multipass
= 0;
1237 (void) fx_print_vertex
;
1245 * Need this to provide at least one external definition.
1248 extern int gl_fx_dummy_function_tris(void);
1250 gl_fx_dummy_function_tris(void)