From fc606f7db9072d4f40081aea8f92f1d4489a5115 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Tue, 24 Oct 2006 22:37:51 +0000 Subject: [PATCH] fix (per-vertex) fog when using ARB_vp by incorporating fog factor computation into the vertex program (not yet fixed for swtnl). Simplify (and correct) the VTX_TCL_OUTPUT_VTXFMT handling when using vertex programs, turns out it's solely driven by the needs of the past-vertex stage of the pipeline, this should fix lockups with ill-specified applications using vertex programs (for instance applications enabling fog but not writing to fog coord output will now get (conformant) undefined results instead of lockups). --- src/mesa/drivers/dri/r200/r200_context.h | 6 +- src/mesa/drivers/dri/r200/r200_maos_arrays.c | 21 ++- src/mesa/drivers/dri/r200/r200_state.c | 9 +- src/mesa/drivers/dri/r200/r200_tcl.c | 31 +--- src/mesa/drivers/dri/r200/r200_vertprog.c | 150 +++++++++++++++---- src/mesa/drivers/dri/r200/r200_vertprog.h | 3 + 6 files changed, 153 insertions(+), 67 deletions(-) diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h index 0d252eceafa..07b6d6e12db 100644 --- a/src/mesa/drivers/dri/r200/r200_context.h +++ b/src/mesa/drivers/dri/r200/r200_context.h @@ -102,10 +102,14 @@ typedef void (*r200_point_func)( r200ContextPtr, struct r200_vertex_program { struct gl_vertex_program mesa_program; /* Must be first */ int translated; - VERTEX_SHADER_INSTRUCTION instr[R200_VSF_MAX_INST + 3]; + /* need excess instr: 1 for late loop checking, 2 for + additional instr due to instr/attr, 3 for fog */ + VERTEX_SHADER_INSTRUCTION instr[R200_VSF_MAX_INST + 6]; int pos_end; int inputs[VERT_ATTRIB_MAX]; int native; + int fogpidx; + int fogmode; }; struct r200_colorbuffer_state { diff --git a/src/mesa/drivers/dri/r200/r200_maos_arrays.c b/src/mesa/drivers/dri/r200/r200_maos_arrays.c index 12ea462a400..92348c90caa 100644 --- a/src/mesa/drivers/dri/r200/r200_maos_arrays.c +++ b/src/mesa/drivers/dri/r200/r200_maos_arrays.c @@ -420,12 +420,21 @@ void r200EmitArrays( GLcontext *ctx, GLuint inputs ) } if (inputs & VERT_BIT_FOG) { - if (!rmesa->tcl.fog.buf) - emit_vecfog( ctx, - &(rmesa->tcl.fog), - (char *)VB->FogCoordPtr->data, - VB->FogCoordPtr->stride, - count); + if (!rmesa->tcl.fog.buf) { + if (ctx->VertexProgram._Enabled) + emit_vector( ctx, + &(rmesa->tcl.fog), + (char *)VB->FogCoordPtr->data, + 1, + VB->FogCoordPtr->stride, + count); + else + emit_vecfog( ctx, + &(rmesa->tcl.fog), + (char *)VB->FogCoordPtr->data, + VB->FogCoordPtr->stride, + count); + } vfmt0 |= R200_VTX_DISCRETE_FOG; component[nr++] = &rmesa->tcl.fog; diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c index ff481a46e78..097fbc868a4 100644 --- a/src/mesa/drivers/dri/r200/r200_state.c +++ b/src/mesa/drivers/dri/r200/r200_state.c @@ -490,7 +490,7 @@ static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR]; fog &= ~R200_FOG_USE_MASK; - if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) { + if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) { fog |= R200_FOG_USE_VTX_FOG; out_0 |= R200_VTX_DISCRETE_FOG; } @@ -2219,10 +2219,9 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state ) rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i); }*/ } - /* FIXME: ugly as hell. need to call everything which might change tcl_output_vtxfmt0/1 and compsel */ + /* ugly. Need to call everything which might change compsel. */ r200UpdateSpecular( ctx ); - r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL ); -#if 1 +#if 0 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM), but without it doom3 locks up at always the same places. Why? */ /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before @@ -2251,7 +2250,9 @@ static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state ) else { /* picked up later */ } + /* call functions which change hw state based on ARB_vp enabled or not. */ r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL ); + r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL ); break; case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: diff --git a/src/mesa/drivers/dri/r200/r200_tcl.c b/src/mesa/drivers/dri/r200/r200_tcl.c index 8f50cd99ad1..dab478db92d 100644 --- a/src/mesa/drivers/dri/r200/r200_tcl.c +++ b/src/mesa/drivers/dri/r200/r200_tcl.c @@ -429,8 +429,11 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx, } } else { - GLuint out_vtxfmt0 = 0; - GLuint out_vtxfmt1 = 0; + /* 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 */ @@ -439,50 +442,28 @@ static GLboolean r200_run_tcl_render( GLcontext *ctx, 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; - /* FIXME: this is a mess. Not really sure how to set up TCL_OUTPUT_VTXFMT - in "undefined" cases (e.g. output needed later but not written by vertex program or vice versa) - - however misconfiguration here will almost certainly lock up the chip. - I think at the very least we need to enable tcl outputs which we write to. Maybe even need to - fix up a vertex program so an output needed later always gets written? - For now just set the compsel and output_vtxfmt to the outputs written. - However, for simplicity we assume always all 4 values are written which may not be correct - (but I don't know if it could lead to lockups). */ assert(vp_out & (1 << VERT_RESULT_HPOS)); - out_vtxfmt0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0; - /* FIXME: need to always enable color_0 otherwise doom3's shadow vp (?) will lock up (?) */ - out_vtxfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT; out_compsel = R200_OUTPUT_XYZW; if (vp_out & (1 << VERT_RESULT_COL0)) { - out_vtxfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT; out_compsel |= R200_OUTPUT_COLOR_0; } if (vp_out & (1 << VERT_RESULT_COL1)) { - out_vtxfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT; out_compsel |= R200_OUTPUT_COLOR_1; } - /* FIXME: probably not everything is set up for fogc to work correctly */ if (vp_out & (1 << VERT_RESULT_FOGC)) { - out_vtxfmt0 |= R200_VTX_DISCRETE_FOG; out_compsel |= R200_OUTPUT_DISCRETE_FOG; } if (vp_out & (1 << VERT_RESULT_PSIZ)) { - out_vtxfmt0 |= R200_VTX_POINT_SIZE; out_compsel |= R200_OUTPUT_PT_SIZE; } for (i = VERT_RESULT_TEX0; i < VERT_RESULT_TEX6; i++) { if (vp_out & (1 << i)) { - out_vtxfmt1 |= 4 << ((i - VERT_RESULT_TEX0) * 3); out_compsel |= R200_OUTPUT_TEX_0 << (i - VERT_RESULT_TEX0); } } - if ((rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] != out_vtxfmt0) || - (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] != out_vtxfmt1) || - (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel)) { + if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) { R200_STATECHANGE( rmesa, vtx ); - rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_vtxfmt0; - rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] = out_vtxfmt1; rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel; - /* FIXME: should restore this when disabling vertex programs maybe? */ } } diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.c b/src/mesa/drivers/dri/r200/r200_vertprog.c index 366d242270e..e5417db9b7e 100644 --- a/src/mesa/drivers/dri/r200/r200_vertprog.c +++ b/src/mesa/drivers/dri/r200/r200_vertprog.c @@ -396,7 +396,7 @@ static unsigned long op_operands(enum prog_opcode opcode) * * \return GL_TRUE for success, GL_FALSE for failure. */ -static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) +static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp, GLenum fogmode) { struct gl_vertex_program *mesa_vp = &vp->mesa_program; struct prog_instruction *vpi; @@ -405,9 +405,12 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) unsigned long operands; int are_srcs_scalar; unsigned long hw_op; + int dofogfix = 0; + int fog_temp_i = 0; vp->native = GL_FALSE; vp->translated = GL_TRUE; + vp->fogmode = fogmode; if (mesa_vp->Base.NumInstructions == 0) return GL_FALSE; @@ -445,9 +448,12 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) Smart enough to realize that it doesnt need it? */ int u_temp_i = R200_VSF_MAX_TEMPS - 1; struct prog_src_register src[3]; + struct prog_dst_register dst; /* FIXME: is changing the prog safe to do here? */ - if (mesa_vp->IsPositionInvariant) { + if (mesa_vp->IsPositionInvariant && + /* make sure we only do this once */ + !(mesa_vp->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))) { struct gl_program_parameter_list *paramList; GLint tokens[6] = { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX }; @@ -537,6 +543,15 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) //_mesa_print_program(&mesa_vp->Base); } + /* for fogc, can't change mesa_vp, as it would hose swtnl + maybe should just copy whole prog ? */ + if (mesa_vp->Base.OutputsWritten & VERT_RESULT_FOGC && !vp->fogpidx) { + struct gl_program_parameter_list *paramList; + GLint tokens[6] = { STATE_FOG_PARAMS, 0, 0, 0, 0, 0 }; + paramList = mesa_vp->Base.Parameters; + vp->fogpidx = _mesa_add_state_reference(paramList, tokens); + } + vp->pos_end = 0; mesa_vp->Base.NumNativeInstructions = 0; if (mesa_vp->Base.Parameters) @@ -582,7 +597,7 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) } o_inst = vp->instr; - for(vpi = mesa_vp->Base.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){ + for (vpi = mesa_vp->Base.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){ operands = op_operands(vpi->Opcode); are_srcs_scalar = operands & SCALAR_FLAG; operands &= OP_MASK; @@ -672,6 +687,17 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) } } + dst = vpi->DstReg; + if (dst.File == PROGRAM_OUTPUT && + dst.Index == VERT_RESULT_FOGC && + dst.WriteMask & WRITEMASK_X) { + fog_temp_i = u_temp_i; + dst.File = PROGRAM_TEMPORARY; + dst.Index = fog_temp_i; + dofogfix = 1; + u_temp_i--; + } + /* These ops need special handling. */ switch(vpi->Opcode){ case OPCODE_POW: @@ -679,8 +705,8 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) So may need to insert additional instruction */ if ((src[0].File == src[1].File) && (src[0].Index == src[1].Index)) { - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 0)), SWIZZLE_ZERO, @@ -708,8 +734,8 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) o_inst->src2 = UNUSED_SRC_1; o_inst++; - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(u_temp_i, VSF_IN_COMPONENT_X, VSF_IN_COMPONENT_Y, @@ -725,8 +751,8 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) case OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} case OPCODE_SWZ: - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = ZERO_SRC_0; o_inst->src2 = UNUSED_SRC_1; @@ -737,8 +763,8 @@ static GLboolean r200_translate_vertex_program(struct r200_vertex_program *vp) src[1].File == PROGRAM_TEMPORARY && src[2].File == PROGRAM_TEMPORARY) ? R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD; - o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = t_src(vp, &src[0]); #if 0 if ((o_inst - vp->instr) == 31) { @@ -763,8 +789,8 @@ else { goto next; case OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 0)), @@ -786,8 +812,8 @@ else { goto next; case OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 0)), @@ -801,8 +827,8 @@ else { goto next; case OPCODE_SUB://ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), @@ -816,8 +842,8 @@ else { goto next; case OPCODE_ABS://MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W - o_inst->op=MAKE_VSF_OP(R200_VPI_OUT_OP_MAX, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op=MAKE_VSF_OP(R200_VPI_OUT_OP_MAX, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0=t_src(vp, &src[0]); o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), @@ -836,15 +862,15 @@ else { o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_FRC, (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, - t_dst_mask(vpi->DstReg.WriteMask)); + t_dst_mask(dst.WriteMask)); o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = UNUSED_SRC_0; o_inst->src2 = UNUSED_SRC_1; o_inst++; - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = t_src(vp, &src[0]); o_inst->src1 = MAKE_VSF_SOURCE(u_temp_i, @@ -868,7 +894,7 @@ else { o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, (u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, - t_dst_mask(vpi->DstReg.WriteMask)); + t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y @@ -890,8 +916,8 @@ else { o_inst++; u_temp_i--; - o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MAD, t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MAD, t_dst(&dst), + t_dst_mask(dst.WriteMask)); o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y @@ -924,8 +950,8 @@ else { break; } - o_inst->op = MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst(&vpi->DstReg), - t_dst_mask(vpi->DstReg.WriteMask)); + o_inst->op = MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst(&dst), + t_dst_mask(dst.WriteMask)); if(are_srcs_scalar){ switch(operands){ @@ -979,6 +1005,67 @@ else { } } next: + + if (dofogfix) { + o_inst++; + if (vp->fogmode == GL_EXP) { + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, + (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, + VSF_FLAG_X); + o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); + o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE); + o_inst->src2 = UNUSED_SRC_1; + o_inst++; + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_FOG, + R200_VSF_OUT_CLASS_RESULT_FOGC, + VSF_FLAG_X); + o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); + o_inst->src1 = UNUSED_SRC_0; + o_inst->src2 = UNUSED_SRC_1; + } + else if (vp->fogmode == GL_EXP2) { + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, + (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, + VSF_FLAG_X); + o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); + o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE); + o_inst->src2 = UNUSED_SRC_1; + o_inst++; + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, + (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, + VSF_FLAG_X); + o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); + o_inst->src1 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); + o_inst->src2 = UNUSED_SRC_1; + o_inst++; + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_FOG, + R200_VSF_OUT_CLASS_RESULT_FOGC, + VSF_FLAG_X); + o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); + o_inst->src1 = UNUSED_SRC_0; + o_inst->src2 = UNUSED_SRC_1; + } + else { /* fogmode == GL_LINEAR */ + /* could do that with single op (dot) if using params like + with fixed function pipeline fog */ + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, + (fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, + VSF_FLAG_X); + o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); + o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, Z, Z, Z, Z, PARAM, NONE); + o_inst->src2 = UNUSED_SRC_1; + o_inst++; + o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, + R200_VSF_OUT_CLASS_RESULT_FOGC, + VSF_FLAG_X); + o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); + o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, W, W, W, W, PARAM, NONE); + o_inst->src2 = UNUSED_SRC_1; + + } + dofogfix = 0; + } + if (mesa_vp->Base.NumNativeTemporaries < (mesa_vp->Base.NumTemporaries + (R200_VSF_MAX_TEMPS - 1 - u_temp_i))) { mesa_vp->Base.NumNativeTemporaries = @@ -1019,9 +1106,9 @@ void r200SetupVertexProg( GLcontext *ctx ) { GLboolean fallback; GLint i; - if (!vp->translated) { + if (!vp->translated || (ctx->Fog.Enabled && ctx->Fog.Mode != vp->fogmode)) { rmesa->curr_vp_hw = NULL; - r200_translate_vertex_program(vp); + r200_translate_vertex_program(vp, ctx->Fog.Mode); } /* could optimize setting up vertex progs away for non-tcl hw */ fallback = !(vp->native && r200VertexProgUpdateParams(ctx, vp) && @@ -1142,8 +1229,9 @@ r200ProgramStringNotify(GLcontext *ctx, GLenum target, struct gl_program *prog) switch(target) { case GL_VERTEX_PROGRAM_ARB: vp->translated = GL_FALSE; + vp->fogpidx = 0; /* memset(&vp->translated, 0, sizeof(struct r200_vertex_program) - sizeof(struct gl_vertex_program));*/ - r200_translate_vertex_program(vp); + r200_translate_vertex_program(vp, ctx->Fog.Mode); rmesa->curr_vp_hw = NULL; break; } @@ -1160,7 +1248,7 @@ r200IsProgramNative(GLcontext *ctx, GLenum target, struct gl_program *prog) case GL_VERTEX_STATE_PROGRAM_NV: case GL_VERTEX_PROGRAM_ARB: if (!vp->translated) { - r200_translate_vertex_program(vp); + r200_translate_vertex_program(vp, ctx->Fog.Mode); } /* does not take parameters etc. into account */ return vp->native; diff --git a/src/mesa/drivers/dri/r200/r200_vertprog.h b/src/mesa/drivers/dri/r200/r200_vertprog.h index 0fbe5eec7d9..38168fb2e78 100644 --- a/src/mesa/drivers/dri/r200/r200_vertprog.h +++ b/src/mesa/drivers/dri/r200/r200_vertprog.h @@ -89,6 +89,9 @@ extern void r200SetupVertexProg( GLcontext *ctx ); #define R200_VPI_OUT_OP_EXP (65 << 0) #define R200_VPI_OUT_OP_LOG (66 << 0) +/* this is used for fog. Not sure what's different to normal EX2, + but for fog calcs seems to match sw tnl much more closely. */ +#define R200_VPI_OUT_OP_EXP_FOG (67 << 0) #define R200_VPI_OUT_OP_LIT (68 << 0) #define R200_VPI_OUT_OP_POW (69 << 0) -- 2.30.2