#ifdef HAVE_CONFIG_H #include "conf.h" #endif #if defined(FX) #include "mmath.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" #include "fxdrv.h" #include "fxglidew.h" static void fx_draw_point( GLcontext *ctx, const fxVertex *v ) { GLfloat sz = ctx->Point._Size; if ( sz <= 1.0 ) { grDrawPoint( &(v->v) ); } else { GrVertex verts[4]; sz *= .5; verts[0] = v->v; verts[1] = v->v; verts[2] = v->v; verts[3] = v->v; verts[0].x = v->v.x - sz; verts[0].y = v->v.y - sz; verts[1].x = v->v.x + sz; verts[1].y = v->v.y - sz; verts[2].x = v->v.x + sz; verts[2].y = v->v.y + sz; verts[3].x = v->v.x - sz; verts[3].y = v->v.y + sz; grDrawTriangle( &verts[0], &verts[1], &verts[3] ); grDrawTriangle( &verts[1], &verts[2], &verts[3] ); } } static void fx_draw_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 ) { float width = ctx->Line.Width; if ( width <= 1.0 ) { grDrawLine( &(v0->v), &(v1->v) ); } else { GrVertex verts[4]; float dx, dy, ix, iy; dx = v0->v.x - v1->v.x; dy = v0->v.y - v1->v.y; if (dx * dx > dy * dy) { iy = width * .5; ix = 0; } else { iy = 0; ix = width * .5; } verts[0] = v0->v; verts[0].x -= ix; verts[0].y -= iy; verts[1] = v0->v; verts[1].x += ix; verts[1].y += iy; verts[2] = v1->v; verts[2].x += ix; verts[2].y += iy; verts[3] = v1->v; verts[3].x -= ix; verts[3].y -= iy; grDrawTriangle( &verts[0], &verts[1], &verts[3] ); grDrawTriangle( &verts[1], &verts[2], &verts[3] ); } } static void fx_draw_tri( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 ) { grDrawTriangle( &(v0->v), &(v1->v), &(v2->v) ); } #define FX_COLOR(vert, c) { \ GLubyte *col = c; \ vert->v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \ vert->v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \ vert->v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \ vert->v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \ } #define FX_COPY_COLOR( dst, src ) { \ dst->v.r = src->v.r; \ dst->v.g = src->v.g; \ dst->v.b = src->v.b; \ dst->v.a = src->v.a; \ } #define FX_FLAT_BIT 0x01 #define FX_OFFSET_BIT 0x02 #define FX_TWOSIDE_BIT 0x04 #define FX_UNFILLED_BIT 0x10 #define FX_FALLBACK_BIT 0x20 #define FX_MAX_TRIFUNC 0x40 static struct { points_func points; line_func line; triangle_func triangle; quad_func quad; } rast_tab[FX_MAX_TRIFUNC]; #define IND (0) #define TAG(x) x #include "fxtritmp.h" #define IND (FX_FLAT_BIT) #define TAG(x) x##_flat #include "fxtritmp.h" #define IND (FX_OFFSET_BIT) #define TAG(x) x##_offset #include "fxtritmp.h" #define IND (FX_OFFSET_BIT | FX_FLAT_BIT) #define TAG(x) x##_offset_flat #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT) #define TAG(x) x##_twoside #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT) #define TAG(x) x##_twoside_flat #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT) #define TAG(x) x##_twoside_offset #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT) #define TAG(x) x##_twoside_offset_flat #include "fxtritmp.h" #define IND (FX_FALLBACK_BIT) #define TAG(x) x##_fallback #include "fxtritmp.h" #define IND (FX_FLAT_BIT | FX_FALLBACK_BIT) #define TAG(x) x##_flat_fallback #include "fxtritmp.h" #define IND (FX_OFFSET_BIT | FX_FALLBACK_BIT) #define TAG(x) x##_offset_fallback #include "fxtritmp.h" #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT) #define TAG(x) x##_offset_flat_fallback #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_FALLBACK_BIT) #define TAG(x) x##_twoside_fallback #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT) #define TAG(x) x##_twoside_flat_fallback #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FALLBACK_BIT) #define TAG(x) x##_twoside_offset_fallback #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT) #define TAG(x) x##_twoside_offset_flat_fallback #include "fxtritmp.h" #define IND (FX_UNFILLED_BIT) #define TAG(x) x##_unfilled #include "fxtritmp.h" #define IND (FX_FLAT_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_flat_unfilled #include "fxtritmp.h" #define IND (FX_OFFSET_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_offset_unfilled #include "fxtritmp.h" #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_offset_flat_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_flat_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_offset_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_offset_flat_unfilled #include "fxtritmp.h" #define IND (FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_fallback_unfilled #include "fxtritmp.h" #define IND (FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_flat_fallback_unfilled #include "fxtritmp.h" #define IND (FX_OFFSET_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_offset_fallback_unfilled #include "fxtritmp.h" #define IND (FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_offset_flat_fallback_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_fallback_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_flat_fallback_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_offset_fallback_unfilled #include "fxtritmp.h" #define IND (FX_TWOSIDE_BIT | FX_OFFSET_BIT | FX_FLAT_BIT | FX_FALLBACK_BIT | FX_UNFILLED_BIT) #define TAG(x) x##_twoside_offset_flat_fallback_unfilled #include "fxtritmp.h" void fxDDTrifuncInit( void ) { init(); init_flat(); init_offset(); init_offset_flat(); init_twoside(); init_twoside_flat(); init_twoside_offset(); init_twoside_offset_flat(); init_fallback(); init_flat_fallback(); init_offset_fallback(); init_offset_flat_fallback(); init_twoside_fallback(); init_twoside_flat_fallback(); init_twoside_offset_fallback(); init_twoside_offset_flat_fallback(); init_unfilled(); init_flat_unfilled(); init_offset_unfilled(); init_offset_flat_unfilled(); init_twoside_unfilled(); init_twoside_flat_unfilled(); init_twoside_offset_unfilled(); init_twoside_offset_flat_unfilled(); init_fallback_unfilled(); init_flat_fallback_unfilled(); init_offset_fallback_unfilled(); init_offset_flat_fallback_unfilled(); init_twoside_fallback_unfilled(); init_twoside_flat_fallback_unfilled(); init_twoside_offset_fallback_unfilled(); init_twoside_offset_flat_fallback_unfilled(); } /* Build an SWvertex from a GrVertex. This is workable because in * states where the GrVertex is insufficent (eg seperate-specular), * the driver initiates a total fallback, and builds SWvertices * directly -- it recognizes that it will never have use for the * GrVertex. * * This code is hit only when a mix of accelerated and unaccelerated * primitives are being drawn, and only for the unaccelerated * primitives. */ static void fx_translate_vertex(GLcontext *ctx, const fxVertex *src, SWvertex *dst) { fxMesaContext fxMesa = FX_CONTEXT( ctx ); GLuint ts0 = fxMesa->tmu_source[0]; GLuint ts1 = fxMesa->tmu_source[1]; GLfloat w = 1.0 / src->v.oow; dst->win[0] = src->v.x; dst->win[1] = src->v.y; dst->win[2] = src->v.ooz; dst->win[3] = src->v.oow; dst->color[0] = (GLubyte) src->v.r; dst->color[1] = (GLubyte) src->v.g; dst->color[2] = (GLubyte) src->v.b; dst->color[3] = (GLubyte) src->v.a; dst->texcoord[ts0][0] = fxMesa->inv_s0scale * src->v.tmuvtx[0].sow * w; dst->texcoord[ts0][1] = fxMesa->inv_t0scale * src->v.tmuvtx[0].tow * w; if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU0) dst->texcoord[ts0][3] = src->v.tmuvtx[0].oow * w; else dst->texcoord[ts0][3] = 1.0; dst->texcoord[ts1][0] = fxMesa->inv_s1scale * src->v.tmuvtx[1].sow * w; dst->texcoord[ts1][1] = fxMesa->inv_t1scale * src->v.tmuvtx[1].tow * w; if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU1) dst->texcoord[ts1][3] = src->v.tmuvtx[1].oow * w; else dst->texcoord[ts1][3] = 1.0; } static void fx_fallback_tri( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 ) { SWvertex v[3]; fx_translate_vertex( ctx, v0, &v[0] ); fx_translate_vertex( ctx, v1, &v[1] ); fx_translate_vertex( ctx, v2, &v[2] ); _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); } static void fx_fallback_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 ) { SWvertex v[2]; fx_translate_vertex( ctx, v0, &v[0] ); fx_translate_vertex( ctx, v1, &v[1] ); _swrast_Line( ctx, &v[0], &v[1] ); } static void fx_fallback_point( GLcontext *ctx, const fxVertex *v0 ) { SWvertex v[1]; fx_translate_vertex( ctx, v0, &v[0] ); _swrast_Point( ctx, &v[0] ); } /* System to turn culling off for rasterized lines and points, and * back on for rasterized triangles. */ static void fx_cull_draw_tri( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 ) { fxMesaContext fxMesa = FX_CONTEXT( ctx ); FX_grCullMode(fxMesa->cullMode); fxMesa->draw_line = fxMesa->initial_line; fxMesa->draw_point = fxMesa->initial_point; fxMesa->draw_tri = fxMesa->subsequent_tri; fxMesa->draw_tri( ctx, v0, v1, v2 ); } static void fx_cull_draw_line( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1 ) { fxMesaContext fxMesa = FX_CONTEXT( ctx ); FX_grCullMode( GR_CULL_DISABLE ); fxMesa->draw_point = fxMesa->initial_point; fxMesa->draw_tri = fxMesa->initial_tri; fxMesa->draw_line = fxMesa->subsequent_line; fxMesa->draw_line( ctx, v0, v1 ); } static void fx_cull_draw_point( GLcontext *ctx, const fxVertex *v0 ) { fxMesaContext fxMesa = FX_CONTEXT( ctx ); FX_grCullMode(GR_CULL_DISABLE); fxMesa->draw_line = fxMesa->initial_line; fxMesa->draw_tri = fxMesa->initial_tri; fxMesa->draw_point = fxMesa->subsequent_point; fxMesa->draw_point( ctx, v0 ); } static void fx_null_tri( GLcontext *ctx, const fxVertex *v0, const fxVertex *v1, const fxVertex *v2 ) { (void) v0; (void) v1; (void) v2; } /**********************************************************************/ /* Render whole begin/end objects */ /**********************************************************************/ /* Vertices, no clipping. */ #define RENDER_POINTS( start, count ) \ for ( ; start < count ; start++) \ grDrawPoint( &v[ELT(start)].v ); #define RENDER_LINE( i1, i ) \ grDrawLine( &v[i1].v, &v[i].v ) #define RENDER_TRI( i2, i1, i ) \ grDrawTriangle( &v[i2].v, &v[i1].v, &v[i].v ) #define RENDER_QUAD( i3, i2, i1, i ) \ grDrawTriangle( &v[i3].v, &v[i2].v, &v[i].v ); \ grDrawTriangle( &v[i2].v, &v[i1].v, &v[i].v ) #define TAG(x) fx_##x##_verts #define LOCAL_VARS \ fxVertex *v = FX_CONTEXT(ctx)->verts; \ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ (void) elt; /* Verts, no clipping. */ #define ELT(x) x #define RESET_STIPPLE #define RESET_OCCLUSION #define PRESERVE_VB_DEFS #include "tnl/t_vb_rendertmp.h" /* Elts, no clipping. */ #undef ELT #undef TAG #define TAG(x) fx_##x##_elts #define ELT(x) elt[x] #include "tnl/t_vb_rendertmp.h" /**********************************************************************/ /* Choose render functions */ /**********************************************************************/ #define POINT_FALLBACK (DD_POINT_SMOOTH ) #define LINE_FALLBACK (DD_LINE_STIPPLE) #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE ) #define ANY_FALLBACK (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK) #define ANY_RENDER_FLAGS (DD_FLATSHADE | \ DD_TRI_LIGHT_TWOSIDE | \ DD_TRI_OFFSET | \ DD_TRI_UNFILLED) /* Setup the Point, Line, Triangle and Quad functions based on the * current rendering state. Wherever possible, use the hardware to * render the primitive. Otherwise, fallback to software rendering. */ void fxDDChooseRenderState( GLcontext *ctx ) { fxMesaContext fxMesa = FX_CONTEXT( ctx ); GLuint flags = ctx->_TriangleCaps; GLuint index = 0; if ( !fxMesa->is_in_hardware ) { /* Build software vertices directly. No acceleration is * possible. GrVertices may be insufficient for this mode. */ ctx->Driver.PointsFunc = _swsetup_Points; ctx->Driver.LineFunc = _swsetup_Line; ctx->Driver.TriangleFunc = _swsetup_Triangle; ctx->Driver.QuadFunc = _swsetup_Quad; ctx->Driver.RenderTabVerts = _tnl_render_tab_verts; ctx->Driver.RenderTabElts = _tnl_render_tab_elts; fxMesa->render_index = FX_FALLBACK_BIT; return; } if ( flags & ANY_RENDER_FLAGS ) { if ( flags & DD_FLATSHADE ) index |= FX_FLAT_BIT; if ( flags & DD_TRI_LIGHT_TWOSIDE ) index |= FX_TWOSIDE_BIT; if ( flags & DD_TRI_OFFSET ) index |= FX_OFFSET_BIT; if ( flags & DD_TRI_UNFILLED ) index |= FX_UNFILLED_BIT; } if ( flags & (ANY_FALLBACK| DD_LINE_WIDTH| DD_POINT_SIZE| DD_TRI_CULL_FRONT_BACK) ) { /* Hook in fallbacks for specific primitives. * * Set up a system to turn culling on/off for wide points and * lines. Alternately: figure out what tris to send so that * culling isn't a problem. * * This replaces the ReducedPrimitiveChange mechanism. */ index |= FX_FALLBACK_BIT; fxMesa->initial_point = fx_cull_draw_point; fxMesa->initial_line = fx_cull_draw_line; fxMesa->initial_tri = fx_cull_draw_tri; fxMesa->subsequent_point = fx_draw_point; fxMesa->subsequent_line = fx_draw_line; fxMesa->subsequent_tri = fx_draw_tri; if ( flags & POINT_FALLBACK ) fxMesa->initial_point = fx_fallback_point; if ( flags & LINE_FALLBACK ) fxMesa->initial_line = fx_fallback_line; if ((flags & DD_LINE_SMOOTH) && ctx->Line.Width != 1.0) fxMesa->initial_line = fx_fallback_line; if ( flags & TRI_FALLBACK ) fxMesa->initial_tri = fx_fallback_tri; if ( flags & DD_TRI_CULL_FRONT_BACK ) fxMesa->initial_tri = fx_null_tri; fxMesa->draw_point = fxMesa->initial_point; fxMesa->draw_line = fxMesa->initial_line; fxMesa->draw_tri = fxMesa->initial_tri; } else if (fxMesa->render_index & FX_FALLBACK_BIT) { FX_grCullMode(fxMesa->cullMode); } ctx->Driver.PointsFunc = rast_tab[index].points; ctx->Driver.LineFunc = rast_tab[index].line; ctx->Driver.TriangleFunc = rast_tab[index].triangle; ctx->Driver.QuadFunc = rast_tab[index].quad; fxMesa->render_index = index; if (fxMesa->render_index == 0) { ctx->Driver.RenderTabVerts = fx_render_tab_verts; ctx->Driver.RenderTabElts = fx_render_tab_elts; } else { ctx->Driver.RenderTabVerts = _tnl_render_tab_verts; ctx->Driver.RenderTabElts = _tnl_render_tab_elts; } } #else /* * Need this to provide at least one external definition. */ extern int gl_fx_dummy_function_trifuncs(void); int gl_fx_dummy_function_trifuncs(void) { return 0; } #endif /* FX */