X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fr200%2Fr200_tcl.c;h=0b3bb281e016604f44259f7336a9dc68b4e48370;hb=5363e3331ba016c9b1b9d5167473d69f32be3dac;hp=daf449060888aceab4a063f51230d925c382e37d;hpb=e946688edac5cdf153652defae3ef732a3487416;p=mesa.git diff --git a/src/mesa/drivers/dri/r200/r200_tcl.c b/src/mesa/drivers/dri/r200/r200_tcl.c index daf44906088..0b3bb281e01 100644 --- a/src/mesa/drivers/dri/r200/r200_tcl.c +++ b/src/mesa/drivers/dri/r200/r200_tcl.c @@ -40,7 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "colormac.h" #include "light.h" -#include "array_cache/acache.h" +#include "vbo/vbo.h" #include "tnl/tnl.h" #include "tnl/t_pipeline.h" @@ -62,13 +62,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define HAVE_TRI_STRIPS 1 #define HAVE_TRI_STRIP_1 0 #define HAVE_TRI_FANS 1 -#define HAVE_QUADS 0 /* hw quad verts in wrong order??? */ +#define HAVE_QUADS 1 #define HAVE_QUAD_STRIPS 1 #define HAVE_POLYGONS 1 #define HAVE_ELTS 1 -#define HW_POINTS R200_VF_PRIM_POINTS +#define HW_POINTS ((ctx->Point.PointSprite || \ + ((ctx->_TriangleCaps & (DD_POINT_SIZE | DD_POINT_ATTEN)) && \ + !(ctx->_TriangleCaps & (DD_POINT_SMOOTH)))) ? \ + R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS) #define HW_LINES R200_VF_PRIM_LINES #define HW_LINE_LOOP 0 #define HW_LINE_STRIP R200_VF_PRIM_LINE_STRIP @@ -140,33 +143,55 @@ static GLboolean discrete_prim[0x10] = { static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr ) { - if (rmesa->dma.flush) - rmesa->dma.flush( rmesa ); + if (rmesa->dma.flush == r200FlushElts && + rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) { - r200EmitAOS( rmesa, - rmesa->tcl.aos_components, - rmesa->tcl.nr_aos_components, 0 ); + GLushort *dest = (GLushort *)(rmesa->store.cmd_buf + + rmesa->store.cmd_used); + + rmesa->store.cmd_used += nr*2; + + return dest; + } + else { + if (rmesa->dma.flush) + rmesa->dma.flush( rmesa ); + + r200EnsureCmdBufSpace( rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) + + rmesa->hw.max_state_size + ELTS_BUFSZ(nr) ); + + r200EmitAOS( rmesa, + rmesa->tcl.aos_components, + rmesa->tcl.nr_aos_components, 0 ); - return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr ); + return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr ); + } } -#define CLOSE_ELTS() R200_NEWPRIM( rmesa ) +#define CLOSE_ELTS() \ +do { \ + if (0) R200_NEWPRIM( rmesa ); \ +} \ +while (0) /* TODO: Try to extend existing primitive if both are identical, * discrete and there are no intervening state changes. (Somewhat * duplicates changes to DrawArrays code) */ -static void EMIT_PRIM( GLcontext *ctx, - GLenum prim, - GLuint hwprim, - GLuint start, - GLuint count) +static void r200EmitPrim( GLcontext *ctx, + GLenum prim, + GLuint hwprim, + GLuint start, + GLuint count) { r200ContextPtr rmesa = R200_CONTEXT( ctx ); r200TclPrimitive( ctx, prim, hwprim ); + r200EnsureCmdBufSpace( rmesa, AOS_BUFSZ(rmesa->tcl.nr_aos_components) + + rmesa->hw.max_state_size + VBUF_BUFSZ ); + r200EmitAOS( rmesa, rmesa->tcl.aos_components, rmesa->tcl.nr_aos_components, @@ -179,7 +204,9 @@ static void EMIT_PRIM( GLcontext *ctx, count - start ); } - +#define EMIT_PRIM(ctx, prim, hwprim, start, count) do { \ + r200EmitPrim( ctx, prim, hwprim, start, count ); \ + (void) rmesa; } while (0) /* Try & join small primitives */ @@ -196,12 +223,15 @@ static void EMIT_PRIM( GLcontext *ctx, #ifdef MESA_BIG_ENDIAN /* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ -#define EMIT_ELT(dest, offset, x) do { \ +#define EMIT_ELT(dest, offset, x) do { \ int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \ GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \ - (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0) + (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); \ + (void)rmesa; } while (0) #else -#define EMIT_ELT(dest, offset, x) (dest)[offset] = (GLushort) (x) +#define EMIT_ELT(dest, offset, x) do { \ + (dest)[offset] = (GLushort) (x); \ + (void)rmesa; } while (0) #endif #define EMIT_TWO_ELTS(dest, offset, x, y) *(GLuint *)((dest)+offset) = ((y)<<16)|(x); @@ -240,12 +270,107 @@ void r200TclPrimitive( GLcontext *ctx, if (newprim != rmesa->tcl.hw_primitive || !discrete_prim[hw_prim&0xf]) { + /* need to disable perspective-correct texturing for point sprites */ + if ((prim & PRIM_MODE_MASK) == GL_POINTS && ctx->Point.PointSprite) { + if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) { + R200_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE; + } + } + else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) { + R200_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE; + } R200_NEWPRIM( rmesa ); rmesa->tcl.hw_primitive = newprim; } } +/**********************************************************************/ +/* Fog blend factor computation for hw tcl */ +/* same calculation used as in t_vb_fog.c */ +/**********************************************************************/ + +#define FOG_EXP_TABLE_SIZE 256 +#define FOG_MAX (10.0) +#define EXP_FOG_MAX .0006595 +#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE) +static GLfloat exp_table[FOG_EXP_TABLE_SIZE]; + +#if 1 +#define NEG_EXP( result, narg ) \ +do { \ + GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR)); \ + GLint k = (GLint) f; \ + if (k > FOG_EXP_TABLE_SIZE-2) \ + result = (GLfloat) EXP_FOG_MAX; \ + else \ + result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \ +} while (0) +#else +#define NEG_EXP( result, narg ) \ +do { \ + result = exp(-narg); \ +} while (0) +#endif + + +/** + * Initialize the exp_table[] lookup table for approximating exp(). + */ +void +r200InitStaticFogData( void ) +{ + GLfloat f = 0.0F; + GLint i = 0; + for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) { + exp_table[i] = (GLfloat) exp(-f); + } +} + + +/** + * Compute per-vertex fog blend factors from fog coordinates by + * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function. + * Fog coordinates are distances from the eye (typically between the + * near and far clip plane distances). + * Note the fog (eye Z) coords may be negative so we use ABS(z) below. + * Fog blend factors are in the range [0,1]. + */ +float +r200ComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord ) +{ + GLfloat end = ctx->Fog.End; + GLfloat d, temp; + const GLfloat z = FABSF(fogcoord); + + switch (ctx->Fog.Mode) { + case GL_LINEAR: + if (ctx->Fog.Start == ctx->Fog.End) + d = 1.0F; + else + d = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + temp = (end - z) * d; + return CLAMP(temp, 0.0F, 1.0F); + break; + case GL_EXP: + d = ctx->Fog.Density; + NEG_EXP( temp, d * z ); + return temp; + break; + case GL_EXP2: + d = ctx->Fog.Density*ctx->Fog.Density; + NEG_EXP( temp, d * z * z ); + return temp; + break; + default: + _mesa_problem(ctx, "Bad fog mode in make_fog_coord"); + return 0; + } +} + + /**********************************************************************/ /* Render pipeline stage */ /**********************************************************************/ @@ -259,6 +384,7 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx, r200ContextPtr rmesa = R200_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; + GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0; GLuint i; /* TODO: separate this from the swtnl pipeline @@ -272,98 +398,100 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx, if (VB->Count == 0) return GL_FALSE; - r200ReleaseArrays( ctx, ~0 /* stage->changed_inputs */ ); - r200EmitArrays( ctx, stage->inputs ); - - rmesa->tcl.Elts = VB->Elts; - - for (i = 0 ; i < VB->PrimitiveCount ; i++) - { - GLuint prim = VB->Primitive[i].mode; - GLuint start = VB->Primitive[i].start; - GLuint length = VB->Primitive[i].count; - - if (!length) - continue; - - if (rmesa->tcl.Elts) - r200EmitEltPrimitive( ctx, start, start+length, prim ); - else - r200EmitPrimitive( ctx, start, start+length, prim ); - } - - return GL_FALSE; /* finished the pipe */ -} - - - -static void r200_check_tcl_render( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint inputs = VERT_BIT_POS; - /* Validate state: */ if (rmesa->NewGLState) r200ValidateState( ctx ); - if (ctx->RenderMode == GL_RENDER) { - /* Make all this event-driven: - */ + if (!ctx->VertexProgram._Enabled) { + /* NOTE: inputs != tnl->render_inputs - these are the untransformed + * inputs. + */ if (ctx->Light.Enabled) { inputs |= VERT_BIT_NORMAL; + } - if (1 || ctx->Light.ColorMaterialEnabled) { - inputs |= VERT_BIT_COLOR0; - } + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { + inputs |= VERT_BIT_COLOR1; } - else { - inputs |= VERT_BIT_COLOR0; - - if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { - inputs |= VERT_BIT_COLOR1; - } + + if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) { + inputs |= VERT_BIT_FOG; } - if (ctx->Texture.Unit[0]._ReallyEnabled) { - if (ctx->Texture.Unit[0].TexGenEnabled) { - if (rmesa->TexGenNeedNormals[0]) { + for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) { + if (ctx->Texture.Unit[i]._ReallyEnabled) { + if (rmesa->TexGenNeedNormals[i]) { inputs |= VERT_BIT_NORMAL; } - } else { - inputs |= VERT_BIT_TEX0; + inputs |= VERT_BIT_TEX(i); } } - - if (ctx->Texture.Unit[1]._ReallyEnabled) { - if (ctx->Texture.Unit[1].TexGenEnabled) { - if (rmesa->TexGenNeedNormals[1]) { - inputs |= VERT_BIT_NORMAL; - } - } else { - inputs |= VERT_BIT_TEX1; + } + else { + /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment + part", since using some vertex interpolator later which is not in + out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex + prog to a not enabled output however, so just don't mess with it. + We only need to change compsel. */ + GLuint out_compsel = 0; + GLuint vp_out = rmesa->curr_vp_hw->mesa_program.Base.OutputsWritten; + /* can't handle other inputs, generic attribs etc. currently - should never arrive here */ + assert ((rmesa->curr_vp_hw->mesa_program.Base.InputsRead & + ~(VERT_BIT_POS | VERT_BIT_NORMAL | VERT_BIT_COLOR0 | VERT_BIT_COLOR1 | + VERT_BIT_FOG | VERT_BIT_TEX0 | VERT_BIT_TEX1 | VERT_BIT_TEX2 | + VERT_BIT_TEX3 | VERT_BIT_TEX4 | VERT_BIT_TEX5)) == 0); + inputs |= rmesa->curr_vp_hw->mesa_program.Base.InputsRead; + assert(vp_out & (1 << VERT_RESULT_HPOS)); + out_compsel = R200_OUTPUT_XYZW; + if (vp_out & (1 << VERT_RESULT_COL0)) { + out_compsel |= R200_OUTPUT_COLOR_0; + } + if (vp_out & (1 << VERT_RESULT_COL1)) { + out_compsel |= R200_OUTPUT_COLOR_1; + } + if (vp_out & (1 << VERT_RESULT_FOGC)) { + out_compsel |= R200_OUTPUT_DISCRETE_FOG; + } + if (vp_out & (1 << VERT_RESULT_PSIZ)) { + out_compsel |= R200_OUTPUT_PT_SIZE; + } + for (i = VERT_RESULT_TEX0; i < VERT_RESULT_TEX6; i++) { + if (vp_out & (1 << i)) { + out_compsel |= R200_OUTPUT_TEX_0 << (i - VERT_RESULT_TEX0); } } + if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) { + R200_STATECHANGE( rmesa, vtx ); + rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel; + } + } + + /* Do the actual work: + */ + r200ReleaseArrays( ctx, ~0 /* stage->changed_inputs */ ); + r200EmitArrays( ctx, inputs ); - stage->inputs = inputs; - stage->active = 1; + rmesa->tcl.Elts = VB->Elts; + + for (i = 0 ; i < VB->PrimitiveCount ; i++) + { + GLuint prim = VB->Primitive[i].mode; + GLuint start = VB->Primitive[i].start; + GLuint length = VB->Primitive[i].count; + + if (!length) + continue; + + if (rmesa->tcl.Elts) + r200EmitEltPrimitive( ctx, start, start+length, prim ); + else + r200EmitPrimitive( ctx, start, start+length, prim ); } - else - stage->active = 0; -} -static void r200_init_tcl_render( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - stage->check = r200_check_tcl_render; - stage->check( ctx, stage ); + return GL_FALSE; /* finished the pipe */ } -static void dtr( struct tnl_pipeline_stage *stage ) -{ - (void)stage; -} /* Initial state for tcl stage. @@ -371,17 +499,10 @@ static void dtr( struct tnl_pipeline_stage *stage ) const struct tnl_pipeline_stage _r200_tcl_stage = { "r200 render", - (_DD_NEW_SEPARATE_SPECULAR | - _NEW_LIGHT| - _NEW_TEXTURE| - _NEW_FOG| - _NEW_RENDERMODE), /* re-check (new inputs) */ - 0, /* re-run (always runs) */ - GL_TRUE, /* active */ - 0, 0, /* inputs (set in check_render), outputs */ - 0, 0, /* changed_inputs, private */ - dtr, /* destructor */ - r200_init_tcl_render, /* check - initially set to alloc data */ + NULL, /* private */ + NULL, + NULL, + NULL, r200_run_tcl_render /* run */ }; @@ -418,18 +539,9 @@ static void transition_to_swtnl( GLcontext *ctx ) * need to put the card into D3D mode to make it work: */ R200_STATECHANGE( rmesa, vap ); - rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_TCL_ENABLE; - rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_D3D_TEX_DEFAULT; - - R200_STATECHANGE( rmesa, vte ); - rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~R200_VTX_W0_FMT; - - R200_STATECHANGE( rmesa, set ); - rmesa->hw.set.cmd[SET_RE_CNTL] |= (R200_VTX_STQ0_D3D | - R200_VTX_STQ1_D3D); + rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_TCL_ENABLE|R200_VAP_PROG_VTX_SHADER_ENABLE); } - static void transition_to_hwtnl( GLcontext *ctx ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); @@ -444,7 +556,7 @@ static void transition_to_hwtnl( GLcontext *ctx ) if ( rmesa->dma.flush ) rmesa->dma.flush( rmesa ); - rmesa->dma.flush = 0; + rmesa->dma.flush = NULL; if (rmesa->swtcl.indexed_verts.buf) r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, @@ -452,18 +564,24 @@ static void transition_to_hwtnl( GLcontext *ctx ) R200_STATECHANGE( rmesa, vap ); rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE; - rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_FORCE_W_TO_ONE | - R200_VAP_D3D_TEX_DEFAULT); + rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE; + if (ctx->VertexProgram._Enabled) { + rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE; + } + + if ( ((rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK) + == R200_FOG_USE_SPEC_ALPHA) && + (ctx->Fog.FogCoordinateSource == GL_FOG_COORD )) { + R200_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK; + rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_VTX_FOG; + } + R200_STATECHANGE( rmesa, vte ); rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT); rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT; - R200_STATECHANGE( rmesa, set ); - rmesa->hw.set.cmd[SET_RE_CNTL] &= ~(R200_VTX_STQ0_D3D | - R200_VTX_STQ1_D3D); - - if (R200_DEBUG & DEBUG_FALLBACKS) fprintf(stderr, "R200 end tcl fallback\n"); } @@ -477,7 +595,12 @@ static char *fallbackStrings[] = { "Texgen unit 0", "Texgen unit 1", "Texgen unit 2", - "User disable" + "Texgen unit 3", + "Texgen unit 4", + "Texgen unit 5", + "User disable", + "Bitmap as points", + "Vertex program" };