fix (per-vertex) fog when using ARB_vp by incorporating fog factor computation into...
authorRoland Scheidegger <rscheidegger@gmx.ch>
Tue, 24 Oct 2006 22:37:51 +0000 (22:37 +0000)
committerRoland Scheidegger <rscheidegger@gmx.ch>
Tue, 24 Oct 2006 22:37:51 +0000 (22:37 +0000)
src/mesa/drivers/dri/r200/r200_context.h
src/mesa/drivers/dri/r200/r200_maos_arrays.c
src/mesa/drivers/dri/r200/r200_state.c
src/mesa/drivers/dri/r200/r200_tcl.c
src/mesa/drivers/dri/r200/r200_vertprog.c
src/mesa/drivers/dri/r200/r200_vertprog.h

index 0d252eceafa56f375202c6d8e28fbf7ea1ea8390..07b6d6e12db8f5940f59d741d8235029e570f5a3 100644 (file)
@@ -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 {
index 12ea462a400abea13205df635bf151ff7dcf5c04..92348c90caad2b6ffcde4f012dbcd38ab0548980 100644 (file)
@@ -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;
index ff481a46e78251e605615443bb6b8ed62011fdc6..097fbc868a454ab30e7927cddf9554df2d592fc9 100644 (file)
@@ -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:
index 8f50cd99ad135b38ed4243f64dbc4e24fb0a6352..dab478db92db58bfc55f24b6ece538b6757d99d8 100644 (file)
@@ -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? */
       }
    }
 
index 366d242270e735672f7bf74f94fa20466d2dd3e7..e5417db9b7ebcc84cb852641d17d2bed3a5efe1f 100644 (file)
@@ -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;
index 0fbe5eec7d9690224862d85abd6f4f45972a82fb..38168fb2e78cbb967260fad99f63ec1f9e9b6255 100644 (file)
@@ -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)