#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 separate-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) { TNLcontext *tnl = TNL_CONTEXT(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. */ tnl->Driver.PointsFunc = _swsetup_Points; tnl->Driver.LineFunc = _swsetup_Line; tnl->Driver.TriangleFunc = _swsetup_Triangle; tnl->Driver.QuadFunc = _swsetup_Quad; tnl->Driver.RenderTabVerts = _tnl_render_tab_verts; tnl->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); } tnl->Driver.PointsFunc = rast_tab[index].points; tnl->Driver.LineFunc = rast_tab[index].line; tnl->Driver.TriangleFunc = rast_tab[index].triangle; tnl->Driver.QuadFunc = rast_tab[index].quad; fxMesa->render_index = index; if (fxMesa->render_index == 0) { tnl->Driver.RenderTabVerts = fx_render_tab_verts; tnl->Driver.RenderTabElts = fx_render_tab_elts; } else { tnl->Driver.RenderTabVerts = _tnl_render_tab_verts; tnl->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 */