📄 fxtris.c
字号:
#define TAG(x) fx_##x##_verts#define ELT(x) x/*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now *//**********************************************************************//* Render clipped primitives *//**********************************************************************/static void fxRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n ){ fxMesaContext fxMesa = FX_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLuint prim = fxMesa->render_primitive; /* Render the new vertices as an unclipped polygon. */ { GLuint *tmp = VB->Elts; VB->Elts = (GLuint *)elts; tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); VB->Elts = tmp; } /* Restore the render primitive */ if (prim != GL_POLYGON) tnl->Driver.Render.PrimitiveNotify( ctx, prim );}static void fxFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n ){ int i; fxMesaContext fxMesa = FX_CONTEXT( ctx ); GrVertex *vertptr = fxMesa->verts; if (n == 3) { grDrawTriangle( VERT(elts[0]), VERT(elts[1]), VERT(elts[2]) ); } else if (n <= 32) { GrVertex *newvptr[32]; for (i = 0 ; i < n ; i++) { newvptr[i] = VERT(elts[i]); } grDrawVertexArray(GR_TRIANGLE_FAN, n, newvptr); } else { const GrVertex *start = VERT(elts[0]); for (i = 2 ; i < n ; i++) { grDrawTriangle( start, VERT(elts[i-1]), VERT(elts[i]) ); } }}/**********************************************************************//* 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_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)#define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \ | DD_TRI_UNFILLED | DD_TRI_TWOSTENCIL)void fxDDChooseRenderState(GLcontext *ctx){ TNLcontext *tnl = TNL_CONTEXT(ctx); fxMesaContext fxMesa = FX_CONTEXT(ctx); GLuint flags = ctx->_TriangleCaps; GLuint index = 0; if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) { if (flags & ANY_RASTER_FLAGS) { if (flags & DD_TRI_TWOSTENCIL) index |= FX_TWOSTENCIL_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 & DD_FLATSHADE) index |= FX_FLAT_BIT; } fxMesa->draw_point = fx_draw_point; fxMesa->draw_line = fx_draw_line; fxMesa->draw_tri = fx_draw_triangle; /* Hook in fallbacks for specific primitives. */ if (flags & (POINT_FALLBACK| LINE_FALLBACK| TRI_FALLBACK)) { if (fxMesa->verbose) { fprintf(stderr, "Voodoo ! fallback (%x), raster (%x)\n", flags & ANY_FALLBACK_FLAGS, flags & ANY_RASTER_FLAGS); } if (flags & POINT_FALLBACK) fxMesa->draw_point = fx_fallback_point; if (flags & LINE_FALLBACK) fxMesa->draw_line = fx_fallback_line; if (flags & TRI_FALLBACK) fxMesa->draw_tri = fx_fallback_tri; index |= FX_FALLBACK_BIT; } } tnl->Driver.Render.Points = rast_tab[index].points; tnl->Driver.Render.Line = rast_tab[index].line; tnl->Driver.Render.ClippedLine = rast_tab[index].line; tnl->Driver.Render.Triangle = rast_tab[index].triangle; tnl->Driver.Render.Quad = rast_tab[index].quad; if (index == 0) { tnl->Driver.Render.PrimTabVerts = fx_render_tab_verts; tnl->Driver.Render.PrimTabElts = fx_render_tab_elts; tnl->Driver.Render.ClippedPolygon = fxFastRenderClippedPoly; } else { tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; tnl->Driver.Render.ClippedPolygon = fxRenderClippedPoly; } fxMesa->render_index = index; /* [dBorca] Hack alert: more a trick than a real plug-in!!! */ if (flags & (DD_POINT_SIZE | DD_POINT_ATTEN)) { /* We need to set the point primitive to go through "rast_tab", * to make sure "POINT" calls "fxMesa->draw_point" instead of * "grDrawPoint". We can achieve this by using FX_FALLBACK_BIT * (not really a total rasterization fallback, so we don't alter * "fxMesa->render_index"). If we get here with DD_POINT_SMOOTH, * we're done, cos we've already set _tnl_render_tab_{verts|elts} * above. Otherwise, the T&L engine can optimize point rendering * by using fx_render_tab_{verts|elts} hence the extra work. */ if (flags & DD_POINT_SMOOTH) { fxMesa->draw_point = fx_draw_point_wide_aa; } else { fxMesa->draw_point = fx_draw_point_wide; fx_render_tab_verts[0] = fx_render_pw_verts; fx_render_tab_elts[0] = fx_render_pw_elts; } tnl->Driver.Render.Points = rast_tab[index|FX_FALLBACK_BIT].points; } else { fx_render_tab_verts[0] = fx_render_vb_points; fx_render_tab_elts[0] = fx_render_points_elts; }}/**********************************************************************//* Runtime render state and callbacks *//**********************************************************************/static void fxRunPipeline( GLcontext *ctx ){ fxMesaContext fxMesa = FX_CONTEXT(ctx); GLuint new_gl_state = fxMesa->new_gl_state; if (TDFX_DEBUG & VERBOSE_PIPELINE) { fprintf(stderr, "fxRunPipeline()\n"); }#if 0 /* Recalculate fog table on projection matrix changes. This used to * be triggered by the NearFar callback. */ if (new_gl_state & _NEW_PROJECTION) fxMesa->new_state |= FX_NEW_FOG;#endif if (new_gl_state & _FX_NEW_IS_IN_HARDWARE) fxCheckIsInHardware(ctx); if (fxMesa->new_state) fxSetupFXUnits(ctx); if (!fxMesa->fallback) { if (new_gl_state & _FX_NEW_RENDERSTATE) fxDDChooseRenderState(ctx); if (new_gl_state & _FX_NEW_SETUP_FUNCTION) fxChooseVertexState(ctx); } if (new_gl_state & _NEW_TEXTURE) { struct gl_texture_unit *t0 = &ctx->Texture.Unit[fxMesa->tmu_source[0]]; struct gl_texture_unit *t1 = &ctx->Texture.Unit[fxMesa->tmu_source[1]]; if (t0->_Current && FX_TEXTURE_DATA(t0)) { fxMesa->s0scale = FX_TEXTURE_DATA(t0)->sScale; fxMesa->t0scale = FX_TEXTURE_DATA(t0)->tScale; fxMesa->inv_s0scale = 1.0F / fxMesa->s0scale; fxMesa->inv_t0scale = 1.0F / fxMesa->t0scale; } if (t1->_Current && FX_TEXTURE_DATA(t1)) { fxMesa->s1scale = FX_TEXTURE_DATA(t1)->sScale; fxMesa->t1scale = FX_TEXTURE_DATA(t1)->tScale; fxMesa->inv_s1scale = 1.0F / fxMesa->s1scale; fxMesa->inv_t1scale = 1.0F / fxMesa->t1scale; } } fxMesa->new_gl_state = 0; _tnl_run_pipeline( ctx );}/* Always called between RenderStart and RenderFinish --> We already * hold the lock. */static void fxRasterPrimitive( GLcontext *ctx, GLenum prim ){ fxMesaContext fxMesa = FX_CONTEXT( ctx ); fxMesa->raster_primitive = prim; fxSetupCull(ctx);}/* Determine the rasterized primitive when not drawing unfilled * polygons. */static void fxRenderPrimitive( GLcontext *ctx, GLenum prim ){ fxMesaContext fxMesa = FX_CONTEXT(ctx); GLuint rprim = reduced_prim[prim]; fxMesa->render_primitive = prim; if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) return; if (fxMesa->raster_primitive != rprim) { fxRasterPrimitive( ctx, rprim ); }}static void fxRenderFinish( GLcontext *ctx ){ fxMesaContext fxMesa = FX_CONTEXT(ctx); if (fxMesa->render_index & FX_FALLBACK_BIT) _swrast_flush( ctx );}/**********************************************************************//* Manage total rasterization fallbacks *//**********************************************************************/static char *fallbackStrings[] = { "3D/Rect/Cube Texture map", "glDrawBuffer(GL_FRONT_AND_BACK)", "Separate specular color", "glEnable/Disable(GL_STENCIL_TEST)", "glRenderMode(selection or feedback)", "glLogicOp()", "Texture env mode", "Texture border", "glColorMask", "blend mode", "multitex"};static char *getFallbackString(GLuint bit){ int i = 0; while (bit > 1) { i++; bit >>= 1; } return fallbackStrings[i];}void fxCheckIsInHardware( GLcontext *ctx ){ fxMesaContext fxMesa = FX_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint oldfallback = fxMesa->fallback; GLuint newfallback = fxMesa->fallback = fx_check_IsInHardware( ctx ); if (newfallback) { if (oldfallback == 0) { if (fxMesa->verbose) { fprintf(stderr, "Voodoo ! enter SW 0x%08x %s\n", newfallback, getFallbackString(newfallback)); } _swsetup_Wakeup( ctx ); } } else { if (oldfallback) { _swrast_flush( ctx ); tnl->Driver.Render.Start = fxCheckTexSizes; tnl->Driver.Render.Finish = fxRenderFinish; tnl->Driver.Render.PrimitiveNotify = fxRenderPrimitive; tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; tnl->Driver.Render.BuildVertices = fxBuildVertices; fxChooseVertexState(ctx); fxDDChooseRenderState(ctx); if (fxMesa->verbose) { fprintf(stderr, "Voodoo ! leave SW 0x%08x %s\n", oldfallback, getFallbackString(oldfallback)); } } tnl->Driver.Render.Multipass = NULL; if (HAVE_SPEC && NEED_SECONDARY_COLOR(ctx)) { tnl->Driver.Render.Multipass = fxMultipass_ColorSum; /* obey stencil, but do not change it */ fxMesa->multipass = GL_TRUE; if (fxMesa->unitsState.stencilEnabled) { fxMesa->new_state |= FX_NEW_STENCIL; } } }}void fxDDInitTriFuncs( GLcontext *ctx ){ TNLcontext *tnl = TNL_CONTEXT(ctx); static int firsttime = 1; if (firsttime) { init_rast_tab(); firsttime = 0; } tnl->Driver.RunPipeline = fxRunPipeline; tnl->Driver.Render.Start = fxCheckTexSizes; tnl->Driver.Render.Finish = fxRenderFinish; tnl->Driver.Render.PrimitiveNotify = fxRenderPrimitive; tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; tnl->Driver.Render.BuildVertices = fxBuildVertices; tnl->Driver.Render.Multipass = NULL; (void) fx_print_vertex;}/* [dBorca] Hack alert: * doesn't work with blending. */static GLbooleanfxMultipass_ColorSum (GLcontext *ctx, GLuint pass){ fxMesaContext fxMesa = FX_CONTEXT(ctx); tfxUnitsState *us = &fxMesa->unitsState; static int t0 = 0; static int t1 = 0; switch (pass) { case 1: /* first pass: the TEXTURED triangles are drawn */ /* set stencil's real values */ fxMesa->multipass = GL_FALSE; if (us->stencilEnabled) { fxSetupStencil(ctx); } /* save per-pass data */ fxMesa->restoreUnitsState = *us; /* turn off texturing */ t0 = ctx->Texture.Unit[0]._ReallyEnabled; t1 = ctx->Texture.Unit[1]._ReallyEnabled; ctx->Texture.Unit[0]._ReallyEnabled = 0; ctx->Texture.Unit[1]._ReallyEnabled = 0; /* SUM the colors */ fxDDBlendEquationSeparate(ctx, GL_FUNC_ADD, GL_FUNC_ADD); fxDDBlendFuncSeparate(ctx, GL_ONE, GL_ONE, GL_ZERO, GL_ONE); fxDDEnable(ctx, GL_BLEND, GL_TRUE); /* make sure we draw only where we want to */ if (us->depthTestEnabled) { switch (us->depthTestFunc) { default: fxDDDepthFunc(ctx, GL_EQUAL); case GL_NEVER: case GL_ALWAYS: ; } fxDDDepthMask(ctx, GL_FALSE); } /* switch to secondary colors */#if FX_PACKEDCOLOR grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PSPEC_OFFSET << 2, GR_PARAM_ENABLE);#else /* !FX_PACKEDCOLOR */ grVertexLayout(GR_PARAM_RGB, GR_VERTEX_SPEC_OFFSET << 2, GR_PARAM_ENABLE);#endif /* !FX_PACKEDCOLOR */ /* don't advertise new state */ fxMesa->new_state = 0; break; case 2: /* 2nd pass (last): the secondary color is summed over texture */ /* restore original state */ *us = fxMesa->restoreUnitsState; /* restore texturing */ ctx->Texture.Unit[0]._ReallyEnabled = t0; ctx->Texture.Unit[1]._ReallyEnabled = t1; /* revert to primary colors */#if FX_PACKEDCOLOR grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PARGB_OFFSET << 2, GR_PARAM_ENABLE);#else /* !FX_PACKEDCOLOR */ grVertexLayout(GR_PARAM_RGB, GR_VERTEX_RGB_OFFSET << 2, GR_PARAM_ENABLE);#endif /* !FX_PACKEDCOLOR */ break; default: assert(0); /* NOTREACHED */ } /* update HW state */ fxSetupBlend(ctx); fxSetupDepthTest(ctx); fxSetupTexture(ctx); return (pass == 1);}#else/* * Need this to provide at least one external definition. */extern int gl_fx_dummy_function_tris(void);intgl_fx_dummy_function_tris(void){ return 0;}#endif /* FX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -