Merge SWvertex texcoord and varying fields into attrib[] array field.

Fragment texcoords and varying code is now unified in the point/line/triangle
rasterization code.  In the future, merge color, fog, etc. attribs.
diff --git a/src/mesa/swrast/s_aaline.c b/src/mesa/swrast/s_aaline.c
index b3a2099..c810951 100644
--- a/src/mesa/swrast/s_aaline.c
+++ b/src/mesa/swrast/s_aaline.c
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -67,14 +67,14 @@
    GLfloat iPlane[4];
    /* DO_SPEC */
    GLfloat srPlane[4], sgPlane[4], sbPlane[4];
-   /* DO_TEX or DO_MULTITEX */
-   GLfloat sPlane[MAX_TEXTURE_COORD_UNITS][4];
-   GLfloat tPlane[MAX_TEXTURE_COORD_UNITS][4];
-   GLfloat uPlane[MAX_TEXTURE_COORD_UNITS][4];
-   GLfloat vPlane[MAX_TEXTURE_COORD_UNITS][4];
-   GLfloat lambda[MAX_TEXTURE_COORD_UNITS];
-   GLfloat texWidth[MAX_TEXTURE_COORD_UNITS];
-   GLfloat texHeight[MAX_TEXTURE_COORD_UNITS];
+   /* DO_TEXVAR */
+   GLfloat sPlane[FRAG_ATTRIB_MAX][4];
+   GLfloat tPlane[FRAG_ATTRIB_MAX][4];
+   GLfloat uPlane[FRAG_ATTRIB_MAX][4];
+   GLfloat vPlane[FRAG_ATTRIB_MAX][4];
+   GLfloat lambda[FRAG_ATTRIB_MAX];
+   GLfloat texWidth[FRAG_ATTRIB_MAX];
+   GLfloat texHeight[FRAG_ATTRIB_MAX];
 
    SWspan span;
 };
@@ -499,15 +499,7 @@
 #define DO_Z
 #define DO_FOG
 #define DO_RGBA
-#define DO_TEX
-#include "s_aalinetemp.h"
-
-
-#define NAME(x)  aa_multitex_rgba_##x
-#define DO_Z
-#define DO_FOG
-#define DO_RGBA
-#define DO_MULTITEX
+#define DO_TEXVAR
 #include "s_aalinetemp.h"
 
 
@@ -515,7 +507,7 @@
 #define DO_Z
 #define DO_FOG
 #define DO_RGBA
-#define DO_MULTITEX
+#define DO_TEXVAR
 #define DO_SPEC
 #include "s_aalinetemp.h"
 
@@ -530,18 +522,15 @@
 
    if (ctx->Visual.rgbMode) {
       /* RGBA */
-      if (ctx->Texture._EnabledCoordUnits != 0) {
-         if (ctx->Texture._EnabledCoordUnits > 1) {
-            /* Multitextured! */
-            if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR || 
-                ctx->Fog.ColorSumEnabled)
-               swrast->Line = aa_multitex_spec_line;
-            else
-               swrast->Line = aa_multitex_rgba_line;
-         }
-         else {
+      if (ctx->Texture._EnabledCoordUnits != 0
+          || ctx->FragmentProgram._Current) {
+
+         if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR || 
+             ctx->Fog.ColorSumEnabled)
+            swrast->Line = aa_multitex_spec_line;
+         else
             swrast->Line = aa_tex_rgba_line;
-         }
+
       }
       else {
          swrast->Line = aa_rgba_line;
diff --git a/src/mesa/swrast/s_aalinetemp.h b/src/mesa/swrast/s_aalinetemp.h
index b977ab8..4d33b7d 100644
--- a/src/mesa/swrast/s_aalinetemp.h
+++ b/src/mesa/swrast/s_aalinetemp.h
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,6 +36,7 @@
 static void
 NAME(plot)(GLcontext *ctx, struct LineInfo *line, int ix, int iy)
 {
+   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLfloat fx = (GLfloat) ix;
    const GLfloat fy = (GLfloat) iy;
 #ifdef DO_INDEX
@@ -45,6 +46,8 @@
 #endif
    const GLuint i = line->span.end;
 
+   (void) swrast;
+
    if (coverage == 0.0)
       return;
 
@@ -77,41 +80,29 @@
    line->span.array->spec[i][GCOMP] = solve_plane_chan(fx, fy, line->sgPlane);
    line->span.array->spec[i][BCOMP] = solve_plane_chan(fx, fy, line->sbPlane);
 #endif
-#ifdef DO_TEX
+#if defined(DO_TEXVAR)
    {
-      GLfloat invQ;
-      if (ctx->FragmentProgram._Current) {
-         invQ = 1.0F;
-      }
-      else {
-         invQ = solve_plane_recip(fx, fy, line->vPlane[0]);
-      }
-      line->span.array->attribs[FRAG_ATTRIB_TEX0][i][0] = solve_plane(fx, fy, line->sPlane[0]) * invQ;
-      line->span.array->attribs[FRAG_ATTRIB_TEX0][i][1] = solve_plane(fx, fy, line->tPlane[0]) * invQ;
-      line->span.array->attribs[FRAG_ATTRIB_TEX0][i][2] = solve_plane(fx, fy, line->uPlane[0]) * invQ;
-      line->span.array->lambda[0][i] = compute_lambda(line->sPlane[0],
-                                                      line->tPlane[0], invQ,
-                                                      line->texWidth[0],
-                                                      line->texHeight[0]);
-   }
-#elif defined(DO_MULTITEX)
-   {
-      GLuint unit;
-      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
-         if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+      GLuint attr;
+      for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+         if (swrast->_FragmentAttribs & (1 << attr)) {
+            GLfloat (*attribArray)[4] = line->span.array->attribs[attr];
             GLfloat invQ;
             if (ctx->FragmentProgram._Current) {
                invQ = 1.0F;
             }
             else {
-               invQ = solve_plane_recip(fx, fy, line->vPlane[unit]);
+               invQ = solve_plane_recip(fx, fy, line->vPlane[attr]);
             }
-            line->span.array->attribs[FRAG_ATTRIB_TEX0 + unit][i][0] = solve_plane(fx, fy, line->sPlane[unit]) * invQ;
-            line->span.array->attribs[FRAG_ATTRIB_TEX0 + unit][i][1] = solve_plane(fx, fy, line->tPlane[unit]) * invQ;
-            line->span.array->attribs[FRAG_ATTRIB_TEX0 + unit][i][2] = solve_plane(fx, fy, line->uPlane[unit]) * invQ;
-            line->span.array->lambda[unit][i] = compute_lambda(line->sPlane[unit],
-                                                               line->tPlane[unit], invQ,
-                                                               line->texWidth[unit], line->texHeight[unit]);
+            attribArray[i][0] = solve_plane(fx, fy, line->sPlane[attr]) * invQ;
+            attribArray[i][1] = solve_plane(fx, fy, line->tPlane[attr]) * invQ;
+            attribArray[i][2] = solve_plane(fx, fy, line->uPlane[attr]) * invQ;
+            if (attr < FRAG_ATTRIB_VAR0) {
+               const GLuint unit = attr - FRAG_ATTRIB_TEX0;
+               line->span.array->lambda[unit][i]
+                  = compute_lambda(line->sPlane[attr],
+                                   line->tPlane[attr], invQ,
+                                   line->texWidth[attr], line->texHeight[attr]);
+            }
          }
       }
    }
@@ -214,52 +205,33 @@
       constant_plane(v1->index, line.iPlane);
    }
 #endif
-#ifdef DO_TEX
+#if defined(DO_TEXVAR)
    {
-      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
-      const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
+      GLuint attr;
       const GLfloat invW0 = v0->win[3];
       const GLfloat invW1 = v1->win[3];
-      const GLfloat s0 = v0->texcoord[0][0] * invW0;
-      const GLfloat s1 = v1->texcoord[0][0] * invW1;
-      const GLfloat t0 = v0->texcoord[0][1] * invW0;
-      const GLfloat t1 = v1->texcoord[0][1] * invW1;
-      const GLfloat r0 = v0->texcoord[0][2] * invW0;
-      const GLfloat r1 = v1->texcoord[0][2] * invW1;
-      const GLfloat q0 = v0->texcoord[0][3] * invW0;
-      const GLfloat q1 = v1->texcoord[0][3] * invW1;
-      line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
-      compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[0]);
-      compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[0]);
-      compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[0]);
-      compute_plane(line.x0, line.y0, line.x1, line.y1, q0, q1, line.vPlane[0]);
-      line.texWidth[0] = (GLfloat) texImage->Width;
-      line.texHeight[0] = (GLfloat) texImage->Height;
-   }
-#elif defined(DO_MULTITEX)
-   {
-      GLuint u;
-      line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture.Unit[u]._ReallyEnabled) {
-            const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
-            const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
-            const GLfloat invW0 = v0->win[3];
-            const GLfloat invW1 = v1->win[3];
-            const GLfloat s0 = v0->texcoord[u][0] * invW0;
-            const GLfloat s1 = v1->texcoord[u][0] * invW1;
-            const GLfloat t0 = v0->texcoord[u][1] * invW0;
-            const GLfloat t1 = v1->texcoord[u][1] * invW1;
-            const GLfloat r0 = v0->texcoord[u][2] * invW0;
-            const GLfloat r1 = v1->texcoord[u][2] * invW1;
-            const GLfloat q0 = v0->texcoord[u][3] * invW0;
-            const GLfloat q1 = v1->texcoord[u][3] * invW1;
-            compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[u]);
-            compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[u]);
-            compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[u]);
-            compute_plane(line.x0, line.y0, line.x1, line.y1, q0, q1, line.vPlane[u]);
-            line.texWidth[u]  = (GLfloat) texImage->Width;
-            line.texHeight[u] = (GLfloat) texImage->Height;
+      line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA | SPAN_VARYING);
+      for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+         if (swrast->_FragmentAttribs & (1 << attr)) {
+            const GLfloat s0 = v0->attrib[attr][0] * invW0;
+            const GLfloat s1 = v1->attrib[attr][0] * invW1;
+            const GLfloat t0 = v0->attrib[attr][1] * invW0;
+            const GLfloat t1 = v1->attrib[attr][1] * invW1;
+            const GLfloat r0 = v0->attrib[attr][2] * invW0;
+            const GLfloat r1 = v1->attrib[attr][2] * invW1;
+            const GLfloat q0 = v0->attrib[attr][3] * invW0;
+            const GLfloat q1 = v1->attrib[attr][3] * invW1;
+            compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[attr]);
+            compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[attr]);
+            compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[attr]);
+            compute_plane(line.x0, line.y0, line.x1, line.y1, q0, q1, line.vPlane[attr]);
+            if (attr < FRAG_ATTRIB_VAR0) {
+               const GLuint u = attr - FRAG_ATTRIB_TEX0;
+               const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
+               const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
+               line.texWidth[attr]  = (GLfloat) texImage->Width;
+               line.texHeight[attr] = (GLfloat) texImage->Height;
+            }
          }
       }
    }
@@ -324,6 +296,5 @@
 #undef DO_RGBA
 #undef DO_INDEX
 #undef DO_SPEC
-#undef DO_TEX
-#undef DO_MULTITEX
+#undef DO_TEXVAR
 #undef NAME
diff --git a/src/mesa/swrast/s_aatriangle.c b/src/mesa/swrast/s_aatriangle.c
index 63a13cf..5e3059a 100644
--- a/src/mesa/swrast/s_aatriangle.c
+++ b/src/mesa/swrast/s_aatriangle.c
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -408,7 +408,7 @@
 #define DO_Z
 #define DO_FOG
 #define DO_RGBA
-#define DO_TEX
+#define DO_TEXVAR
 #include "s_aatritemp.h"
 }
 
@@ -422,39 +422,12 @@
 #define DO_Z
 #define DO_FOG
 #define DO_RGBA
-#define DO_TEX
+#define DO_TEXVAR
 #define DO_SPEC
 #include "s_aatritemp.h"
 }
 
 
-static void
-multitex_aa_tri(GLcontext *ctx,
-		const SWvertex *v0,
-		const SWvertex *v1,
-		const SWvertex *v2)
-{
-#define DO_Z
-#define DO_FOG
-#define DO_RGBA
-#define DO_MULTITEX
-#include "s_aatritemp.h"
-}
-
-static void
-spec_multitex_aa_tri(GLcontext *ctx,
-		     const SWvertex *v0,
-		     const SWvertex *v1,
-		     const SWvertex *v2)
-{
-#define DO_Z
-#define DO_FOG
-#define DO_RGBA
-#define DO_MULTITEX
-#define DO_SPEC
-#include "s_aatritemp.h"
-}
-
 
 /*
  * Examine GL state and set swrast->Triangle to an
@@ -465,22 +438,13 @@
 {
    ASSERT(ctx->Polygon.SmoothFlag);
 
-   if (ctx->Texture._EnabledCoordUnits != 0) {
+   if (ctx->Texture._EnabledCoordUnits != 0
+       || ctx->FragmentProgram._Current) {
       if (NEED_SECONDARY_COLOR(ctx)) {
-         if (ctx->Texture._EnabledCoordUnits > 1) {
-            SWRAST_CONTEXT(ctx)->Triangle = spec_multitex_aa_tri;
-         }
-         else {
-            SWRAST_CONTEXT(ctx)->Triangle = spec_tex_aa_tri;
-         }
+         SWRAST_CONTEXT(ctx)->Triangle = spec_tex_aa_tri;
       }
       else {
-         if (ctx->Texture._EnabledCoordUnits > 1) {
-            SWRAST_CONTEXT(ctx)->Triangle = multitex_aa_tri;
-         }
-         else {
-            SWRAST_CONTEXT(ctx)->Triangle = tex_aa_tri;
-         }
+         SWRAST_CONTEXT(ctx)->Triangle = tex_aa_tri;
       }
    }
    else if (ctx->Visual.rgbMode) {
diff --git a/src/mesa/swrast/s_aatritemp.h b/src/mesa/swrast/s_aatritemp.h
index 3359a91..bbf9cc6 100644
--- a/src/mesa/swrast/s_aatritemp.h
+++ b/src/mesa/swrast/s_aatritemp.h
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -36,12 +36,12 @@
  *    DO_RGBA      - if defined, compute RGBA values
  *    DO_INDEX     - if defined, compute color index values
  *    DO_SPEC      - if defined, compute specular RGB values
- *    DO_TEX       - if defined, compute unit 0 STRQ texcoords
- *    DO_MULTITEX  - if defined, compute all unit's STRQ texcoords
+ *    DO_TEXVAR    - if defined, compute texcoords, varying
  */
 
 /*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
 {
+   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLfloat *p0 = v0->win;
    const GLfloat *p1 = v1->win;
    const GLfloat *p2 = v2->win;
@@ -70,20 +70,18 @@
 #ifdef DO_SPEC
    GLfloat srPlane[4], sgPlane[4], sbPlane[4];
 #endif
-#ifdef DO_TEX
-   GLfloat sPlane[4], tPlane[4], uPlane[4], vPlane[4];
-   GLfloat texWidth, texHeight;
-#elif defined(DO_MULTITEX)
-   GLfloat sPlane[MAX_TEXTURE_COORD_UNITS][4];  /* texture S */
-   GLfloat tPlane[MAX_TEXTURE_COORD_UNITS][4];  /* texture T */
-   GLfloat uPlane[MAX_TEXTURE_COORD_UNITS][4];  /* texture R */
-   GLfloat vPlane[MAX_TEXTURE_COORD_UNITS][4];  /* texture Q */
-   GLfloat texWidth[MAX_TEXTURE_COORD_UNITS];
-   GLfloat texHeight[MAX_TEXTURE_COORD_UNITS];
+#if defined(DO_TEXVAR)
+   GLfloat sPlane[FRAG_ATTRIB_MAX][4];  /* texture S */
+   GLfloat tPlane[FRAG_ATTRIB_MAX][4];  /* texture T */
+   GLfloat uPlane[FRAG_ATTRIB_MAX][4];  /* texture R */
+   GLfloat vPlane[FRAG_ATTRIB_MAX][4];  /* texture Q */
+   GLfloat texWidth[FRAG_ATTRIB_MAX];
+   GLfloat texHeight[FRAG_ATTRIB_MAX];
 #endif
    GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
    
-   
+   (void) swrast;
+
    INIT_SPAN(span, GL_POLYGON, 0, 0, SPAN_COVERAGE);
 
    /* determine bottom to top order of vertices */
@@ -179,65 +177,44 @@
    }
    span.arrayMask |= SPAN_SPEC;
 #endif
-#ifdef DO_TEX
+#if defined(DO_TEXVAR)
    {
-      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
-      const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
+      GLuint attr;
       const GLfloat invW0 = v0->win[3];
       const GLfloat invW1 = v1->win[3];
       const GLfloat invW2 = v2->win[3];
-      const GLfloat s0 = v0->texcoord[0][0] * invW0;
-      const GLfloat s1 = v1->texcoord[0][0] * invW1;
-      const GLfloat s2 = v2->texcoord[0][0] * invW2;
-      const GLfloat t0 = v0->texcoord[0][1] * invW0;
-      const GLfloat t1 = v1->texcoord[0][1] * invW1;
-      const GLfloat t2 = v2->texcoord[0][1] * invW2;
-      const GLfloat r0 = v0->texcoord[0][2] * invW0;
-      const GLfloat r1 = v1->texcoord[0][2] * invW1;
-      const GLfloat r2 = v2->texcoord[0][2] * invW2;
-      const GLfloat q0 = v0->texcoord[0][3] * invW0;
-      const GLfloat q1 = v1->texcoord[0][3] * invW1;
-      const GLfloat q2 = v2->texcoord[0][3] * invW2;
-      compute_plane(p0, p1, p2, s0, s1, s2, sPlane);
-      compute_plane(p0, p1, p2, t0, t1, t2, tPlane);
-      compute_plane(p0, p1, p2, r0, r1, r2, uPlane);
-      compute_plane(p0, p1, p2, q0, q1, q2, vPlane);
-      texWidth = (GLfloat) texImage->Width;
-      texHeight = (GLfloat) texImage->Height;
-   }
-   span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
-#elif defined(DO_MULTITEX)
-   {
-      GLuint u;
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture.Unit[u]._ReallyEnabled) {
-            const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
-            const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
-            const GLfloat invW0 = v0->win[3];
-            const GLfloat invW1 = v1->win[3];
-            const GLfloat invW2 = v2->win[3];
-            const GLfloat s0 = v0->texcoord[u][0] * invW0;
-            const GLfloat s1 = v1->texcoord[u][0] * invW1;
-            const GLfloat s2 = v2->texcoord[u][0] * invW2;
-            const GLfloat t0 = v0->texcoord[u][1] * invW0;
-            const GLfloat t1 = v1->texcoord[u][1] * invW1;
-            const GLfloat t2 = v2->texcoord[u][1] * invW2;
-            const GLfloat r0 = v0->texcoord[u][2] * invW0;
-            const GLfloat r1 = v1->texcoord[u][2] * invW1;
-            const GLfloat r2 = v2->texcoord[u][2] * invW2;
-            const GLfloat q0 = v0->texcoord[u][3] * invW0;
-            const GLfloat q1 = v1->texcoord[u][3] * invW1;
-            const GLfloat q2 = v2->texcoord[u][3] * invW2;
-            compute_plane(p0, p1, p2, s0, s1, s2, sPlane[u]);
-            compute_plane(p0, p1, p2, t0, t1, t2, tPlane[u]);
-            compute_plane(p0, p1, p2, r0, r1, r2, uPlane[u]);
-            compute_plane(p0, p1, p2, q0, q1, q2, vPlane[u]);
-            texWidth[u]  = (GLfloat) texImage->Width;
-            texHeight[u] = (GLfloat) texImage->Height;
+      for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+         if (swrast->_FragmentAttribs & (1 << attr)) {
+            const GLfloat s0 = v0->attrib[attr][0] * invW0;
+            const GLfloat s1 = v1->attrib[attr][0] * invW1;
+            const GLfloat s2 = v2->attrib[attr][0] * invW2;
+            const GLfloat t0 = v0->attrib[attr][1] * invW0;
+            const GLfloat t1 = v1->attrib[attr][1] * invW1;
+            const GLfloat t2 = v2->attrib[attr][1] * invW2;
+            const GLfloat r0 = v0->attrib[attr][2] * invW0;
+            const GLfloat r1 = v1->attrib[attr][2] * invW1;
+            const GLfloat r2 = v2->attrib[attr][2] * invW2;
+            const GLfloat q0 = v0->attrib[attr][3] * invW0;
+            const GLfloat q1 = v1->attrib[attr][3] * invW1;
+            const GLfloat q2 = v2->attrib[attr][3] * invW2;
+            compute_plane(p0, p1, p2, s0, s1, s2, sPlane[attr]);
+            compute_plane(p0, p1, p2, t0, t1, t2, tPlane[attr]);
+            compute_plane(p0, p1, p2, r0, r1, r2, uPlane[attr]);
+            compute_plane(p0, p1, p2, q0, q1, q2, vPlane[attr]);
+            if (attr < FRAG_ATTRIB_VAR0) {
+               const GLuint u = attr - FRAG_ATTRIB_TEX0;
+               const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
+               const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
+               texWidth[attr]  = (GLfloat) texImage->Width;
+               texHeight[attr] = (GLfloat) texImage->Height;
+            }
+            else {
+               texWidth[attr] = texHeight[attr] = 1.0;
+            }
          }
       }
    }
-   span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
+   span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA | SPAN_VARYING);
 #endif
 
    /* Begin bottom-to-top scan over the triangle.
@@ -305,28 +282,21 @@
             array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
             array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
 #endif
-#ifdef DO_TEX
+#if defined(DO_TEXVAR)
             {
-               const GLfloat invQ = solve_plane_recip(cx, cy, vPlane);
-               array->attribs[FRAG_ATTRIB_TEX0 + 0][count][0] = solve_plane(cx, cy, sPlane) * invQ;
-               array->attribs[FRAG_ATTRIB_TEX0 + 0][count][1] = solve_plane(cx, cy, tPlane) * invQ;
-               array->attribs[FRAG_ATTRIB_TEX0 + 0][count][2] = solve_plane(cx, cy, uPlane) * invQ;
-               array->lambda[0][count] = compute_lambda(sPlane, tPlane, vPlane,
-                                                      cx, cy, invQ,
-                                                      texWidth, texHeight);
-            }
-#elif defined(DO_MULTITEX)
-            {
-               GLuint unit;
-               for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
-                  if (ctx->Texture.Unit[unit]._ReallyEnabled) {
-                     GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]);
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][count][0] = solve_plane(cx, cy, sPlane[unit]) * invQ;
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][count][1] = solve_plane(cx, cy, tPlane[unit]) * invQ;
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][count][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
-                     array->lambda[unit][count] = compute_lambda(sPlane[unit],
-                                      tPlane[unit], vPlane[unit], cx, cy, invQ,
-                                      texWidth[unit], texHeight[unit]);
+               GLuint attr;
+               for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+                  if (swrast->_FragmentAttribs & (1 << attr)) {
+                     GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]);
+                     array->attribs[attr][count][0] = solve_plane(cx, cy, sPlane[attr]) * invQ;
+                     array->attribs[attr][count][1] = solve_plane(cx, cy, tPlane[attr]) * invQ;
+                     array->attribs[attr][count][2] = solve_plane(cx, cy, uPlane[attr]) * invQ;
+                     if (attr < FRAG_ATTRIB_VAR0) {
+                        const GLuint unit = attr - FRAG_ATTRIB_TEX0;
+                        array->lambda[unit][count] = compute_lambda(sPlane[attr], tPlane[attr],
+                                                                    vPlane[attr], cx, cy, invQ,
+                                                                    texWidth[attr], texHeight[attr]);
+                     }
                   }
                }
             }
@@ -409,30 +379,24 @@
             array->spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
             array->spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
 #endif
-#ifdef DO_TEX
+#if defined(DO_TEXVAR)
             {
-               const GLfloat invQ = solve_plane_recip(cx, cy, vPlane);
-               array->attribs[FRAG_ATTRIB_TEX0][ix][0] = solve_plane(cx, cy, sPlane) * invQ;
-               array->attribs[FRAG_ATTRIB_TEX0][ix][1] = solve_plane(cx, cy, tPlane) * invQ;
-               array->attribs[FRAG_ATTRIB_TEX0][ix][2] = solve_plane(cx, cy, uPlane) * invQ;
-               array->lambda[0][ix] = compute_lambda(sPlane, tPlane, vPlane,
-                                          cx, cy, invQ, texWidth, texHeight);
-            }
-#elif defined(DO_MULTITEX)
-            {
-               GLuint unit;
-               for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
-                  if (ctx->Texture.Unit[unit]._ReallyEnabled) {
-                     GLfloat invQ = solve_plane_recip(cx, cy, vPlane[unit]);
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][ix][0] = solve_plane(cx, cy, sPlane[unit]) * invQ;
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][ix][1] = solve_plane(cx, cy, tPlane[unit]) * invQ;
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][ix][2] = solve_plane(cx, cy, uPlane[unit]) * invQ;
-                     array->lambda[unit][ix] = compute_lambda(sPlane[unit],
-                                                            tPlane[unit],
-                                                            vPlane[unit],
-                                                            cx, cy, invQ,
-                                                            texWidth[unit],
-                                                            texHeight[unit]);
+               GLuint attr;
+               for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+                  if (swrast->_FragmentAttribs & (1 << attr)) {
+                     GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]);
+                     array->attribs[attr][ix][0] = solve_plane(cx, cy, sPlane[attr]) * invQ;
+                     array->attribs[attr][ix][1] = solve_plane(cx, cy, tPlane[attr]) * invQ;
+                     array->attribs[attr][ix][2] = solve_plane(cx, cy, uPlane[attr]) * invQ;
+                     if (attr < FRAG_ATTRIB_VAR0) {
+                        const GLuint unit = attr - FRAG_ATTRIB_TEX0;
+                        array->lambda[unit][ix] = compute_lambda(sPlane[attr],
+                                                                 tPlane[attr],
+                                                                 vPlane[attr],
+                                                                 cx, cy, invQ,
+                                                                 texWidth[attr],
+                                                                 texHeight[attr]);
+                     }
                   }
                }
             }
@@ -471,28 +435,25 @@
                array->attribs[FRAG_ATTRIB_FOGC][j][0]
                   = array->attribs[FRAG_ATTRIB_FOGC][j + left][0];
 #endif
-#ifdef DO_TEX
-               COPY_4V(array->attribs[FRAG_ATTRIB_TEX0 + 0][j], array->attribs[FRAG_ATTRIB_TEX0 + 0][j + left]);
-#endif
-#if defined(DO_MULTITEX) || defined(DO_TEX)
+#if defined(DO_TEXVAR)
                array->lambda[0][j] = array->lambda[0][j + left];
 #endif
                array->coverage[j] = array->coverage[j + left];
             }
          }
-#ifdef DO_MULTITEX
-         /* shift texcoords */
+#ifdef DO_TEXVAR
+         /* shift texcoords, varying */
          {
             SWspanarrays *array = span.array;
-            GLuint unit;
-            for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
-               if (ctx->Texture.Unit[unit]._ReallyEnabled) {
+            GLuint attr;
+            for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+               if (swrast->_FragmentAttribs & (1 << attr)) {
                   GLint j;
                   for (j = 0; j < (GLint) n; j++) {
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][j][0] = array->attribs[FRAG_ATTRIB_TEX0 + unit][j + left][0];
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][j][1] = array->attribs[FRAG_ATTRIB_TEX0 + unit][j + left][1];
-                     array->attribs[FRAG_ATTRIB_TEX0 + unit][j][2] = array->attribs[FRAG_ATTRIB_TEX0 + unit][j + left][2];
-                     array->lambda[unit][j] = array->lambda[unit][j + left];
+                     array->attribs[attr][j][0] = array->attribs[attr][j + left][0];
+                     array->attribs[attr][j][1] = array->attribs[attr][j + left][1];
+                     array->attribs[attr][j][2] = array->attribs[attr][j + left][2];
+                     /*array->lambda[unit][j] = array->lambda[unit][j + left];*/
                   }
                }
             }
@@ -533,12 +494,8 @@
 #undef DO_SPEC
 #endif
 
-#ifdef DO_TEX
-#undef DO_TEX
-#endif
-
-#ifdef DO_MULTITEX
-#undef DO_MULTITEX
+#ifdef DO_TEXVAR
+#undef DO_TEXVAR
 #endif
 
 #ifdef DO_OCCLUSION_TEST
diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c
index ec2f3d6..d8a5520 100644
--- a/src/mesa/swrast/s_context.c
+++ b/src/mesa/swrast/s_context.c
@@ -507,6 +507,50 @@
 }
 
 
+/**
+ * Update the swrast->_FragmentAttribs field.
+ */
+static void
+_swrast_update_fragment_attribs(GLcontext *ctx)
+{
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   
+   if (ctx->FragmentProgram._Current) {
+      swrast->_FragmentAttribs
+         = ctx->FragmentProgram._Current->Base.InputsRead;
+   }
+   else {
+      GLuint u;
+      swrast->_FragmentAttribs = 0x0;
+
+      if (ctx->Depth.Test)
+         swrast->_FragmentAttribs |= FRAG_BIT_WPOS;
+      if (NEED_SECONDARY_COLOR(ctx))
+         swrast->_FragmentAttribs |= FRAG_BIT_COL1;
+      if (swrast->_FogEnabled)
+         swrast->_FragmentAttribs |= FRAG_BIT_FOGC;
+
+      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+         if (ctx->Texture.Unit[u]._ReallyEnabled) {
+            swrast->_FragmentAttribs |= FRAG_BIT_TEX(u);
+         }
+      }
+   }
+
+   /* Find lowest, highest bit set in _FragmentAttribs */
+   {
+      GLuint bits = swrast->_FragmentAttribs;
+      GLuint i = 0;;
+      while (bits) {
+         i++;
+         bits = bits >> 1;
+      }
+      swrast->_MaxFragmentAttrib = i;
+      swrast->_MinFragmentAttrib = FRAG_ATTRIB_TEX0; /* XXX temporary */
+   }
+}
+
+
 void
 _swrast_validate_derived( GLcontext *ctx )
 {
@@ -547,6 +591,12 @@
       if (swrast->NewState & _SWRAST_NEW_RASTERMASK)
  	 _swrast_update_rasterflags( ctx );
 
+      if (swrast->NewState & (_NEW_DEPTH |
+                              _NEW_FOG |
+                              _NEW_PROGRAM |
+                              _NEW_TEXTURE))
+         _swrast_update_fragment_attribs(ctx);
+
       swrast->NewState = 0;
       swrast->StateChanges = 0;
       swrast->InvalidateState = _swrast_invalidate_state;
@@ -806,8 +856,10 @@
       for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
 	 if (ctx->Texture.Unit[i]._ReallyEnabled)
 	    _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i,
-                        v->texcoord[i][0], v->texcoord[i][1],
-                        v->texcoord[i][2], v->texcoord[i][3]);
+                        v->attrib[FRAG_ATTRIB_TEX0 + i][0],
+                        v->attrib[FRAG_ATTRIB_TEX0 + i][1],
+                        v->attrib[FRAG_ATTRIB_TEX0 + i][2],
+                        v->attrib[FRAG_ATTRIB_TEX0 + i][3]);
 
 #if CHAN_TYPE == GL_FLOAT
       _mesa_debug(ctx, "color %f %f %f %f\n",
diff --git a/src/mesa/swrast/s_context.h b/src/mesa/swrast/s_context.h
index b15a22d..a3f61cd 100644
--- a/src/mesa/swrast/s_context.h
+++ b/src/mesa/swrast/s_context.h
@@ -133,6 +133,13 @@
    GLboolean _FogEnabled;
    GLenum _FogMode;  /* either GL_FOG_MODE or fragment program's fog mode */
 
+   /** Fragment attributes to compute during rasterization.
+    * Mask of FRAG_BIT_* flags.
+    */
+   GLbitfield _FragmentAttribs;
+   GLuint _MinFragmentAttrib;  /**< Lowest bit set in _FragmentAttribs */
+   GLuint _MaxFragmentAttrib;  /**< Highest bit set in _FragmentAttribs + 1 */
+
    /* Accum buffer temporaries.
     */
    GLboolean _IntegerAccumMode;	/**< Storing unscaled integers? */
diff --git a/src/mesa/swrast/s_feedback.c b/src/mesa/swrast/s_feedback.c
index 26cb05c..5d3fbdf 100644
--- a/src/mesa/swrast/s_feedback.c
+++ b/src/mesa/swrast/s_feedback.c
@@ -46,10 +46,10 @@
 static void feedback_vertex( GLcontext *ctx,
                              const SWvertex *v, const SWvertex *pv )
 {
-   const GLuint texUnit = 0;  /* See section 5.3 of 1.2.1 spec */
    GLfloat win[4];
    GLfloat color[4];
    GLfloat tc[4];
+   const GLfloat *vtc = v->attrib[FRAG_ATTRIB_TEX0];
 
    win[0] = v->win[0];
    win[1] = v->win[1];
@@ -61,16 +61,15 @@
    color[2] = CHAN_TO_FLOAT(pv->color[2]);
    color[3] = CHAN_TO_FLOAT(pv->color[3]);
 
-   if (v->texcoord[texUnit][3] != 1.0 &&
-       v->texcoord[texUnit][3] != 0.0) {
-      GLfloat invq = 1.0F / v->texcoord[texUnit][3];
-      tc[0] = v->texcoord[texUnit][0] * invq;
-      tc[1] = v->texcoord[texUnit][1] * invq;
-      tc[2] = v->texcoord[texUnit][2] * invq;
-      tc[3] = v->texcoord[texUnit][3];
+   if (vtc[3] != 1.0 && vtc[3] != 0.0) {
+      GLfloat invq = 1.0F / vtc[3];
+      tc[0] = vtc[0] * invq;
+      tc[1] = vtc[1] * invq;
+      tc[2] = vtc[2] * invq;
+      tc[3] = vtc[3];
    }
    else {
-      COPY_4V(tc, v->texcoord[texUnit]);
+      COPY_4V(tc, vtc);
    }
 
    _mesa_feedback_vertex( ctx, win, color, (GLfloat) v->index, tc );
diff --git a/src/mesa/swrast/s_linetemp.h b/src/mesa/swrast/s_linetemp.h
index e3ca4bd..d2f37bf 100644
--- a/src/mesa/swrast/s_linetemp.h
+++ b/src/mesa/swrast/s_linetemp.h
@@ -71,6 +71,7 @@
 static void
 NAME( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
 {
+   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
    SWspan span;
    GLuint interpFlags = 0;
    GLint x0 = (GLint) vert0->win[0];
@@ -99,6 +100,8 @@
    SETUP_CODE
 #endif
 
+   (void) swrast;
+
    /* Cull primitives with malformed coordinates.
     */
    {
@@ -286,14 +289,14 @@
       const GLfloat invw1 = vert1->win[3];
       const GLfloat invLen = 1.0F / numPixels;
       GLfloat ds, dt, dr, dq;
-      span.attrStart[FRAG_ATTRIB_TEX0][0] = invw0 * vert0->texcoord[0][0];
-      span.attrStart[FRAG_ATTRIB_TEX0][1] = invw0 * vert0->texcoord[0][1];
-      span.attrStart[FRAG_ATTRIB_TEX0][2] = invw0 * vert0->texcoord[0][2];
-      span.attrStart[FRAG_ATTRIB_TEX0][3] = invw0 * vert0->texcoord[0][3];
-      ds = (invw1 * vert1->texcoord[0][0]) - span.attrStart[FRAG_ATTRIB_TEX0][0];
-      dt = (invw1 * vert1->texcoord[0][1]) - span.attrStart[FRAG_ATTRIB_TEX0][1];
-      dr = (invw1 * vert1->texcoord[0][2]) - span.attrStart[FRAG_ATTRIB_TEX0][2];
-      dq = (invw1 * vert1->texcoord[0][3]) - span.attrStart[FRAG_ATTRIB_TEX0][3];
+      span.attrStart[FRAG_ATTRIB_TEX0][0] = invw0 * vert0->attrib[FRAG_ATTRIB_TEX0][0];
+      span.attrStart[FRAG_ATTRIB_TEX0][1] = invw0 * vert0->attrib[FRAG_ATTRIB_TEX0][1];
+      span.attrStart[FRAG_ATTRIB_TEX0][2] = invw0 * vert0->attrib[FRAG_ATTRIB_TEX0][2];
+      span.attrStart[FRAG_ATTRIB_TEX0][3] = invw0 * vert0->attrib[FRAG_ATTRIB_TEX0][3];
+      ds = (invw1 * vert1->attrib[FRAG_ATTRIB_TEX0][0]) - span.attrStart[FRAG_ATTRIB_TEX0][0];
+      dt = (invw1 * vert1->attrib[FRAG_ATTRIB_TEX0][1]) - span.attrStart[FRAG_ATTRIB_TEX0][1];
+      dr = (invw1 * vert1->attrib[FRAG_ATTRIB_TEX0][2]) - span.attrStart[FRAG_ATTRIB_TEX0][2];
+      dq = (invw1 * vert1->attrib[FRAG_ATTRIB_TEX0][3]) - span.attrStart[FRAG_ATTRIB_TEX0][3];
       span.attrStepX[FRAG_ATTRIB_TEX0][0] = ds * invLen;
       span.attrStepX[FRAG_ATTRIB_TEX0][1] = dt * invLen;
       span.attrStepX[FRAG_ATTRIB_TEX0][2] = dr * invLen;
@@ -304,25 +307,24 @@
       span.attrStepY[FRAG_ATTRIB_TEX0][3] = 0.0F;
    }
 #endif
-#ifdef INTERP_MULTITEX
-   interpFlags |= SPAN_TEXTURE;
+#if defined(INTERP_MULTITEX) || defined(INTERP_VARYING)
+   interpFlags |= (SPAN_TEXTURE | SPAN_VARYING);
    {
       const GLfloat invLen = 1.0F / numPixels;
-      GLuint u;
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture.Unit[u]._ReallyEnabled) {
-            const GLuint attr = FRAG_ATTRIB_TEX0 + u;
-            const GLfloat invw0 = vert0->win[3];
-            const GLfloat invw1 = vert1->win[3];
+      const GLfloat invw0 = vert0->win[3];
+      const GLfloat invw1 = vert1->win[3];
+      GLuint attr;
+      for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+         if (swrast->_FragmentAttribs & (1 << attr)) {
             GLfloat ds, dt, dr, dq;
-            span.attrStart[attr][0] = invw0 * vert0->texcoord[u][0];
-            span.attrStart[attr][1] = invw0 * vert0->texcoord[u][1];
-            span.attrStart[attr][2] = invw0 * vert0->texcoord[u][2];
-            span.attrStart[attr][3] = invw0 * vert0->texcoord[u][3];
-            ds = (invw1 * vert1->texcoord[u][0]) - span.attrStart[attr][0];
-            dt = (invw1 * vert1->texcoord[u][1]) - span.attrStart[attr][1];
-            dr = (invw1 * vert1->texcoord[u][2]) - span.attrStart[attr][2];
-            dq = (invw1 * vert1->texcoord[u][3]) - span.attrStart[attr][3];
+            span.attrStart[attr][0] = invw0 * vert0->attrib[attr][0];
+            span.attrStart[attr][1] = invw0 * vert0->attrib[attr][1];
+            span.attrStart[attr][2] = invw0 * vert0->attrib[attr][2];
+            span.attrStart[attr][3] = invw0 * vert0->attrib[attr][3];
+            ds = (invw1 * vert1->attrib[attr][0]) - span.attrStart[attr][0];
+            dt = (invw1 * vert1->attrib[attr][1]) - span.attrStart[attr][1];
+            dr = (invw1 * vert1->attrib[attr][2]) - span.attrStart[attr][2];
+            dq = (invw1 * vert1->attrib[attr][3]) - span.attrStart[attr][3];
             span.attrStepX[attr][0] = ds * invLen;
             span.attrStepX[attr][1] = dt * invLen;
             span.attrStepX[attr][2] = dr * invLen;
@@ -335,39 +337,6 @@
       }
    }
 #endif
-#ifdef INTERP_VARYING
-   interpFlags |= SPAN_VARYING;
-   {
-      const GLfloat invLen = 1.0F / numPixels;
-      const GLbitfield inputsUsed = ctx->FragmentProgram._Current ?
-         ctx->FragmentProgram._Current->Base.InputsRead : 0x0;
-      const GLfloat invw0 = vert0->win[3];
-      const GLfloat invw1 = vert1->win[3];
-      GLuint v;
-      for (v = 0; v < MAX_VARYING; v++) {
-         if (inputsUsed & FRAG_BIT_VAR(v)) {
-            GLuint attr = FRAG_ATTRIB_VAR0 + v;
-            GLfloat ds, dt, dr, dq;
-            span.attrStart[attr][0] = invw0 * vert0->varying[v][0];
-            span.attrStart[attr][1] = invw0 * vert0->varying[v][1];
-            span.attrStart[attr][2] = invw0 * vert0->varying[v][2];
-            span.attrStart[attr][3] = invw0 * vert0->varying[v][3];
-            ds = (invw1 * vert1->varying[v][0]) - span.attrStart[attr][0];
-            dt = (invw1 * vert1->varying[v][1]) - span.attrStart[attr][1];
-            dr = (invw1 * vert1->varying[v][2]) - span.attrStart[attr][2];
-            dq = (invw1 * vert1->varying[v][3]) - span.attrStart[attr][3];
-            span.attrStepX[attr][0] = ds * invLen;
-            span.attrStepX[attr][1] = dt * invLen;
-            span.attrStepX[attr][2] = dr * invLen;
-            span.attrStepX[attr][3] = dq * invLen;
-            span.attrStepY[attr][0] = 0.0F;
-            span.attrStepY[attr][1] = 0.0F;
-            span.attrStepY[attr][2] = 0.0F;
-            span.attrStepY[attr][3] = 0.0F;
-         }
-      }
-   }
-#endif
 
    INIT_SPAN(span, GL_LINE, numPixels, interpFlags, SPAN_XY);
 
diff --git a/src/mesa/swrast/s_pointtemp.h b/src/mesa/swrast/s_pointtemp.h
index d211a5a..eca0b9d 100644
--- a/src/mesa/swrast/s_pointtemp.h
+++ b/src/mesa/swrast/s_pointtemp.h
@@ -88,8 +88,8 @@
    const GLuint colorIndex = (GLuint) vert->index; /* XXX round? */
 #endif
 #if FLAGS & TEXTURE
-   GLfloat texcoord[MAX_TEXTURE_COORD_UNITS][4];
-   GLuint u;
+   GLfloat attrib[FRAG_ATTRIB_MAX][4]; /* texture & varying */
+   GLuint attr;
 #endif
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    SWspan *span = &(swrast->PointSpan);
@@ -123,22 +123,22 @@
    span->arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA);
    if (ctx->FragmentProgram._Current) {
       /* Don't divide texture s,t,r by q (use TXP to do that) */
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
-            COPY_4V(texcoord[u], vert->texcoord[u]);
+      for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+         if (swrast->_FragmentAttribs & (1 << attr)) {
+            COPY_4V(attrib[attr], vert->attrib[attr]);
          }
       }
    }
    else {
       /* Divide texture s,t,r by q here */
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
-            const GLfloat q = vert->texcoord[u][3];
+      for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+         if (swrast->_FragmentAttribs & (1 << attr)) {
+            const GLfloat q = vert->attrib[attr][3];
             const GLfloat invQ = (q == 0.0F || q == 1.0F) ? 1.0F : (1.0F / q);
-            texcoord[u][0] = vert->texcoord[u][0] * invQ;
-            texcoord[u][1] = vert->texcoord[u][1] * invQ;
-            texcoord[u][2] = vert->texcoord[u][2] * invQ;
-            texcoord[u][3] = q;
+            attrib[attr][0] = vert->attrib[attr][0] * invQ;
+            attrib[attr][1] = vert->attrib[attr][1] * invQ;
+            attrib[attr][2] = vert->attrib[attr][2] * invQ;
+            attrib[attr][3] = q;
          }
       }
    }
@@ -260,7 +260,7 @@
             count = span->end = 0;
          }
          for (x = xmin; x <= xmax; x++) {
-#if FLAGS & (SPRITE | TEXTURE)
+#if FLAGS & SPRITE
             GLuint u;
 #endif
 
@@ -279,10 +279,13 @@
             span->array->index[count] = colorIndex;
 #endif
 #if FLAGS & TEXTURE
-            for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-               if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
-                  COPY_4V(span->array->attribs[FRAG_ATTRIB_TEX0 + u][count], texcoord[u]);
-                  span->array->lambda[u][count] = 0.0;
+            for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+               if (swrast->_FragmentAttribs & (1 << attr)) {
+                  COPY_4V(span->array->attribs[attr][count], attrib[attr]);
+                  if (attr < FRAG_ATTRIB_VAR0) {
+                     const GLuint u = attr - FRAG_ATTRIB_TEX0;
+                     span->array->lambda[u][count] = 0.0;
+                  }
                }
             }
 #endif
@@ -329,6 +332,7 @@
 
 #if FLAGS & SPRITE
             for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+               GLuint attr = FRAG_ATTRIB_TEX0 + u;
                if (ctx->Texture.Unit[u]._ReallyEnabled) {
                   if (ctx->Point.CoordReplace[u]) {
                      GLfloat s = 0.5F + (x + 0.5F - vert->win[0]) / size;
@@ -340,17 +344,18 @@
                      if (ctx->Point.SpriteRMode == GL_ZERO)
                         r = 0.0F;
                      else if (ctx->Point.SpriteRMode == GL_S)
-                        r = vert->texcoord[u][0];
+                        r = vert->attrib[attr][0];
                      else /* GL_R */
-                        r = vert->texcoord[u][2];
-                     span->array->attribs[FRAG_ATTRIB_TEX0 + u][count][0] = s;
-                     span->array->attribs[FRAG_ATTRIB_TEX0 + u][count][1] = t;
-                     span->array->attribs[FRAG_ATTRIB_TEX0 + u][count][2] = r;
-                     span->array->attribs[FRAG_ATTRIB_TEX0 + u][count][3] = 1.0F;
+                        r = vert->attrib[attr][2];
+                     span->array->attribs[attr][count][0] = s;
+                     span->array->attribs[attr][count][1] = t;
+                     span->array->attribs[attr][count][2] = r;
+                     span->array->attribs[attr][count][3] = 1.0F;
                      span->array->lambda[u][count] = 0.0; /* XXX fix? */
                   }
                   else {
-                     COPY_4V(span->array->attribs[FRAG_ATTRIB_TEX0 + u][count], vert->texcoord[u]);
+                     COPY_4V(span->array->attribs[attr][count],
+                             vert->attrib[attr]);
                   }
                }
             }
@@ -401,9 +406,9 @@
       span->array->index[count] = colorIndex;
 #endif
 #if FLAGS & TEXTURE
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
-         if (ctx->Texture.Unit[u]._ReallyEnabled) {
-            COPY_4V(span->array->attribs[FRAG_ATTRIB_TEX0 + u][count], texcoord[u]);
+      for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) {
+         if (swrast->_FragmentAttribs & (1 << attr)) {
+            COPY_4V(span->array->attribs[attr][count], attribs[attr]);
          }
       }
 #endif
diff --git a/src/mesa/swrast/s_triangle.c b/src/mesa/swrast/s_triangle.c
index 6c2e386..3b7960b 100644
--- a/src/mesa/swrast/s_triangle.c
+++ b/src/mesa/swrast/s_triangle.c
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.2
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -866,7 +866,6 @@
 
 /*
  * Render a smooth-shaded, textured, RGBA triangle.
- * Interpolate S,T,R with perspective correction, w/out mipmapping.
  */
 #define NAME general_textured_triangle
 #define INTERP_Z 1
@@ -881,24 +880,6 @@
 
 
 
-/*
- * This is the big one!
- * Interpolate Z, RGB, Alpha, specular, fog, N sets of texture coordinates,
- * and varying floats.  Yup, it's slow.
- */
-#define NAME multitextured_triangle
-#define INTERP_Z 1
-#define INTERP_W 1
-#define INTERP_FOG 1
-#define INTERP_RGB 1
-#define INTERP_ALPHA 1
-#define INTERP_SPEC 1
-#define INTERP_MULTITEX 1
-#define INTERP_VARYING 1
-#define RENDER_SPAN( span )   _swrast_write_rgba_span(ctx, &span);
-#include "s_tritemp.h"
-
-
 
 /*
  * Special tri function for occlusion testing
@@ -1137,13 +1118,7 @@
 	 }
          else {
             /* general case textured triangles */
-            if (ctx->Texture._EnabledCoordUnits > 1 ||
-                ctx->FragmentProgram._Current) {
-               USE(multitextured_triangle);
-            }
-            else {
-               USE(general_textured_triangle);
-            }
+            USE(general_textured_triangle);
          }
       }
       else {
diff --git a/src/mesa/swrast/s_tritemp.h b/src/mesa/swrast/s_tritemp.h
index 83b2f03..435491a 100644
--- a/src/mesa/swrast/s_tritemp.h
+++ b/src/mesa/swrast/s_tritemp.h
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  6.5.3
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -38,10 +38,8 @@
  *    INTERP_INDEX    - if defined, interpolate color index values
  *    INTERP_INT_TEX  - if defined, interpolate integer ST texcoords
  *                         (fast, simple 2-D texture mapping)
- *    INTERP_TEX      - if defined, interpolate set 0 float STRQ texcoords
+ *    INTERP_TEX      - if defined, interpolate texcoords and varying vars
  *                         NOTE:  OpenGL STRQ = Mesa STUV (R was taken for red)
- *    INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords
- *    INTERP_VARYING  - if defined, interpolate M GLSL varyings
  *
  * When one can directly address pixels in the color buffer the following
  * macros can be defined and used to compute pixel addresses during
@@ -119,52 +117,19 @@
 #endif
 
 
-/*
- * Either loop over all texture units, or just use unit zero.
- */
-#ifdef INTERP_MULTITEX
-#define TEX_UNIT_LOOP(CODE)					\
-   {								\
-      GLuint u;							\
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {	\
-         if (ctx->Texture._EnabledCoordUnits & (1 << u)) {	\
-            const GLuint attr = FRAG_ATTRIB_TEX0 + u;		\
-            (void) attr;                                        \
-            CODE						\
-         }							\
-      }								\
+#define TEXVAR_LOOP(CODE)                                \
+   {                                                     \
+      GLuint attr;                                       \
+      for (attr = swrast->_MinFragmentAttrib;            \
+           attr < swrast->_MaxFragmentAttrib; attr++) {  \
+         if (swrast->_FragmentAttribs & (1 << attr)) {   \
+            CODE                                         \
+         }                                               \
+      }                                                  \
    }
-#define INTERP_TEX
-#elif defined(INTERP_TEX)
-#define TEX_UNIT_LOOP(CODE)					\
-   {								\
-      const GLuint u = 0;					\
-      const GLuint attr = FRAG_ATTRIB_TEX0 + u;			\
-      (void) attr;                                              \
-      CODE							\
-   }
-#endif
 
 
 
-#ifdef INTERP_VARYING
-
-#define VARYING_LOOP(CODE)                       \
-   {                                             \
-      GLuint iv, ic;                             \
-      for (iv = 0; iv < MAX_VARYING; iv++) {     \
-         if (inputsUsed & FRAG_BIT_VAR(iv)) {    \
-            GLuint attr = FRAG_ATTRIB_VAR0 + iv; \
-            (void) attr;                         \
-            for (ic = 0; ic < 4; ic++) {         \
-               CODE                              \
-            }                                    \
-         }                                       \
-      }                                          \
-   }
-#endif
-
-
 
 /*
  * Some code we unfortunately need to prevent negative interpolated colors.
@@ -210,6 +175,7 @@
       GLint lines;	/* number of lines to be sampled on this edge */
    } EdgeT;
 
+   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
 #ifdef INTERP_Z
    const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
    const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
@@ -224,13 +190,11 @@
    const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
 #endif
    GLinterp vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
-#ifdef INTERP_VARYING
-   const GLbitfield inputsUsed = ctx->FragmentProgram._Current ?
-      ctx->FragmentProgram._Current->Base.InputsRead : 0x0;
-#endif
 
    SWspan span;
 
+   (void) swrast;
+
    INIT_SPAN(span, GL_POLYGON, 0, 0, 0);
 
 #ifdef INTERP_Z
@@ -638,10 +602,10 @@
 #ifdef INTERP_INT_TEX
       span.interpMask |= SPAN_INT_TEXTURE;
       {
-         GLfloat eMaj_ds = (vMax->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
-         GLfloat eBot_ds = (vMid->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
-         GLfloat eMaj_dt = (vMax->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
-         GLfloat eBot_dt = (vMid->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
+         GLfloat eMaj_ds = (vMax->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
+         GLfloat eBot_ds = (vMid->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
+         GLfloat eMaj_dt = (vMax->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
+         GLfloat eBot_dt = (vMid->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
          span.attrStepX[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
          span.attrStepY[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
          span.attrStepX[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
@@ -651,19 +615,19 @@
       }
 #endif
 #ifdef INTERP_TEX
-      span.interpMask |= SPAN_TEXTURE;
+      span.interpMask |= (SPAN_TEXTURE | SPAN_VARYING);
       {
          /* win[3] is 1/W */
          const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
-         TEX_UNIT_LOOP(
-            GLfloat eMaj_ds = vMax->texcoord[u][0] * wMax - vMin->texcoord[u][0] * wMin;
-            GLfloat eBot_ds = vMid->texcoord[u][0] * wMid - vMin->texcoord[u][0] * wMin;
-            GLfloat eMaj_dt = vMax->texcoord[u][1] * wMax - vMin->texcoord[u][1] * wMin;
-            GLfloat eBot_dt = vMid->texcoord[u][1] * wMid - vMin->texcoord[u][1] * wMin;
-            GLfloat eMaj_du = vMax->texcoord[u][2] * wMax - vMin->texcoord[u][2] * wMin;
-            GLfloat eBot_du = vMid->texcoord[u][2] * wMid - vMin->texcoord[u][2] * wMin;
-            GLfloat eMaj_dv = vMax->texcoord[u][3] * wMax - vMin->texcoord[u][3] * wMin;
-            GLfloat eBot_dv = vMid->texcoord[u][3] * wMid - vMin->texcoord[u][3] * wMin;
+         TEXVAR_LOOP(
+            GLfloat eMaj_ds = vMax->attrib[attr][0] * wMax - vMin->attrib[attr][0] * wMin;
+            GLfloat eBot_ds = vMid->attrib[attr][0] * wMid - vMin->attrib[attr][0] * wMin;
+            GLfloat eMaj_dt = vMax->attrib[attr][1] * wMax - vMin->attrib[attr][1] * wMin;
+            GLfloat eBot_dt = vMid->attrib[attr][1] * wMid - vMin->attrib[attr][1] * wMin;
+            GLfloat eMaj_du = vMax->attrib[attr][2] * wMax - vMin->attrib[attr][2] * wMin;
+            GLfloat eBot_du = vMid->attrib[attr][2] * wMid - vMin->attrib[attr][2] * wMin;
+            GLfloat eMaj_dv = vMax->attrib[attr][3] * wMax - vMin->attrib[attr][3] * wMin;
+            GLfloat eBot_dv = vMid->attrib[attr][3] * wMid - vMin->attrib[attr][3] * wMin;
             span.attrStepX[attr][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
             span.attrStepY[attr][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
             span.attrStepX[attr][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
@@ -675,19 +639,6 @@
          )
       }
 #endif
-#ifdef INTERP_VARYING
-      span.interpMask |= SPAN_VARYING;
-      {
-         /* win[3] is 1/W */
-         const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
-         VARYING_LOOP(
-            GLfloat eMaj_dvar = vMax->varying[iv][ic] * wMax - vMin->varying[iv][ic] * wMin;
-            GLfloat eBot_dvar = vMid->varying[iv][ic] * wMid - vMin->varying[iv][ic] * wMin;
-            span.attrStepX[attr][ic] = oneOverArea * (eMaj_dvar * eBot.dy - eMaj.dy * eBot_dvar);
-            span.attrStepY[attr][ic] = oneOverArea * (eMaj.dx * eBot_dvar - eMaj_dvar * eBot.dx);
-         )
-      }
-#endif
 
       /*
        * We always sample at pixel centers.  However, we avoid
@@ -782,19 +733,14 @@
          GLfixed tLeft=0, dtOuter=0, dtInner;
 #endif
 #ifdef INTERP_TEX
-         GLfloat sLeft[MAX_TEXTURE_COORD_UNITS];
-         GLfloat tLeft[MAX_TEXTURE_COORD_UNITS];
-         GLfloat uLeft[MAX_TEXTURE_COORD_UNITS];
-         GLfloat vLeft[MAX_TEXTURE_COORD_UNITS];
-         GLfloat dsOuter[MAX_TEXTURE_COORD_UNITS], dsInner[MAX_TEXTURE_COORD_UNITS];
-         GLfloat dtOuter[MAX_TEXTURE_COORD_UNITS], dtInner[MAX_TEXTURE_COORD_UNITS];
-         GLfloat duOuter[MAX_TEXTURE_COORD_UNITS], duInner[MAX_TEXTURE_COORD_UNITS];
-         GLfloat dvOuter[MAX_TEXTURE_COORD_UNITS], dvInner[MAX_TEXTURE_COORD_UNITS];
-#endif
-#ifdef INTERP_VARYING
-         GLfloat varLeft[MAX_VARYING][4];
-         GLfloat dvarOuter[MAX_VARYING][4];
-         GLfloat dvarInner[MAX_VARYING][4];
+         GLfloat sLeft[FRAG_ATTRIB_MAX];
+         GLfloat tLeft[FRAG_ATTRIB_MAX];
+         GLfloat uLeft[FRAG_ATTRIB_MAX];
+         GLfloat vLeft[FRAG_ATTRIB_MAX];
+         GLfloat dsOuter[FRAG_ATTRIB_MAX], dsInner[FRAG_ATTRIB_MAX];
+         GLfloat dtOuter[FRAG_ATTRIB_MAX], dtInner[FRAG_ATTRIB_MAX];
+         GLfloat duOuter[FRAG_ATTRIB_MAX], duInner[FRAG_ATTRIB_MAX];
+         GLfloat dvOuter[FRAG_ATTRIB_MAX], dvInner[FRAG_ATTRIB_MAX];
 #endif
 
          for (subTriangle=0; subTriangle<=1; subTriangle++) {
@@ -1042,41 +988,32 @@
 #ifdef INTERP_INT_TEX
                {
                   GLfloat s0, t0;
-                  s0 = vLower->texcoord[0][0] * S_SCALE;
+                  s0 = vLower->attrib[FRAG_ATTRIB_TEX0][0] * S_SCALE;
                   sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][0] * adjx
                                  + span.attrStepY[FRAG_ATTRIB_TEX0][0] * adjy) + FIXED_HALF;
                   dsOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][0]);
 
-                  t0 = vLower->texcoord[0][1] * T_SCALE;
+                  t0 = vLower->attrib[FRAG_ATTRIB_TEX0][1] * T_SCALE;
                   tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][1] * adjx
                                  + span.attrStepY[FRAG_ATTRIB_TEX0][1] * adjy) + FIXED_HALF;
                   dtOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][1]);
                }
 #endif
 #ifdef INTERP_TEX
-               TEX_UNIT_LOOP(
+               TEXVAR_LOOP(
                   const GLfloat invW = vLower->win[3];
-                  const GLfloat s0 = vLower->texcoord[u][0] * invW;
-                  const GLfloat t0 = vLower->texcoord[u][1] * invW;
-                  const GLfloat u0 = vLower->texcoord[u][2] * invW;
-                  const GLfloat v0 = vLower->texcoord[u][3] * invW;
-                  sLeft[u] = s0 + (span.attrStepX[attr][0] * adjx + span.attrStepY[attr][0] * adjy) * (1.0F/FIXED_SCALE);
-                  tLeft[u] = t0 + (span.attrStepX[attr][1] * adjx + span.attrStepY[attr][1] * adjy) * (1.0F/FIXED_SCALE);
-                  uLeft[u] = u0 + (span.attrStepX[attr][2] * adjx + span.attrStepY[attr][2] * adjy) * (1.0F/FIXED_SCALE);
-                  vLeft[u] = v0 + (span.attrStepX[attr][3] * adjx + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
-                  dsOuter[u] = span.attrStepY[attr][0] + dxOuter * span.attrStepX[attr][0];
-                  dtOuter[u] = span.attrStepY[attr][1] + dxOuter * span.attrStepX[attr][1];
-                  duOuter[u] = span.attrStepY[attr][2] + dxOuter * span.attrStepX[attr][2];
-                  dvOuter[u] = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
-               )
-#endif
-#ifdef INTERP_VARYING
-               VARYING_LOOP(
-                  const GLfloat invW = vLower->win[3];
-                  const GLfloat var0 = vLower->varying[iv][ic] * invW;
-                  varLeft[iv][ic] = var0 + (span.attrStepX[attr][ic] * adjx +
-                     span.attrStepY[attr][ic] * adjy) * (1.0f / FIXED_SCALE);
-                  dvarOuter[iv][ic] = span.attrStepY[attr][ic] + dxOuter * span.attrStepX[attr][ic];
+                  const GLfloat s0 = vLower->attrib[attr][0] * invW;
+                  const GLfloat t0 = vLower->attrib[attr][1] * invW;
+                  const GLfloat u0 = vLower->attrib[attr][2] * invW;
+                  const GLfloat v0 = vLower->attrib[attr][3] * invW;
+                  sLeft[attr] = s0 + (span.attrStepX[attr][0] * adjx + span.attrStepY[attr][0] * adjy) * (1.0F/FIXED_SCALE);
+                  tLeft[attr] = t0 + (span.attrStepX[attr][1] * adjx + span.attrStepY[attr][1] * adjy) * (1.0F/FIXED_SCALE);
+                  uLeft[attr] = u0 + (span.attrStepX[attr][2] * adjx + span.attrStepY[attr][2] * adjy) * (1.0F/FIXED_SCALE);
+                  vLeft[attr] = v0 + (span.attrStepX[attr][3] * adjx + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
+                  dsOuter[attr] = span.attrStepY[attr][0] + dxOuter * span.attrStepX[attr][0];
+                  dtOuter[attr] = span.attrStepY[attr][1] + dxOuter * span.attrStepX[attr][1];
+                  duOuter[attr] = span.attrStepY[attr][2] + dxOuter * span.attrStepX[attr][2];
+                  dvOuter[attr] = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
                )
 #endif
             } /*if setupLeft*/
@@ -1134,16 +1071,11 @@
             dtInner = dtOuter + span.intTexStep[1];
 #endif
 #ifdef INTERP_TEX
-            TEX_UNIT_LOOP(
-               dsInner[u] = dsOuter[u] + span.attrStepX[attr][0];
-               dtInner[u] = dtOuter[u] + span.attrStepX[attr][1];
-               duInner[u] = duOuter[u] + span.attrStepX[attr][2];
-               dvInner[u] = dvOuter[u] + span.attrStepX[attr][3];
-            )
-#endif
-#ifdef INTERP_VARYING
-            VARYING_LOOP(
-               dvarInner[iv][ic] = dvarOuter[iv][ic] + span.attrStepX[attr][ic];
+            TEXVAR_LOOP(
+               dsInner[attr] = dsOuter[attr] + span.attrStepX[attr][0];
+               dtInner[attr] = dtOuter[attr] + span.attrStepX[attr][1];
+               duInner[attr] = duOuter[attr] + span.attrStepX[attr][2];
+               dvInner[attr] = dvOuter[attr] + span.attrStepX[attr][3];
             )
 #endif
 
@@ -1188,16 +1120,11 @@
 #endif
 
 #ifdef INTERP_TEX
-               TEX_UNIT_LOOP(
-                  span.attrStart[attr][0] = sLeft[u];
-                  span.attrStart[attr][1] = tLeft[u];
-                  span.attrStart[attr][2] = uLeft[u];
-                  span.attrStart[attr][3] = vLeft[u];
-               )
-#endif
-#ifdef INTERP_VARYING
-               VARYING_LOOP(
-                  span.attrStart[attr][ic] = varLeft[iv][ic];
+               TEXVAR_LOOP(
+                  span.attrStart[attr][0] = sLeft[attr];
+                  span.attrStart[attr][1] = tLeft[attr];
+                  span.attrStart[attr][2] = uLeft[attr];
+                  span.attrStart[attr][3] = vLeft[attr];
                )
 #endif
 
@@ -1281,16 +1208,11 @@
                   tLeft += dtOuter;
 #endif
 #ifdef INTERP_TEX
-                  TEX_UNIT_LOOP(
-                     sLeft[u] += dsOuter[u];
-                     tLeft[u] += dtOuter[u];
-                     uLeft[u] += duOuter[u];
-                     vLeft[u] += dvOuter[u];
-                  )
-#endif
-#ifdef INTERP_VARYING
-                  VARYING_LOOP(
-                     varLeft[iv][ic] += dvarOuter[iv][ic];
+                  TEXVAR_LOOP(
+                     sLeft[attr] += dsOuter[attr];
+                     tLeft[attr] += dtOuter[attr];
+                     uLeft[attr] += duOuter[attr];
+                     vLeft[attr] += dvOuter[attr];
                   )
 #endif
                }
@@ -1331,16 +1253,11 @@
                   tLeft += dtInner;
 #endif
 #ifdef INTERP_TEX
-                  TEX_UNIT_LOOP(
-                     sLeft[u] += dsInner[u];
-                     tLeft[u] += dtInner[u];
-                     uLeft[u] += duInner[u];
-                     vLeft[u] += dvInner[u];
-                  )
-#endif
-#ifdef INTERP_VARYING
-                  VARYING_LOOP(
-                     varLeft[iv][ic] += dvarInner[iv][ic];
+                  TEXVAR_LOOP(
+                     sLeft[attr] += dsInner[attr];
+                     tLeft[attr] += dtInner[attr];
+                     uLeft[attr] += duInner[attr];
+                     vLeft[attr] += dvInner[attr];
                   )
 #endif
                }
@@ -1373,8 +1290,6 @@
 #undef INTERP_INDEX
 #undef INTERP_INT_TEX
 #undef INTERP_TEX
-#undef INTERP_MULTITEX
-#undef INTERP_VARYING
 #undef TEX_UNIT_LOOP
 #undef VARYING_LOOP
 
diff --git a/src/mesa/swrast/swrast.h b/src/mesa/swrast/swrast.h
index 2c1c095..9e1fe24 100644
--- a/src/mesa/swrast/swrast.h
+++ b/src/mesa/swrast/swrast.h
@@ -67,13 +67,12 @@
     * that clip{XYZ} were multiplied by to get ndc{XYZ}.
     */
    GLfloat win[4];
-   GLfloat texcoord[MAX_TEXTURE_COORD_UNITS][4];
    GLchan color[4];
    GLchan specular[4];
    GLfloat fog;
    GLfloat index;
    GLfloat pointSize;
-   GLfloat varying[MAX_VERTEX_ATTRIBS][4];
+   GLfloat attrib[FRAG_ATTRIB_MAX][4]; /**< texcoords & varying, more to come */
 } SWvertex;
 
 
diff --git a/src/mesa/swrast_setup/ss_context.c b/src/mesa/swrast_setup/ss_context.c
index f17e69b..e1b60d0 100644
--- a/src/mesa/swrast_setup/ss_context.c
+++ b/src/mesa/swrast_setup/ss_context.c
@@ -145,7 +145,7 @@
       if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
          for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
             if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
-               EMIT_ATTR( _TNL_ATTRIB_TEX(i), EMIT_4F, texcoord[i] );
+               EMIT_ATTR( _TNL_ATTRIB_TEX(i), EMIT_4F, attrib[FRAG_ATTRIB_TEX0 + i] );
             }
          }
       }
@@ -156,7 +156,7 @@
          for (i = 0; i < ctx->Const.MaxVarying; i++) {
             if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_GENERIC(i) )) {
                EMIT_ATTR( _TNL_ATTRIB_GENERIC(i), VARYING_EMIT_STYLE,
-                          varying[i] );
+                          attrib[FRAG_ATTRIB_VAR0 + i] );
             }
          }
       }
@@ -242,8 +242,13 @@
 
 
    for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
-      _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_TEX0+i, dest->texcoord[i] );
-	  
+      _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_TEX0+i,
+                     dest->attrib[FRAG_ATTRIB_TEX0 + i] );
+
+   for (i = 0 ; i < ctx->Const.MaxVarying ; i++)
+      _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_GENERIC0+i,
+                     dest->attrib[FRAG_ATTRIB_VAR0 + i] );
+
    _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR0, tmp );
    UNCLAMPED_FLOAT_TO_RGBA_CHAN( dest->color, tmp );