}
}
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 */
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? */
}
}
*
* \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;
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;
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 };
//_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)
}
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;
}
}
+ 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:
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,
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,
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;
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) {
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)),
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)),
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]),
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]),
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,
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
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
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){
}
}
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 =
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) &&
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;
}
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;