add GL_EXT_fog_coord support to radeon driver. No vtxfmt code (just uses fallback) yet. May cause a tcl fallback if fog coord is used together with separate specular lighting. Fog factors are precomputed and then submitted instead of the raw coords (chip limitation, same as on r200).
diff --git a/docs/VERSIONS b/docs/VERSIONS
index 58ec9ed..7d14e02 100644
--- a/docs/VERSIONS
+++ b/docs/VERSIONS
@@ -1383,7 +1383,8 @@
 	- GL_EXT_timer_query extension
 	- r200: add support for GL_ATI_fragment_shader
 	- added fast XOR-mode line drawing optimization
-	- radeon: add support for all 3 tmus and cube maps
+	- radeon: add support for all 3 tmus, GL_ARB_texture_cube_map
+	  and GL_EXT_fog_coord
     Changes:
 	- removed GL_HP_occlusion_test (use GL_ARB_occlusion_query instead)
     Bug fixes:
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
index a1e3582..4b81b53 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_context.c
@@ -66,6 +66,7 @@
 #define need_GL_ARB_multisample
 #define need_GL_ARB_texture_compression
 #define need_GL_EXT_blend_minmax
+#define need_GL_EXT_fog_coord
 #define need_GL_EXT_secondary_color
 #include "extension_helper.h"
 
@@ -139,6 +140,7 @@
     { "GL_ARB_texture_mirrored_repeat",    NULL },
     { "GL_EXT_blend_logic_op",             NULL },
     { "GL_EXT_blend_subtract",             GL_EXT_blend_minmax_functions },
+    { "GL_EXT_fog_coord",                  GL_EXT_fog_coord_functions },
     { "GL_EXT_secondary_color",            GL_EXT_secondary_color_functions },
     { "GL_EXT_stencil_wrap",               NULL },
     { "GL_EXT_texture_edge_clamp",         NULL },
@@ -238,6 +240,9 @@
    if ( !rmesa )
       return GL_FALSE;
 
+   /* init exp fog table data */
+   radeonInitStaticFogData();
+   
    /* Parse configuration files.
     * Do this here so that initialMaxAnisotropy is set before we create
     * the default textures.
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
index 76ad1f3..49d6414 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
@@ -48,6 +48,7 @@
 #include "radeon_state.h"
 #include "radeon_swtcl.h"
 #include "radeon_maos.h"
+#include "radeon_tcl.h"
 
 #if 0
 /* Usage:
@@ -169,6 +170,46 @@
 } while (0)
 #endif
 
+static void emit_vecfog( GLcontext *ctx,
+			 struct radeon_dma_region *rvb,
+			 char *data,
+			 int stride,
+			 int count )
+{
+   int i;
+   GLfloat *out;
+
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d\n",
+	      __FUNCTION__, count, stride);
+
+   assert (!rvb->buf);
+
+   if (stride == 0) {
+      radeonAllocDmaRegion( rmesa, rvb, 4, 4 );
+      count = 1;
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = 0;
+      rvb->aos_size = 1;
+   }
+   else {
+      radeonAllocDmaRegion( rmesa, rvb, count * 4, 4 );	/* alignment? */
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = 1;
+      rvb->aos_size = 1;
+   }
+
+   /* Emit the data
+    */
+   out = (GLfloat *)(rvb->address + rvb->start);
+   for (i = 0; i < count; i++) {
+      out[0] = radeonComputeFogBlendFactor( ctx, *(GLfloat *)data );
+      out++;
+      data += stride;
+   }
+}
 
 static void emit_vec4( GLcontext *ctx,
 		       struct radeon_dma_region *rvb,
@@ -525,6 +566,20 @@
       component[nr++] = &rmesa->tcl.spec;
    }
 
+
+   if (inputs & VERT_BIT_FOG) {
+      if (!rmesa->tcl.fog.buf)
+	 emit_vecfog( ctx,
+		      &(rmesa->tcl.fog),
+		      (char *)VB->FogCoordPtr->data,
+		      VB->FogCoordPtr->stride,
+		      count);
+
+      vfmt |= RADEON_CP_VC_FRMT_FPFOG;
+      component[nr++] = &rmesa->tcl.fog;
+   }
+
+
    vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
 	  ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2));
       
@@ -589,6 +644,9 @@
 
    if (newinputs & VERT_BIT_COLOR1) 
       radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
+      
+   if (newinputs & VERT_BIT_FOG)
+      radeonReleaseDmaRegion( rmesa, &rmesa->tcl.fog, __FUNCTION__ );
 
    for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
       if (newinputs & VERT_BIT_TEX(unit))
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h b/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
index 265d061..034cda8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
@@ -50,7 +50,6 @@
    GLuint rqcoordsnoswap = 0;
    GLuint (*coord)[4];
    GLuint coord_stride; /* object coordinates */
-   GLubyte dummy[4];
    int i;
 
    union emit_union *v = (union emit_union *)dest;
@@ -133,7 +132,7 @@
       }
    }
 
-   if (DO_SPEC) {
+   if (DO_SPEC_OR_FOG) {
       if (VB->SecondaryColorPtr[0]) {
 	 spec = VB->SecondaryColorPtr[0]->data;
 	 spec_stride = VB->SecondaryColorPtr[0]->stride;
@@ -143,12 +142,12 @@
       }
    }
 
-   if (DO_FOG) {
+   if (DO_SPEC_OR_FOG) {
       if (VB->FogCoordPtr) {
 	 fog = VB->FogCoordPtr->data;
 	 fog_stride = VB->FogCoordPtr->stride;
       } else {
-	 fog = (GLfloat (*)[4])&dummy; fog[0][0] = 0.0F;
+	 fog = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_FOG];
 	 fog_stride = 0;
       }
    }
@@ -202,7 +201,7 @@
 	    STRIDE_4F(col, col_stride);
 	    v++;
 	 }
-	 if (DO_SPEC || DO_FOG) {
+	 if (DO_SPEC_OR_FOG) {
 	    if (DO_SPEC) {
 	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.red, spec[0][0]);
 	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.green, spec[0][1]);
@@ -210,8 +209,8 @@
 	       STRIDE_4F(spec, spec_stride);
 	    }
 	    if (DO_FOG) {
-	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, fog[0][0]);
-	       fog = (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
+	       UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, radeonComputeFogBlendFactor(ctx, fog[0][0]));
+	       STRIDE_4F(fog, fog_stride);
 	    }
 	    if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
 	    v++;
@@ -283,7 +282,7 @@
    if (DO_W) sz++;
    if (DO_NORM) sz += 3;
    if (DO_RGBA) sz++;
-   if (DO_SPEC || DO_FOG) sz++;
+   if (DO_SPEC_OR_FOG) sz++;
    if (DO_TEX0) sz += 2;
    if (DO_TEX0 && DO_PTEX) sz++;
    if (DO_TEX1) sz += 2;
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
index 24e681c..91a60bb 100644
--- a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
+++ b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
@@ -63,8 +63,11 @@
 
 #define DO_W    (IND & RADEON_CP_VC_FRMT_W0)
 #define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR)
-#define DO_SPEC (IND & RADEON_CP_VC_FRMT_PKSPEC)
-#define DO_FOG  (IND & RADEON_CP_VC_FRMT_PKSPEC)
+#define DO_SPEC_OR_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC)
+#define DO_SPEC ((IND & RADEON_CP_VC_FRMT_PKSPEC) && \
+		 (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
+#define DO_FOG  ((IND & RADEON_CP_VC_FRMT_PKSPEC) && ctx->Fog.Enabled && \
+		 (ctx->Fog.FogCoordinateSource == GL_FOG_COORD))
 #define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0)
 #define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1)
 #define DO_TEX2 (IND & RADEON_CP_VC_FRMT_ST2)
@@ -337,7 +340,7 @@
       req |= RADEON_CP_VC_FRMT_PKCOLOR;
    }
 
-   if (inputs & VERT_BIT_COLOR1) {
+   if (inputs & (VERT_BIT_COLOR1|VERT_BIT_FOG)) {
       req |= RADEON_CP_VC_FRMT_PKSPEC;
    }
 
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
index 2803388..681de91 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state.c
@@ -55,6 +55,8 @@
 #include "radeon_vtxfmt.h"
 #include "drirenderbuffer.h"
 
+static void radeonUpdateSpecular( GLcontext *ctx );
+
 /* =============================================================
  * Alpha blending
  */
@@ -329,9 +331,6 @@
    union { int i; float f; } c, d;
    GLchan col[4];
 
-   c.i = rmesa->hw.fog.cmd[FOG_C];
-   d.i = rmesa->hw.fog.cmd[FOG_D];
-
    switch (pname) {
    case GL_FOG_MODE:
       if (!ctx->Fog.Enabled)
@@ -341,30 +340,24 @@
       switch (ctx->Fog.Mode) {
       case GL_LINEAR:
 	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
-	 if (ctx->Fog.Start == ctx->Fog.End) {
-	    c.f = 1.0F;
-	    d.f = 1.0F;
-	 }
-	 else {
-	    c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
-	    d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
-	 }
 	 break;
       case GL_EXP:
 	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
-	 c.f = 0.0;
-	 d.f = ctx->Fog.Density;
 	 break;
       case GL_EXP2:
 	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
-	 c.f = 0.0;
-	 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
 	 break;
       default:
 	 return;
       }
-      break;
+   /* fallthrough */
    case GL_FOG_DENSITY:
+   case GL_FOG_START:
+   case GL_FOG_END:
+      if (!ctx->Fog.Enabled)
+	 return;
+      c.i = rmesa->hw.fog.cmd[FOG_C];
+      d.i = rmesa->hw.fog.cmd[FOG_D];
       switch (ctx->Fog.Mode) {
       case GL_EXP:
 	 c.f = 0.0;
@@ -374,13 +367,7 @@
 	 c.f = 0.0;
 	 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
 	 break;
-      default:
-	 break;
-      }
-      break;
-   case GL_FOG_START:
-   case GL_FOG_END:
-      if (ctx->Fog.Mode == GL_LINEAR) {
+      case GL_LINEAR:
 	 if (ctx->Fog.Start == ctx->Fog.End) {
 	    c.f = 1.0F;
 	    d.f = 1.0F;
@@ -388,27 +375,29 @@
 	    c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
 	    d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
 	 }
+	 break;
+      default:
+	 break;
+      }
+      if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
+	 RADEON_STATECHANGE( rmesa, fog );
+	 rmesa->hw.fog.cmd[FOG_C] = c.i;
+	 rmesa->hw.fog.cmd[FOG_D] = d.i;
       }
       break;
    case GL_FOG_COLOR: 
       RADEON_STATECHANGE( rmesa, ctx );
       UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
-      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] =
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK;
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |=
 	 radeonPackColor( 4, col[0], col[1], col[2], 0 );
       break;
-   case GL_FOG_COORDINATE_SOURCE_EXT: 
-      /* What to do?
-       */
+   case GL_FOG_COORD_SRC:
+      radeonUpdateSpecular( ctx );
       break;
    default:
       return;
    }
-
-   if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
-      RADEON_STATECHANGE( rmesa, fog );
-      rmesa->hw.fog.cmd[FOG_C] = c.i;
-      rmesa->hw.fog.cmd[FOG_D] = d.i;
-   }
 }
 
 
@@ -692,6 +681,7 @@
 {
    radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
    u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
+   GLuint flag = 0;
 
    RADEON_STATECHANGE( rmesa, tcl );
 
@@ -730,13 +720,22 @@
    }
 
    if (ctx->Fog.Enabled) {
-      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
       rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
-
-      /* Bizzare: have to leave lighting enabled to get fog.
-       */
-      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+      if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) {
+	 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+      /* Bizzare: have to leave lighting enabled to get fog. */
+	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+      }
+      else {
+      /* cannot do tcl fog factor calculation with fog coord source
+       * (send precomputed factors). Cannot use precomputed fog
+       * factors together with tcl spec light (need tcl fallback) */
+	 flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &
+	    RADEON_TCL_COMPUTE_SPECULAR) != 0;
+      }
    }
+ 
+   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
 
    if (NEED_SECONDARY_COLOR(ctx)) {
       assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
@@ -1809,8 +1808,6 @@
 	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
       }
       radeonUpdateSpecular( ctx ); /* for PK_SPEC */
-      if (rmesa->TclFallback) 
-	 radeonChooseVertexState( ctx );
       _mesa_allow_light_in_model( ctx, !state );
       break;
 
diff --git a/src/mesa/drivers/dri/radeon/radeon_state_init.c b/src/mesa/drivers/dri/radeon/radeon_state_init.c
index 6e538a2..6c0298a 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state_init.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state_init.c
@@ -345,6 +345,7 @@
 				     RADEON_RIGHT_HAND_CUBE_OGL */);
 
    rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX |
+					  /* this bit unused for vertex fog */
 					  RADEON_FOG_USE_DEPTH);
 
    rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.c b/src/mesa/drivers/dri/radeon/radeon_tcl.c
index fb0f10a..90383d4 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_tcl.c
@@ -279,6 +279,88 @@
    }
 }
 
+/**********************************************************************/
+/*             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
+radeonInitStaticFogData( 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
+radeonComputeFogBlendFactor( 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                     */
@@ -314,7 +396,7 @@
       }
    }
 
-   if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
+   if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
       inputs |= VERT_BIT_FOG;
    }
 
@@ -445,7 +527,8 @@
    "Texgen unit 0",
    "Texgen unit 1",
    "Texgen unit 2",
-   "User disable"
+   "User disable",
+   "Fogcoord with separate specular lighting"
 };
 
 
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.h b/src/mesa/drivers/dri/radeon/radeon_tcl.h
index 062c9fb..168ab95 100644
--- a/src/mesa/drivers/dri/radeon/radeon_tcl.h
+++ b/src/mesa/drivers/dri/radeon/radeon_tcl.h
@@ -46,7 +46,10 @@
 				 GLuint flags );
 
 extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
-					      
+
+extern void radeonInitStaticFogData( void );
+extern float radeonComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord );
+
 #define RADEON_TCL_FALLBACK_RASTER            0x1 /* rasterization */
 #define RADEON_TCL_FALLBACK_UNFILLED          0x2 /* unfilled tris */
 #define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE     0x4 /* twoside tris */
@@ -55,6 +58,7 @@
 #define RADEON_TCL_FALLBACK_TEXGEN_1          0x20 /* texgen, unit 1 */
 #define RADEON_TCL_FALLBACK_TEXGEN_2          0x40 /* texgen, unit 2 */
 #define RADEON_TCL_FALLBACK_TCL_DISABLE       0x80 /* user disable */
+#define RADEON_TCL_FALLBACK_FOGCOORDSPEC      0x100 /* fogcoord, sep. spec light */
 
 /* max maos_verts vertex format has a size of 18 floats */
 #define RADEON_MAX_TCL_VERTSIZE (18*4)
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
index e554aeb..c734ab8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
@@ -549,7 +549,8 @@
    GLuint ind = RADEON_CP_VC_FRMT_Z;
    GLuint unit;
 
-   if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
+   if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag ||
+      (ctx->Fog.Enabled && (ctx->Fog.FogCoordinateSource == GL_FOG_COORD)))
       return GL_FALSE;
 
    if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) 
@@ -582,6 +583,10 @@
       }
    }
 
+   if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
+      ind |= RADEON_CP_VC_FRMT_PKSPEC;
+   }
+
    for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
       if (ctx->Texture.Unit[unit]._ReallyEnabled) {
 	 if (ctx->Texture.Unit[unit].TexGenEnabled) {
@@ -657,6 +662,9 @@
       UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->red,   ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] );
       UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] );
       UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->blue,  ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] );
+      /* fog ??? */
+/*      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->alpha,
+			       radeonComputeFogFactor(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]) ); */
    }
 
    for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
@@ -948,8 +956,6 @@
 
    /* Not active in supported states; just keep ctx->Current uptodate:
     */
-   vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
-   vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
    vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
    vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
    vfmt->Indexf = _mesa_noop_Indexf;
@@ -986,6 +992,8 @@
    vfmt->VertexAttrib3fvNV = radeon_fallback_VertexAttrib3fvNV;
    vfmt->VertexAttrib4fNV  = radeon_fallback_VertexAttrib4fNV;
    vfmt->VertexAttrib4fvNV = radeon_fallback_VertexAttrib4fvNV;
+   vfmt->FogCoordfEXT = radeon_fallback_FogCoordfEXT;
+   vfmt->FogCoordfvEXT = radeon_fallback_FogCoordfvEXT;
 
    (void)radeon_fallback_vtxfmt;