New triangle rasterization code. Store per-span initial/step values in the
authorBrian Paul <brian.paul@tungstengraphics.com>
Mon, 14 May 2001 16:23:04 +0000 (16:23 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Mon, 14 May 2001 16:23:04 +0000 (16:23 +0000)
new triangle_span struct.  Much cleaner code and possibilities for future
optimizations.

src/mesa/drivers/osmesa/osmesa.c
src/mesa/drivers/x11/xm_tri.c
src/mesa/swrast/s_triangle.c
src/mesa/swrast/s_trispan.h [new file with mode: 0644]
src/mesa/swrast/s_tritemp.h

index 65ab67798cb716507ac6edc56a539efaaa1c0716..c046b18822f203f32fd6cc02cec2543bce3ac039 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: osmesa.c,v 1.54 2001/05/10 12:22:32 keithw Exp $ */
+/* $Id: osmesa.c,v 1.55 2001/05/14 16:23:04 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -55,6 +55,7 @@
 #include "swrast/s_depth.h"
 #include "swrast/s_lines.h"
 #include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
 #include "tnl/tnl.h"
 #include "tnl/t_context.h"
 #include "tnl/t_pipeline.h"
@@ -1600,21 +1601,24 @@ static void smooth_rgba_z_triangle( GLcontext *ctx,
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-{                                                              \
-   GLint i, len = RIGHT-LEFT;                                  \
-   GLchan *img = PIXELADDR4(LEFT, Y);                          \
-   for (i = 0; i < len; i++, img += 4) {                       \
-      GLdepth z = FixedToDepth(ffz);                           \
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLchan *img = PIXELADDR4(span.x, span.y);                   \
+   for (i = 0; i < span.count; i++, img += 4) {                        \
+      const GLdepth z = FixedToDepth(span.z);                  \
       if (z < zRow[i]) {                                       \
-         PACK_RGBA(img, FixedToInt(ffr), FixedToInt(ffg),      \
-                       FixedToInt(ffb), FixedToInt(ffa));      \
+         PACK_RGBA(img, FixedToInt(span.red),                  \
+            FixedToInt(span.green), FixedToInt(span.blue),     \
+            FixedToInt(span.alpha));                           \
          zRow[i] = z;                                          \
       }                                                                \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;  ffa += fdadx;\
-      ffz += fdzdx;                                            \
-   }                                                           \
-}
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.alpha += span.alphaStep;                            \
+      span.z += span.zStep;                                    \
+   }
+
 #ifdef WIN32
 #include "..\swrast\s_tritemp.h"
 #else
@@ -1641,19 +1645,18 @@ static void flat_rgba_z_triangle( GLcontext *ctx,
    PACK_RGBA((GLchan *) &pixel, v0->color[0], v0->color[1],    \
                                 v0->color[2], v0->color[3]);
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint i, len = RIGHT-LEFT;                          \
-   GLuint *img = (GLuint *) PIXELADDR4(LEFT, Y);       \
-   for (i=0;i<len;i++) {                               \
-      GLdepth z = FixedToDepth(ffz);                   \
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);        \
+   for (i = 0; i < span.count; i++) {                  \
+      const GLdepth z = FixedToDepth(span.z);          \
       if (z < zRow[i]) {                               \
          img[i] = pixel;                               \
          zRow[i] = z;                                  \
       }                                                        \
-      ffz += fdzdx;                                    \
-   }                                                   \
-}
+      span.z += span.zStep;                            \
+   }
+
 #ifdef WIN32
 #include "..\swrast\s_tritemp.h"
 #else
index a6a53461586eef71004545b8e253ac8d77a55476..e017ed523fbade4cb59d1c86f6695571ea76fa95 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: xm_tri.c,v 1.19 2001/03/08 17:33:33 brianp Exp $ */
+/* $Id: xm_tri.c,v 1.20 2001/05/14 16:23:04 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -44,7 +44,7 @@
 #include "swrast/s_context.h"
 #include "swrast/s_depth.h"
 #include "swrast/s_triangle.h"
-
+#include "swrast/s_trispan.h"
 
 
 
@@ -66,22 +66,25 @@ static void smooth_TRUECOLOR_z_triangle( GLcontext *ctx,
 #define INTERP_Z 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 #define INTERP_RGB 1
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer, Y);                 \
-   GLint len = RIGHT-LEFT;                                             \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         unsigned long p;                                              \
-         PACK_TRUECOLOR(p, FixedToInt(ffr), FixedToInt(ffg), FixedToInt(ffb));\
-         XMesaPutPixel( img, xx, yy, p );                              \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p;                                      \
+         PACK_TRUECOLOR(p, FixedToInt(span.red),               \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         XMesaPutPixel(img, x, y, p);                          \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -102,20 +105,22 @@ static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLuint
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, len = RIGHT-LEFT;                                          \
-   for (i=0;i<len;i++) {                                               \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),      \
-                                FixedToInt(ffb) );                     \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = PACK_8B8G8R(FixedToInt(span.red),           \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -135,20 +140,22 @@ static void smooth_8R8G8B_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLuint
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, len = RIGHT-LEFT;                                          \
-   for (i=0;i<len;i++) {                                               \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),      \
-                                FixedToInt(ffb) );                     \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = PACK_8R8G8B(FixedToInt(span.red),           \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -168,22 +175,24 @@ static void smooth_8R8G8B24_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE bgr_t
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, len = RIGHT-LEFT;                                          \
-   for (i=0;i<len;i++) {                                               \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-        PIXEL_TYPE *ptr = pRow + i;                                    \
-         ptr->r = FixedToInt(ffr);                                     \
-         ptr->g = FixedToInt(ffg);                                     \
-         ptr->b = FixedToInt(ffb);                                     \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+        PIXEL_TYPE *ptr = pRow + i;                            \
+         ptr->r = FixedToInt(span.red);                                \
+         ptr->g = FixedToInt(span.green);                      \
+         ptr->b = FixedToInt(span.blue);                       \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -201,22 +210,25 @@ static void smooth_TRUEDITHER_z_triangle( GLcontext *ctx,
 #define INTERP_Z 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 #define INTERP_RGB 1
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         unsigned long p;                                              \
-         PACK_TRUEDITHER( p, xx, yy, FixedToInt(ffr),                  \
-                          FixedToInt(ffg), FixedToInt(ffb) );          \
-         XMesaPutPixel( img, xx, yy, p );                              \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p;                                      \
+         PACK_TRUEDITHER(p, x, y, FixedToInt(span.red),                \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         XMesaPutPixel(img, x, y, p);                          \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -236,20 +248,22 @@ static void smooth_5R6G5B_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLushort
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, len = RIGHT-LEFT;                                          \
-   for (i=0;i<len;i++) {                                               \
-      DEPTH_TYPE z = FixedToDepth(ffz);                                        \
-      if (z < zRow[i]) {                                               \
-         pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg),      \
-                                FixedToInt(ffb) );                     \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = PACK_5R6G5B(FixedToInt(span.red),           \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -269,21 +283,23 @@ static void smooth_DITHER_5R6G5B_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLushort
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, len = RIGHT-LEFT;                                          \
-   GLint yy = FLIP(xmesa->xm_buffer, Y);                               \
-   for (i=0;i<len;i++) {                                               \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         PACK_TRUEDITHER(pRow[i], LEFT+i, yy, FixedToInt(ffr),         \
-                        FixedToInt(ffg), FixedToInt(ffb) );            \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red),  \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -303,21 +319,24 @@ static void smooth_DITHER8_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLubyte
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   XDITHER_SETUP(yy);                                                  \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         pRow[i] = (PIXEL_TYPE) XDITHER( xx, FixedToInt(ffr),          \
-                       FixedToInt(ffg), FixedToInt(ffb) );             \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red),\
+            FixedToInt(span.green), FixedToInt(span.blue) );   \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -335,25 +354,25 @@ static void smooth_DITHER_z_triangle( GLcontext *ctx,
 #define INTERP_Z 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 #define INTERP_RGB 1
-#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
-#define PIXEL_TYPE GLubyte
-#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   XDITHER_SETUP(yy);                                                  \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-        unsigned long p = XDITHER( xx, FixedToInt(ffr),                \
-                                FixedToInt(ffg), FixedToInt(ffb) );    \
-        XMesaPutPixel( img, xx, yy, p );                               \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p = XDITHER(x, FixedToInt(span.red),    \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+        XMesaPutPixel(img, x, y, p);                           \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -373,21 +392,23 @@ static void smooth_LOOKUP8_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLubyte
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, len = RIGHT-LEFT;                                          \
-   LOOKUP_SETUP;                                                       \
-   for (i=0;i<len;i++) {                                               \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         pRow[i] = LOOKUP( FixedToInt(ffr), FixedToInt(ffg),           \
-                                FixedToInt(ffb) );                     \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   LOOKUP_SETUP;                                               \
+   for (i = 0; i < span.count; i++) {                          \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = LOOKUP(FixedToInt(span.red),                        \
+            FixedToInt(span.green), FixedToInt(span.blue));    \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -408,20 +429,23 @@ static void smooth_HPCR_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLubyte
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         pRow[i] = DITHER_HPCR( xx, yy, FixedToInt(ffr),               \
-                                FixedToInt(ffg), FixedToInt(ffb) );    \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red),     \
+            FixedToInt(span.green), FixedToInt(span.blue) );   \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -442,18 +466,18 @@ static void flat_TRUECOLOR_z_triangle( GLcontext *ctx,
    unsigned long pixel;                                                \
    PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]);
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         XMesaPutPixel( img, xx, yy, pixel );                          \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         XMesaPutPixel(img, x, y, pixel);                      \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -475,18 +499,17 @@ static void flat_8A8B8G8R_z_triangle( GLcontext *ctx,
 #define SETUP_CODE                                     \
    unsigned long p = PACK_8B8G8R( v2->color[0],        \
                 v2->color[1], v2->color[2] );
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, len = RIGHT-LEFT;                                          \
-   for (i=0;i<len;i++) {                                               \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-        pRow[i] = (PIXEL_TYPE) p;                                      \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.count; i++) {                  \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
+      if (z < zRow[i]) {                               \
+        pRow[i] = (PIXEL_TYPE) p;                      \
+         zRow[i] = z;                                  \
+      }                                                        \
+      span.z += span.zStep;                            \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -505,21 +528,20 @@ static void flat_8R8G8B_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLuint
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define SETUP_CODE                                     \
+#define SETUP_CODE                             \
    unsigned long p = PACK_8R8G8B( v2->color[0],        \
                 v2->color[1], v2->color[2] );
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint i, len = RIGHT-LEFT;                          \
-   for (i=0;i<len;i++) {                               \
-      GLdepth z = FixedToDepth(ffz);                   \
-      if (z < zRow[i]) {                               \
-        pRow[i] = (PIXEL_TYPE) p;                      \
-         zRow[i] = z;                                  \
-      }                                                        \
-      ffz += fdzdx;                                    \
-   }                                                   \
-}
+#define RENDER_SPAN( span )                    \
+   GLuint i;                                   \
+   for (i = 0; i < span.count; i++) {          \
+      DEPTH_TYPE z = FixedToDepth(span.z);     \
+      if (z < zRow[i]) {                       \
+        pRow[i] = (PIXEL_TYPE) p;              \
+         zRow[i] = z;                          \
+      }                                                \
+      span.z += span.zStep;                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -539,21 +561,20 @@ static void flat_8R8G8B24_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE bgr_t
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint i, len = RIGHT-LEFT;                          \
-   for (i=0;i<len;i++) {                               \
-      GLdepth z = FixedToDepth(ffz);                   \
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.count; i++) {                  \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
       if (z < zRow[i]) {                               \
-        PIXEL_TYPE *ptr = pRow+i;                      \
+        PIXEL_TYPE *ptr = pRow + i;                    \
          ptr->r = color[RCOMP];                                \
          ptr->g = color[GCOMP];                                \
          ptr->b = color[BCOMP];                                \
          zRow[i] = z;                                  \
       }                                                        \
-      ffz += fdzdx;                                    \
-   }                                                   \
-}
+      span.z += span.zStep;                            \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -570,21 +591,21 @@ static void flat_TRUEDITHER_z_triangle( GLcontext *ctx,
    XMesaImage *img = xmesa->xm_buffer->backimage;
 #define INTERP_Z 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         unsigned long p;                                              \
-         PACK_TRUEDITHER( p, xx, yy, v2->color[0],             \
-            v2->color[1], v2->color[2] );      \
-         XMesaPutPixel( img, xx, yy, p );                              \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p;                                      \
+         PACK_TRUEDITHER(p, x, y, v2->color[0],                        \
+            v2->color[1], v2->color[2]);                       \
+         XMesaPutPixel(img, x, y, p);                          \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -603,21 +624,20 @@ static void flat_5R6G5B_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLushort
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define SETUP_CODE                                                     \
+#define SETUP_CODE                                     \
    unsigned long p = PACK_5R6G5B( v2->color[0],                \
             v2->color[1], v2->color[2] );
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint i, len = RIGHT-LEFT;                          \
-   for (i=0;i<len;i++) {                               \
-      DEPTH_TYPE z = FixedToDepth(ffz);                        \
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.count; i++) {                  \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
       if (z < zRow[i]) {                               \
         pRow[i] = (PIXEL_TYPE) p;                      \
          zRow[i] = z;                                  \
       }                                                        \
-      ffz += fdzdx;                                    \
-   }                                                   \
-}
+      span.z += span.zStep;                            \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -637,20 +657,19 @@ static void flat_DITHER_5R6G5B_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLushort
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-{                                                              \
-   GLint i, len = RIGHT-LEFT;                                  \
-   GLint yy = FLIP(xmesa->xm_buffer, Y);                       \
-   for (i=0;i<len;i++) {                                       \
-      DEPTH_TYPE z = FixedToDepth(ffz);                                \
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
       if (z < zRow[i]) {                                       \
-        PACK_TRUEDITHER(pRow[i], LEFT+i, yy, color[RCOMP],     \
+        PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP],           \
                         color[GCOMP], color[BCOMP]);           \
          zRow[i] = z;                                          \
       }                                                                \
-      ffz += fdzdx;                                            \
-   }                                                           \
-}
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -672,19 +691,19 @@ static void flat_DITHER8_z_triangle( GLcontext *ctx,
 #define SETUP_CODE     \
    FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, yy));                  \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-        pRow[i] = (PIXEL_TYPE) FLAT_DITHER(xx);                        \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, y));           \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+        pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x);                 \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -704,20 +723,20 @@ static void flat_DITHER_z_triangle( GLcontext *ctx,
 #define SETUP_CODE     \
    FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   FLAT_DITHER_ROW_SETUP(yy);                                          \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-         unsigned long p = FLAT_DITHER(xx);                            \
-        XMesaPutPixel( img, xx, yy, p );                               \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   FLAT_DITHER_ROW_SETUP(y);                                   \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+         unsigned long p = FLAT_DITHER(x);                     \
+        XMesaPutPixel(img, x, y, p);                           \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -736,22 +755,22 @@ static void flat_HPCR_z_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLubyte
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define SETUP_CODE                             \
+#define SETUP_CODE             \
    GLubyte r = v2->color[0];   \
    GLubyte g = v2->color[1];   \
    GLubyte b = v2->color[2];
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint i, xx = LEFT, yy = FLIP(xmesa->xm_buffer,Y), len = RIGHT-LEFT;        \
-   for (i=0;i<len;i++,xx++) {                                          \
-      GLdepth z = FixedToDepth(ffz);                                   \
-      if (z < zRow[i]) {                                               \
-        pRow[i] = (PIXEL_TYPE) DITHER_HPCR( xx, yy, r, g, b );         \
-         zRow[i] = z;                                                  \
-      }                                                                        \
-      ffz += fdzdx;                                                    \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      const DEPTH_TYPE z = FixedToDepth(span.z);               \
+      if (z < zRow[i]) {                                       \
+        pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b);     \
+         zRow[i] = z;                                          \
+      }                                                                \
+      span.z += span.zStep;                                    \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -776,18 +795,17 @@ static void flat_LOOKUP8_z_triangle( GLcontext *ctx,
    GLubyte g = v2->color[1];   \
    GLubyte b = v2->color[2];   \
    GLubyte p = LOOKUP(r,g,b);
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint i, len = RIGHT-LEFT;                          \
-   for (i=0;i<len;i++) {                               \
-      GLdepth z = FixedToDepth(ffz);                   \
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.count; i++) {                  \
+      const DEPTH_TYPE z = FixedToDepth(span.z);       \
       if (z < zRow[i]) {                               \
         pRow[i] = p;                                   \
          zRow[i] = z;                                  \
       }                                                        \
-      ffz += fdzdx;                                    \
-   }                                                   \
-}
+      span.z += span.zStep;                            \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -804,16 +822,19 @@ static void smooth_TRUECOLOR_triangle( GLcontext *ctx,
    XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
    XMesaImage *img = xmesa->xm_buffer->backimage;
 #define INTERP_RGB 1
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                           \
-   for (xx=LEFT;xx<RIGHT;xx++) {                                       \
-      unsigned long p;                                                 \
-      PACK_TRUECOLOR(p, FixedToInt(ffr), FixedToInt(ffg), FixedToInt(ffb));\
-      XMesaPutPixel( img, xx, yy, p );                                 \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      unsigned long p;                                         \
+      PACK_TRUECOLOR(p, FixedToInt(span.red),                  \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      XMesaPutPixel(img, x, y, p);                             \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -831,16 +852,16 @@ static void smooth_8A8B8G8R_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLuint
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx;                                                           \
-   PIXEL_TYPE *pixel = pRow;                                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \
-      *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg),          \
-                               FixedToInt(ffb) );                      \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      pRow[i] = PACK_8B8G8R(FixedToInt(span.red),              \
+         FixedToInt(span.green), FixedToInt(span.blue) );      \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }                                                           \
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -858,16 +879,16 @@ static void smooth_8R8G8B_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLuint
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx;                                                           \
-   PIXEL_TYPE *pixel = pRow;                                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \
-      *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg),          \
-                               FixedToInt(ffb) );                      \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      pRow[i] = PACK_8R8G8B(FixedToInt(span.red),              \
+         FixedToInt(span.green), FixedToInt(span.blue) );      \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -885,18 +906,18 @@ static void smooth_8R8G8B24_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE bgr_t
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-{                                                              \
-   GLint xx;                                                   \
-   PIXEL_TYPE *pixel = pRow;                                   \
-   for (xx=LEFT;xx<RIGHT;xx++) {                               \
-      pixel->r = FixedToInt(ffr);                              \
-      pixel->g = FixedToInt(ffg);                              \
-      pixel->b = FixedToInt(ffb);                              \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;              \
-      pixel++;                                                 \
-   }                                                           \
-}
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   PIXEL_TYPE *pixel = pRow;                           \
+   for (i = 0; i < span.count; i++, pixel++) {         \
+      pixel->r = FixedToInt(span.red);                 \
+      pixel->g = FixedToInt(span.green);               \
+      pixel->b = FixedToInt(span.blue);                        \
+      span.red += span.redStep;                                \
+      span.green += span.greenStep;                    \
+      span.blue += span.blueStep;                      \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -912,17 +933,19 @@ static void smooth_TRUEDITHER_triangle( GLcontext *ctx,
    XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
    XMesaImage *img = xmesa->xm_buffer->backimage;
 #define INTERP_RGB 1
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                           \
-   for (xx=LEFT;xx<RIGHT;xx++) {                                       \
-      unsigned long p;                                                 \
-      PACK_TRUEDITHER( p, xx, yy, FixedToInt(ffr), FixedToInt(ffg),    \
-                               FixedToInt(ffb) );                      \
-      XMesaPutPixel( img, xx, yy, p );                                 \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      unsigned long p;                                         \
+      PACK_TRUEDITHER(p, x, y, FixedToInt(span.red),           \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      XMesaPutPixel(img, x, y, p );                            \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -940,16 +963,16 @@ static void smooth_5R6G5B_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLushort
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx;                                                           \
-   PIXEL_TYPE *pixel = pRow;                                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \
-      *pixel = (PIXEL_TYPE) PACK_5R6G5B( FixedToInt(ffr),              \
-                                FixedToInt(ffg), FixedToInt(ffb) );    \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      pRow[i] = (PIXEL_TYPE) PACK_5R6G5B(FixedToInt(span.red), \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -967,16 +990,17 @@ static void smooth_DITHER_5R6G5B_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLushort
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                           \
-   PIXEL_TYPE *pixel = pRow;                                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \
-      PACK_TRUEDITHER(*pixel, xx, yy, FixedToInt(ffr),                 \
-                                FixedToInt(ffg), FixedToInt(ffb) );    \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red),     \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -994,17 +1018,18 @@ static void smooth_DITHER8_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLubyte
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                           \
-   PIXEL_TYPE *pixel = pRow;                                           \
-   XDITHER_SETUP(yy);                                                  \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \
-      *pixel = (PIXEL_TYPE) XDITHER( xx, FixedToInt(ffr),              \
-                                FixedToInt(ffg), FixedToInt(ffb) );    \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red),  \
+         FixedToInt(span.green), FixedToInt(span.blue) );      \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1021,17 +1046,19 @@ static void smooth_DITHER_triangle( GLcontext *ctx,
    XMesaImage *img = xmesa->xm_buffer->backimage;
 
 #define INTERP_RGB 1
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                           \
-   XDITHER_SETUP(yy);                                                  \
-   for (xx=LEFT;xx<RIGHT;xx++) {                                       \
-      unsigned long p = XDITHER( xx, FixedToInt(ffr),                  \
-                               FixedToInt(ffg), FixedToInt(ffb) );     \
-      XMesaPutPixel( img, xx, yy, p );                                 \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   XDITHER_SETUP(y);                                           \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      unsigned long p = XDITHER(x, FixedToInt(span.red),       \
+         FixedToInt(span.green), FixedToInt(span.blue) );      \
+      XMesaPutPixel(img, x, y, p);                             \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1050,17 +1077,17 @@ static void smooth_LOOKUP8_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLubyte
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx;                                                           \
-   PIXEL_TYPE *pixel = pRow;                                           \
-   LOOKUP_SETUP;                                                       \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \
-      *pixel = LOOKUP( FixedToInt(ffr), FixedToInt(ffg),               \
-                       FixedToInt(ffb) );                              \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   LOOKUP_SETUP;                                       \
+   for (i = 0; i < span.count; i++) {                  \
+      pRow[i] = LOOKUP(FixedToInt(span.red),           \
+         FixedToInt(span.green), FixedToInt(span.blue));\
+      span.red += span.redStep;                                \
+      span.green += span.greenStep;                    \
+      span.blue += span.blueStep;                      \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1080,16 +1107,17 @@ static void smooth_HPCR_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLubyte
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                           \
-   PIXEL_TYPE *pixel = pRow;                                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                               \
-      *pixel = DITHER_HPCR( xx, yy, FixedToInt(ffr),                   \
-                               FixedToInt(ffg), FixedToInt(ffb) );     \
-      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;                      \
-   }                                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red),                \
+         FixedToInt(span.green), FixedToInt(span.blue));       \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1108,13 +1136,13 @@ static void flat_TRUECOLOR_triangle( GLcontext *ctx,
    unsigned long pixel;                                                \
    PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]);
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-{                                                              \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                   \
-   for (xx=LEFT;xx<RIGHT;xx++) {                               \
-      XMesaPutPixel( img, xx, yy, pixel );                     \
-   }                                                           \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      XMesaPutPixel(img, x, y, pixel);                         \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1132,16 +1160,14 @@ static void flat_8A8B8G8R_triangle( GLcontext *ctx,
 #define PIXEL_TYPE GLuint
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
 #define SETUP_CODE                                     \
-   unsigned long p = PACK_8B8G8R( v2->color[0],        \
+   unsigned long p = PACK_8B8G8R( v2->color[0],                \
                 v2->color[1], v2->color[2] );
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint xx;                                           \
-   PIXEL_TYPE *pixel = pRow;                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \
-      *pixel = (PIXEL_TYPE) p;                         \
-   }                                                   \
-}
+#define RENDER_SPAN( span )                    \
+   GLuint i;                                   \
+   for (i = 0; i < span.count; i++) {          \
+      pRow[i] = (PIXEL_TYPE) p;                        \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1158,17 +1184,15 @@ static void flat_8R8G8B_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLuint
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define SETUP_CODE                                     \
+#define SETUP_CODE                             \
    unsigned long p = PACK_8R8G8B( v2->color[0],        \
                 v2->color[1], v2->color[2] );
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint xx;                                           \
-   PIXEL_TYPE *pixel = pRow;                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \
-      *pixel = (PIXEL_TYPE) p;                         \
-   }                                                   \
-}
+#define RENDER_SPAN( span )                    \
+   GLuint i;                                   \
+   for (i = 0; i < span.count; i++) {          \
+      pRow[i] = (PIXEL_TYPE) p;                        \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1186,17 +1210,15 @@ static void flat_8R8G8B24_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE bgr_t
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint xx;                                           \
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
    PIXEL_TYPE *pixel = pRow;                           \
-   for (xx=LEFT;xx<RIGHT;xx++) {                       \
+   for (i = 0; i < span.count; i++, pixel++) {         \
       pixel->r = color[RCOMP];                         \
       pixel->g = color[GCOMP];                         \
       pixel->b = color[BCOMP];                         \
-      pixel++;                                         \
-   }                                                   \
-}
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1210,16 +1232,17 @@ static void flat_TRUEDITHER_triangle( GLcontext *ctx,
 {
    XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
    XMesaImage *img = xmesa->xm_buffer->backimage;
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-{                                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                           \
-   for (xx=LEFT;xx<RIGHT;xx++) {                                       \
-      unsigned long p;                                                 \
-      PACK_TRUEDITHER( p, xx, yy, v2->color[0],                \
-               v2->color[1], v2->color[2] );   \
-      XMesaPutPixel( img, xx, yy, p );                                 \
-   }                                                                   \
-}
+
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      unsigned long p;                                         \
+      PACK_TRUEDITHER(p, x, y, v2->color[0],                   \
+               v2->color[1], v2->color[2] );                   \
+      XMesaPutPixel(img, x, y, p);                             \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1240,14 +1263,12 @@ static void flat_5R6G5B_triangle( GLcontext *ctx,
 #define SETUP_CODE                                     \
    unsigned long p = PACK_5R6G5B( v2->color[0],        \
                 v2->color[1], v2->color[2] );
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint xx;                                           \
-   PIXEL_TYPE *pixel = pRow;                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \
-      *pixel = (PIXEL_TYPE) p;                         \
-   }                                                   \
-}
+#define RENDER_SPAN( span )                    \
+   GLuint i;                                   \
+   for (i = 0; i < span.count; i++) {          \
+      pRow[i] = (PIXEL_TYPE) p;                        \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1265,15 +1286,14 @@ static void flat_DITHER_5R6G5B_triangle( GLcontext *ctx,
 #define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
 #define PIXEL_TYPE GLushort
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);           \
-   PIXEL_TYPE *pixel = pRow;                           \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \
-      PACK_TRUEDITHER(*pixel, xx, yy, color[RCOMP],    \
-                     color[GCOMP], color[BCOMP]);      \
-   }                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP],             \
+         color[GCOMP], color[BCOMP]);                          \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1293,15 +1313,14 @@ static void flat_DITHER8_triangle( GLcontext *ctx,
 #define SETUP_CODE     \
    FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint xx;                                           \
-   PIXEL_TYPE *pixel = pRow;                           \
-   FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, Y));   \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {               \
-      *pixel = (PIXEL_TYPE) FLAT_DITHER(xx);           \
-   }                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, y));           \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x);                   \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1319,15 +1338,15 @@ static void flat_DITHER_triangle( GLcontext *ctx,
 #define SETUP_CODE     \
    FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                   \
-{                                                      \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);           \
-   FLAT_DITHER_ROW_SETUP(yy);                          \
-   for (xx=LEFT;xx<RIGHT;xx++) {                       \
-      unsigned long p = FLAT_DITHER(xx);               \
-      XMesaPutPixel( img, xx, yy, p );                 \
-   }                                                   \
-}
+#define RENDER_SPAN( span )                                    \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   FLAT_DITHER_ROW_SETUP(y);                                   \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      unsigned long p = FLAT_DITHER(x);                                \
+      XMesaPutPixel(img, x, y, p );                            \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1348,14 +1367,13 @@ static void flat_HPCR_triangle( GLcontext *ctx,
    GLubyte r = v2->color[0];   \
    GLubyte g = v2->color[1];   \
    GLubyte b = v2->color[2];
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-{                                                              \
-   GLint xx, yy = FLIP(xmesa->xm_buffer, Y);                   \
-   PIXEL_TYPE *pixel = pRow;                                   \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {                       \
-      *pixel = (PIXEL_TYPE) DITHER_HPCR( xx, yy, r, g, b );    \
-   }                                                           \
-}
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                                   \
+   GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y);       \
+   for (i = 0; i < span.count; i++, x++) {                     \
+      pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b);       \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
@@ -1374,18 +1392,16 @@ static void flat_LOOKUP8_triangle( GLcontext *ctx,
 #define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
 #define SETUP_CODE                             \
    LOOKUP_SETUP;                               \
-   GLubyte r = v2->color[0];           \
-   GLubyte g = v2->color[1];           \
-   GLubyte b = v2->color[2];           \
+   GLubyte r = v2->color[0];                   \
+   GLubyte g = v2->color[1];                   \
+   GLubyte b = v2->color[2];                   \
    GLubyte p = LOOKUP(r,g,b);
-#define INNER_LOOP( LEFT, RIGHT, Y )           \
-{                                              \
-   GLint xx;                                   \
-   PIXEL_TYPE *pixel = pRow;                   \
-   for (xx=LEFT;xx<RIGHT;xx++,pixel++) {       \
-      *pixel = p;                              \
-   }                                           \
-}
+#define RENDER_SPAN( span )                    \
+   GLuint i;                                   \
+   for (i = 0; i < span.count; i++) {          \
+      pRow[i] = (PIXEL_TYPE) p;                        \
+   }
+
 #include "swrast/s_tritemp.h"
 }
 
index 82c690502bff8e539016179136e2607f06b9c4cb..29805a537a65e73a7e035b1b12029fd79ff207a4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_triangle.c,v 1.25 2001/05/03 22:13:32 brianp Exp $ */
+/* $Id: s_triangle.c,v 1.26 2001/05/14 16:23:04 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -47,6 +47,9 @@
 #include "s_feedback.h"
 #include "s_span.h"
 #include "s_triangle.h"
+#include "s_trispan.h"
+
+
 
 GLboolean _mesa_cull_triangle( GLcontext *ctx,
                            const SWvertex *v0,
@@ -78,23 +81,18 @@ static void flat_ci_triangle( GLcontext *ctx,
 #define INTERP_Z 1
 #define INTERP_FOG 1
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          const GLint n = RIGHT-LEFT;                          \
-          GLint i;                                             \
-          GLdepth zspan[MAX_WIDTH];                            \
-          GLfloat fogspan[MAX_WIDTH];                          \
-          if (n>0) {                                           \
-             for (i=0;i<n;i++) {                               \
-                zspan[i] = FixedToDepth(ffz);                  \
-                ffz += fdzdx;                                  \
-                fogspan[i] = ffog;                             \
-                 ffog += dfogdx;                               \
-             }                                                 \
-             _mesa_write_monoindex_span( ctx, n, LEFT, Y, zspan,       \
-                         fogspan, v0->index, GL_POLYGON );     \
-          }                                                    \
-       }
+#define RENDER_SPAN( span )                                            \
+   GLdepth zSpan[MAX_WIDTH];                                           \
+   GLfloat fogSpan[MAX_WIDTH];                                         \
+   GLuint i;                                                           \
+   for (i = 0; i < span.count; i++) {                                  \
+      zSpan[i] = FixedToDepth(span.z);                                 \
+      span.z += span.zStep;                                            \
+      fogSpan[i] = span.fog;                                           \
+      span.fog += span.fogStep;                                                \
+   }                                                                   \
+   _mesa_write_monoindex_span(ctx, span.count, span.x, span.y,         \
+                             zSpan, fogSpan, v0->index, GL_POLYGON );
 
 #include "s_tritemp.h"
 }
@@ -113,26 +111,21 @@ static void smooth_ci_triangle( GLcontext *ctx,
 #define INTERP_FOG 1
 #define INTERP_INDEX 1
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          const GLint n = RIGHT-LEFT;                          \
-          GLint i;                                             \
-          GLdepth zspan[MAX_WIDTH];                            \
-           GLfloat fogspan[MAX_WIDTH];                         \
-           GLuint index[MAX_WIDTH];                            \
-          if (n>0) {                                           \
-             for (i=0;i<n;i++) {                               \
-                zspan[i] = FixedToDepth(ffz);                  \
-                ffz += fdzdx;                                  \
-                 index[i] = FixedToInt(ffi);                   \
-                ffi += fdidx;                                  \
-                fogspan[i] = ffog;                             \
-                ffog += dfogdx;                                \
-             }                                                 \
-             _mesa_write_index_span( ctx, n, LEFT, Y, zspan, fogspan,  \
-                                  index, GL_POLYGON );         \
-          }                                                    \
-       }
+#define RENDER_SPAN( span )                                            \
+   GLdepth zSpan[MAX_WIDTH];                                           \
+   GLfloat fogSpan[MAX_WIDTH];                                         \
+   GLuint indexSpan[MAX_WIDTH];                                                \
+   GLuint i;                                                           \
+   for (i = 0; i < span.count; i++) {                                  \
+      zSpan[i] = FixedToDepth(span.z);                                 \
+      span.z += span.zStep;                                            \
+      indexSpan[i] = FixedToInt(span.index);                           \
+      span.index += span.indexStep;                                    \
+      fogSpan[i] = span.fog;                                           \
+      span.fog += span.fogStep;                                                \
+   }                                                                   \
+   _mesa_write_index_span(ctx, span.count, span.x, span.y,             \
+                          zSpan, fogSpan, indexSpan, GL_POLYGON);
 
 #include "s_tritemp.h"
 }
@@ -151,24 +144,18 @@ static void flat_rgba_triangle( GLcontext *ctx,
 #define INTERP_FOG 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          const GLint n = RIGHT-LEFT;                          \
-          GLint i;                                             \
-          GLdepth zspan[MAX_WIDTH];                            \
-          GLfloat fogspan[MAX_WIDTH];                          \
-          if (n>0) {                                           \
-             for (i=0;i<n;i++) {                               \
-                zspan[i] = FixedToDepth(ffz);                  \
-                ffz += fdzdx;                                  \
-                fogspan[i] = ffog;                             \
-                ffog += dfogdx;                                \
-             }                                                 \
-              _mesa_write_monocolor_span( ctx, n, LEFT, Y, zspan,      \
-                                       fogspan, v2->color,     \
-                                      GL_POLYGON );            \
-          }                                                    \
-       }
+#define RENDER_SPAN( span )                                            \
+   GLdepth zSpan[MAX_WIDTH];                                           \
+   GLfloat fogSpan[MAX_WIDTH];                                         \
+   GLuint i;                                                           \
+   for (i = 0; i < span.count; i++) {                                  \
+      zSpan[i] = FixedToDepth(span.z);                                 \
+      span.z += span.zStep;                                            \
+      fogSpan[i] = span.fog;                                           \
+      span.fog += span.fogStep;                                                \
+   }                                                                   \
+   _mesa_write_monocolor_span(ctx, span.count, span.x, span.y,         \
+                              zSpan, fogSpan, v2->color, GL_POLYGON );
 
 #include "s_tritemp.h"
 
@@ -193,34 +180,28 @@ static void smooth_rgba_triangle( GLcontext *ctx,
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          const GLint n = RIGHT-LEFT;                          \
-          GLint i;                                             \
-          GLdepth zspan[MAX_WIDTH];                            \
-          GLchan rgba[MAX_WIDTH][4];                           \
-          GLfloat fogspan[MAX_WIDTH];                          \
-          if (n>0) {                                           \
-             for (i=0;i<n;i++) {                               \
-                zspan[i] = FixedToDepth(ffz);                  \
-                rgba[i][RCOMP] = FixedToInt(ffr);              \
-                rgba[i][GCOMP] = FixedToInt(ffg);              \
-                rgba[i][BCOMP] = FixedToInt(ffb);              \
-                rgba[i][ACOMP] = FixedToInt(ffa);              \
-                fogspan[i] = ffog;;                            \
-                ffz += fdzdx;                                  \
-                ffr += fdrdx;                                  \
-                ffg += fdgdx;                                  \
-                ffb += fdbdx;                                  \
-                ffa += fdadx;                                  \
-                ffog += dfogdx;                                \
-             }                                                 \
-             _mesa_write_rgba_span( ctx, n, LEFT, Y,           \
-                                  (CONST GLdepth *) zspan,     \
-                                  fogspan,                      \
-                                 rgba, GL_POLYGON );           \
-          }                                                    \
-       }
+#define RENDER_SPAN( span )                                    \
+   GLdepth zSpan[MAX_WIDTH];                                   \
+   GLchan rgbaSpan[MAX_WIDTH][4];                              \
+   GLfloat fogSpan[MAX_WIDTH];                                 \
+   GLuint i;                                                   \
+   for (i = 0; i < span.count; i++) {                          \
+      rgbaSpan[i][RCOMP] = FixedToInt(span.red);               \
+      rgbaSpan[i][GCOMP] = FixedToInt(span.green);             \
+      rgbaSpan[i][BCOMP] = FixedToInt(span.blue);              \
+      rgbaSpan[i][ACOMP] = FixedToInt(span.alpha);             \
+      span.red += span.redStep;                                        \
+      span.green += span.greenStep;                            \
+      span.blue += span.blueStep;                              \
+      span.alpha += span.alphaStep;                            \
+      zSpan[i] = FixedToDepth(span.z);                         \
+      span.z += span.zStep;                                    \
+      fogSpan[i] = span.fog;                                   \
+      span.fog += span.fogStep;                                        \
+   }                                                           \
+   _mesa_write_rgba_span(ctx, span.count, span.x, span.y,      \
+                         (CONST GLdepth *) zSpan,              \
+                         fogSpan, rgbaSpan, GL_POLYGON);
 
 #include "s_tritemp.h"
 
@@ -243,44 +224,40 @@ static void simple_textured_triangle( GLcontext *ctx,
 #define INTERP_INT_TEX 1
 #define S_SCALE twidth
 #define T_SCALE theight
+
 #define SETUP_CODE                                                     \
    SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
    struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;     \
    GLint b = obj->BaseLevel;                                           \
-   GLfloat twidth = (GLfloat) obj->Image[b]->Width;                    \
-   GLfloat theight = (GLfloat) obj->Image[b]->Height;                  \
-   GLint twidth_log2 = obj->Image[b]->WidthLog2;                       \
+   const GLfloat twidth = (GLfloat) obj->Image[b]->Width;              \
+   const GLfloat theight = (GLfloat) obj->Image[b]->Height;            \
+   const GLint twidth_log2 = obj->Image[b]->WidthLog2;                 \
    const GLchan *texture = (const GLchan *) obj->Image[b]->Data;       \
-   GLint smask = obj->Image[b]->Width - 1;                             \
-   GLint tmask = obj->Image[b]->Height - 1;                            \
+   const GLint smask = obj->Image[b]->Width - 1;                       \
+   const GLint tmask = obj->Image[b]->Height - 1;                      \
    if (!texture) {                                                     \
       /* this shouldn't happen */                                      \
       return;                                                          \
    }
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          CONST GLint n = RIGHT-LEFT;                          \
-          GLint i;                                             \
-          GLchan rgb[MAX_WIDTH][3];                            \
-          if (n>0) {                                           \
-              ffs -= FIXED_HALF; /* off-by-one error? */        \
-              fft -= FIXED_HALF;                                \
-             for (i=0;i<n;i++) {                               \
-                 GLint s = FixedToInt(ffs) & smask;            \
-                 GLint t = FixedToInt(fft) & tmask;            \
-                 GLint pos = (t << twidth_log2) + s;           \
-                 pos = pos + pos + pos;  /* multiply by 3 */   \
-                 rgb[i][RCOMP] = texture[pos];                 \
-                 rgb[i][GCOMP] = texture[pos+1];               \
-                 rgb[i][BCOMP] = texture[pos+2];               \
-                ffs += fdsdx;                                  \
-                fft += fdtdx;                                  \
-             }                                                 \
-              (*swrast->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
-                           (CONST GLchan (*)[3]) rgb, NULL );  \
-          }                                                    \
-       }
+#define RENDER_SPAN( span  )                                           \
+   GLchan rgbSpan[MAX_WIDTH][3];                                       \
+   GLuint i;                                                           \
+   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */               \
+   span.intTex[1] -= FIXED_HALF;                                       \
+   for (i = 0; i < span.count; i++) {                                  \
+      GLint s = FixedToInt(span.intTex[0]) & smask;                    \
+      GLint t = FixedToInt(span.intTex[1]) & tmask;                    \
+      GLint pos = (t << twidth_log2) + s;                              \
+      pos = pos + pos + pos;  /* multiply by 3 */                      \
+      rgbSpan[i][RCOMP] = texture[pos];                                        \
+      rgbSpan[i][GCOMP] = texture[pos+1];                              \
+      rgbSpan[i][BCOMP] = texture[pos+2];                              \
+      span.intTex[0] += span.intTexStep[0];                            \
+      span.intTex[1] += span.intTexStep[1];                            \
+   }                                                                   \
+   (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y,     \
+                                  (CONST GLchan (*)[3]) rgbSpan, NULL );
 
 #include "s_tritemp.h"
 }
@@ -303,6 +280,7 @@ static void simple_z_textured_triangle( GLcontext *ctx,
 #define INTERP_INT_TEX 1
 #define S_SCALE twidth
 #define T_SCALE theight
+
 #define SETUP_CODE                                                     \
    SWcontext *swrast = SWRAST_CONTEXT(ctx);                             \
    struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;     \
@@ -318,110 +296,58 @@ static void simple_z_textured_triangle( GLcontext *ctx,
       return;                                                          \
    }
 
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          CONST GLint n = RIGHT-LEFT;                          \
-          GLint i;                                             \
-          GLchan rgb[MAX_WIDTH][3];                            \
-           GLubyte mask[MAX_WIDTH];                            \
-          if (n>0) {                                           \
-              ffs -= FIXED_HALF; /* off-by-one error? */        \
-              fft -= FIXED_HALF;                                \
-             for (i=0;i<n;i++) {                               \
-                 GLdepth z = FixedToDepth(ffz);                        \
-                 if (z < zRow[i]) {                            \
-                    GLint s = FixedToInt(ffs) & smask;         \
-                    GLint t = FixedToInt(fft) & tmask;         \
-                    GLint pos = (t << twidth_log2) + s;                \
-                    pos = pos + pos + pos;  /* multiply by 3 */        \
-                    rgb[i][RCOMP] = texture[pos];              \
-                    rgb[i][GCOMP] = texture[pos+1];            \
-                    rgb[i][BCOMP] = texture[pos+2];            \
-                   zRow[i] = z;                                \
-                    mask[i] = 1;                               \
-                 }                                             \
-                 else {                                                \
-                    mask[i] = 0;                               \
-                 }                                             \
-                ffz += fdzdx;                                  \
-                ffs += fdsdx;                                  \
-                fft += fdtdx;                                  \
-             }                                                 \
-              (*swrast->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
-                           (CONST GLchan (*)[3]) rgb, mask );  \
-          }                                                    \
-       }
+#define RENDER_SPAN( span )                                            \
+   GLchan rgbSpan[MAX_WIDTH][3];                                       \
+   GLubyte mask[MAX_WIDTH];                                            \
+   GLuint i;                                                           \
+   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */               \
+   span.intTex[1] -= FIXED_HALF;                                       \
+   for (i = 0; i < span.count; i++) {                                  \
+      const GLdepth z = FixedToDepth(span.z);                          \
+      if (z < zRow[i]) {                                               \
+         GLint s = FixedToInt(span.intTex[0]) & smask;                 \
+         GLint t = FixedToInt(span.intTex[1]) & tmask;                 \
+         GLint pos = (t << twidth_log2) + s;                           \
+         pos = pos + pos + pos;  /* multiply by 3 */                   \
+         rgbSpan[i][RCOMP] = texture[pos];                             \
+         rgbSpan[i][GCOMP] = texture[pos+1];                           \
+         rgbSpan[i][BCOMP] = texture[pos+2];                           \
+         zRow[i] = z;                                                  \
+         mask[i] = 1;                                                  \
+      }                                                                        \
+      else {                                                           \
+         mask[i] = 0;                                                  \
+      }                                                                        \
+      span.intTex[0] += span.intTexStep[0];                            \
+      span.intTex[1] += span.intTexStep[1];                            \
+      span.z += span.zStep;                                            \
+   }                                                                   \
+   (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y,     \
+                                  (CONST GLchan (*)[3]) rgbSpan, mask );
 
 #include "s_tritemp.h"
 }
 
 
 
-/*
- * Render an RGB/RGBA textured triangle without perspective correction.
- */
-static void affine_textured_triangle( GLcontext *ctx,
-                                     const SWvertex *v0,
-                                     const SWvertex *v1,
-                                     const SWvertex *v2 )
+struct affine_info
 {
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
-#define INTERP_RGB 1
-#define INTERP_ALPHA 1
-#define INTERP_INT_TEX 1
-#define S_SCALE twidth
-#define T_SCALE theight
-#define SETUP_CODE                                                     \
-   struct gl_texture_unit *unit = ctx->Texture.Unit+0;                 \
-   struct gl_texture_object *obj = unit->Current2D;                    \
-   GLint b = obj->BaseLevel;                                           \
-   GLfloat twidth = (GLfloat) obj->Image[b]->Width;                    \
-   GLfloat theight = (GLfloat) obj->Image[b]->Height;                  \
-   GLint twidth_log2 = obj->Image[b]->WidthLog2;                       \
-   const GLchan *texture = (const GLchan *) obj->Image[b]->Data;       \
-   GLint smask = obj->Image[b]->Width - 1;                             \
-   GLint tmask = obj->Image[b]->Height - 1;                             \
-   GLint format = obj->Image[b]->Format;                                \
-   GLint filter = obj->MinFilter;                                       \
-   GLint envmode = unit->EnvMode;                                       \
-   GLint comp, tbytesline, tsize;                                       \
-   GLfixed er, eg, eb, ea;                                              \
-   GLint tr, tg, tb, ta;                                                \
-   if (!texture) {                                                     \
-      /* this shouldn't happen */                                      \
-      return;                                                          \
-   }                                                                   \
-   if (envmode == GL_BLEND || envmode == GL_ADD) {                      \
-      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */        \
-      er = FloatToFixed(unit->EnvColor[RCOMP]);                         \
-      eg = FloatToFixed(unit->EnvColor[GCOMP]);                         \
-      eb = FloatToFixed(unit->EnvColor[BCOMP]);                         \
-      ea = FloatToFixed(unit->EnvColor[ACOMP]);                         \
-   }                                                                    \
-   switch (format) {                                                    \
-   case GL_ALPHA:                                                       \
-   case GL_LUMINANCE:                                                   \
-   case GL_INTENSITY:                                                   \
-      comp = 1;                                                         \
-      break;                                                            \
-   case GL_LUMINANCE_ALPHA:                                             \
-      comp = 2;                                                         \
-      break;                                                            \
-   case GL_RGB:                                                         \
-      comp = 3;                                                         \
-      break;                                                            \
-   case GL_RGBA:                                                        \
-      comp = 4;                                                         \
-      break;                                                            \
-   default:                                                             \
-      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
-      return;                                                           \
-   }                                                                    \
-   tbytesline = obj->Image[b]->Width * comp;                            \
-   tsize = obj->Image[b]->Height * tbytesline;
+   GLenum filter;
+   GLenum format;
+   GLenum envmode;
+   GLint smask, tmask;
+   GLint twidth_log2;
+   const GLchan *texture;
+   GLchan er, eg, eb, ea;
+   GLint tbytesline, tsize;
+   GLint fixedToDepthShift;
+};
 
+static void
+affine_span(GLcontext *ctx, struct triangle_span *span,
+            struct affine_info *info)
+{
+   GLint tr, tg, tb, ta;
 
   /* Instead of defining a function for each mode, a test is done
    * between the outer and inner loops. This is to reduce code size
@@ -429,66 +355,75 @@ static void affine_textured_triangle( GLcontext *ctx,
    * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
    */
 
-#define NEAREST_RGB    \
-        tr = tex00[RCOMP]; \
-        tg = tex00[GCOMP]; \
-        tb = tex00[BCOMP]; \
+#define NEAREST_RGB            \
+        tr = tex00[RCOMP];     \
+        tg = tex00[GCOMP];     \
+        tb = tex00[BCOMP];     \
         ta = 0xff
 
-#define LINEAR_RGB                                                      \
-       tr = (ti * (si * tex00[0] + sf * tex01[0]) +                    \
-              tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
-       tg = (ti * (si * tex00[1] + sf * tex01[1]) +                    \
-              tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
-       tb = (ti * (si * tex00[2] + sf * tex01[2]) +                    \
-              tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
+#define LINEAR_RGB                                                     \
+       tr = (ti * (si * tex00[0] + sf * tex01[0]) +                    \
+              tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;        \
+       tg = (ti * (si * tex00[1] + sf * tex01[1]) +                    \
+              tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;        \
+       tb = (ti * (si * tex00[2] + sf * tex01[2]) +                    \
+              tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;        \
        ta = 0xff
 
-#define NEAREST_RGBA   \
-        tr = tex00[RCOMP]; \
-        tg = tex00[GCOMP]; \
-        tb = tex00[BCOMP]; \
+#define NEAREST_RGBA           \
+        tr = tex00[RCOMP];     \
+        tg = tex00[GCOMP];     \
+        tb = tex00[BCOMP];     \
         ta = tex00[ACOMP]
 
-#define LINEAR_RGBA                                                     \
-       tr = (ti * (si * tex00[0] + sf * tex01[0]) +                    \
-              tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
-       tg = (ti * (si * tex00[1] + sf * tex01[1]) +                    \
-              tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
-       tb = (ti * (si * tex00[2] + sf * tex01[2]) +                    \
-              tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
-       ta = (ti * (si * tex00[3] + sf * tex01[3]) +                    \
+#define LINEAR_RGBA                                                    \
+       tr = (ti * (si * tex00[0] + sf * tex01[0]) +                    \
+              tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;        \
+       tg = (ti * (si * tex00[1] + sf * tex01[1]) +                    \
+              tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;        \
+       tb = (ti * (si * tex00[2] + sf * tex01[2]) +                    \
+              tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;        \
+       ta = (ti * (si * tex00[3] + sf * tex01[3]) +                    \
               tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
 
-#define MODULATE                                       \
-        dest[RCOMP] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
-        dest[GCOMP] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
-        dest[BCOMP] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
-        dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
-
-#define DECAL                                                                \
-       dest[RCOMP] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
-       dest[GCOMP] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
-       dest[BCOMP] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
-       dest[ACOMP] = FixedToInt(ffa)
-
-#define BLEND                                                               \
-        dest[RCOMP] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
-        dest[GCOMP] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
-        dest[BCOMP] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
-        dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
-
-#define REPLACE       \
-        dest[RCOMP] = tr; \
-        dest[GCOMP] = tg; \
-        dest[BCOMP] = tb; \
+#define MODULATE                                                       \
+        dest[RCOMP] = span->red * (tr + 1) >> (FIXED_SHIFT + 8);       \
+        dest[GCOMP] = span->green * (tg + 1) >> (FIXED_SHIFT + 8);     \
+        dest[BCOMP] = span->blue * (tb + 1) >> (FIXED_SHIFT + 8);      \
+        dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8)
+
+#define DECAL                                                          \
+       dest[RCOMP] = ((0xff - ta) * span->red                          \
+           + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);     \
+       dest[GCOMP] = ((0xff - ta) * span->green                        \
+           + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);     \
+       dest[BCOMP] = ((0xff - ta) * span->blue                         \
+           + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8);     \
+       dest[ACOMP] = FixedToInt(span->alpha)
+
+#define BLEND                                                          \
+        dest[RCOMP] = ((0xff - tr) * span->red                         \
+           + (tr + 1) * info->er) >> (FIXED_SHIFT + 8);                        \
+        dest[GCOMP] = ((0xff - tg) * span->green                       \
+           + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8);                        \
+        dest[BCOMP] = ((0xff - tb) * span->blue                                \
+           + (tb + 1) * info->eb) >> (FIXED_SHIFT + 8);                        \
+        dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8)
+
+#define REPLACE                        \
+        dest[RCOMP] = tr;      \
+        dest[GCOMP] = tg;      \
+        dest[BCOMP] = tb;      \
         dest[ACOMP] = ta
 
-#define ADD                                                          \
-        dest[RCOMP] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
-        dest[GCOMP] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
-        dest[BCOMP] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
-        dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
+#define ADD                                                            \
+        dest[RCOMP] = ((span->red << 8)                                        \
+           + (tr + 1) * info->er) >> (FIXED_SHIFT + 8);                        \
+        dest[GCOMP] = ((span->green << 8)                              \
+           + (tg + 1) * info->eg) >> (FIXED_SHIFT + 8);                        \
+        dest[BCOMP] = ((span->blue << 8)                               \
+           + (tb + 1) * info->eb) >> (FIXED_SHIFT + 8);                        \
+        dest[ACOMP] = span->alpha * (ta + 1) >> (FIXED_SHIFT + 8)
 
 /* shortcuts */
 
@@ -496,180 +431,251 @@ static void affine_textured_triangle( GLcontext *ctx,
 
 #define NEAREST_RGBA_REPLACE  *(GLint *)dest = *(GLint *)tex00
 
-#define SPAN1(DO_TEX,COMP)                                 \
-       for (i=0;i<n;i++) {                                \
-           GLint s = FixedToInt(ffs) & smask;              \
-           GLint t = FixedToInt(fft) & tmask;              \
-           GLint pos = (t << twidth_log2) + s;             \
-           const GLchan *tex00 = texture + COMP * pos;     \
-          zspan[i] = FixedToDepth(ffz);                   \
-          fogspan[i] = ffog;;                             \
-           DO_TEX;                                         \
-          ffog += dfogdx;                                 \
-          ffz += fdzdx;                                   \
-           ffr += fdrdx;                                   \
-          ffg += fdgdx;                                   \
-           ffb += fdbdx;                                   \
-          ffa += fdadx;                                   \
-          ffs += fdsdx;                                   \
-          fft += fdtdx;                                   \
-           dest += 4;                                      \
+#define SPAN1(DO_TEX,COMP)                                             \
+       for (i = 0; i < span->count; i++) {                             \
+           GLint s = FixedToInt(span->intTex[0]) & info->smask;                \
+           GLint t = FixedToInt(span->intTex[1]) & info->tmask;                \
+           GLint pos = (t << info->twidth_log2) + s;                   \
+           const GLchan *tex00 = info->texture + COMP * pos;           \
+          zspan[i] = FixedToDepth(span->z);                            \
+          fogspan[i] = span->fog;                                      \
+           DO_TEX;                                                     \
+          span->fog += span->fogStep;                                  \
+          span->z += span->zStep;                                      \
+           span->red += span->redStep;                                 \
+          span->green += span->greenStep;                              \
+           span->blue += span->blueStep;                               \
+          span->alpha += span->alphaStep;                              \
+          span->intTex[0] += span->intTexStep[0];                      \
+          span->intTex[1] += span->intTexStep[1];                      \
+           dest += 4;                                                  \
        }
 
-#define SPAN2(DO_TEX,COMP)                                 \
-       for (i=0;i<n;i++) {                                \
-           GLint s = FixedToInt(ffs) & smask;              \
-           GLint t = FixedToInt(fft) & tmask;              \
-           GLint sf = ffs & FIXED_FRAC_MASK;               \
-           GLint tf = fft & FIXED_FRAC_MASK;               \
-           GLint si = FIXED_FRAC_MASK - sf;                \
-           GLint ti = FIXED_FRAC_MASK - tf;                \
-           GLint pos = (t << twidth_log2) + s;             \
-           const GLchan *tex00 = texture + COMP * pos;     \
-           const GLchan *tex10 = tex00 + tbytesline;       \
-           const GLchan *tex01 = tex00 + COMP;             \
-           const GLchan *tex11 = tex10 + COMP;             \
-           if (t == tmask) {                               \
-              tex10 -= tsize;                              \
-              tex11 -= tsize;                              \
-           }                                               \
-           if (s == smask) {                               \
-              tex01 -= tbytesline;                         \
-              tex11 -= tbytesline;                         \
-           }                                               \
-          zspan[i] = FixedToDepth(ffz);                   \
-          fogspan[i] = ffog;                              \
-           DO_TEX;                                         \
-          ffog += dfogdx;                                 \
-          ffz += fdzdx;                                   \
-           ffr += fdrdx;                                   \
-          ffg += fdgdx;                                   \
-           ffb += fdbdx;                                   \
-          ffa += fdadx;                                   \
-          ffs += fdsdx;                                   \
-          fft += fdtdx;                                   \
-           dest += 4;                                      \
+#define SPAN2(DO_TEX,COMP)                                             \
+       for (i = 0; i < span->count; i++) {                             \
+           GLint s = FixedToInt(span->intTex[0]) & info->smask;                \
+           GLint t = FixedToInt(span->intTex[1]) & info->tmask;                \
+           GLint sf = span->intTex[0] & FIXED_FRAC_MASK;               \
+           GLint tf = span->intTex[1] & FIXED_FRAC_MASK;               \
+           GLint si = FIXED_FRAC_MASK - sf;                            \
+           GLint ti = FIXED_FRAC_MASK - tf;                            \
+           GLint pos = (t << info->twidth_log2) + s;                   \
+           const GLchan *tex00 = info->texture + COMP * pos;           \
+           const GLchan *tex10 = tex00 + info->tbytesline;             \
+           const GLchan *tex01 = tex00 + COMP;                         \
+           const GLchan *tex11 = tex10 + COMP;                         \
+           (void) ti;                                                  \
+           (void) si;                                                  \
+           if (t == info->tmask) {                                     \
+              tex10 -= info->tsize;                                    \
+              tex11 -= info->tsize;                                    \
+           }                                                           \
+           if (s == info->smask) {                                     \
+              tex01 -= info->tbytesline;                               \
+              tex11 -= info->tbytesline;                               \
+           }                                                           \
+          zspan[i] = FixedToDepth(span->z);                            \
+          fogspan[i] = span->fog;                                      \
+           DO_TEX;                                                     \
+          span->fog += span->fogStep;                                  \
+          span->z += span->zStep;                                      \
+           span->red += span->redStep;                                 \
+          span->green += span->greenStep;                              \
+           span->blue += span->blueStep;                               \
+          span->alpha += span->alphaStep;                              \
+          span->intTex[0] += span->intTexStep[0];                      \
+          span->intTex[1] += span->intTexStep[1];                      \
+           dest += 4;                                                  \
        }
 
-/* here comes the heavy part.. (something for the compiler to chew on) */
-#define INNER_LOOP( LEFT, RIGHT, Y )                      \
-       {                                                  \
-           CONST GLint n = RIGHT-LEFT;                    \
-          GLint i;                                        \
-          GLdepth zspan[MAX_WIDTH];                       \
-          GLfloat fogspan[MAX_WIDTH];                     \
-          GLchan rgba[MAX_WIDTH][4];                      \
-          if (n>0) {                                      \
-              GLchan *dest = rgba[0];                      \
-              ffs -= FIXED_HALF; /* off-by-one error? */   \
-              fft -= FIXED_HALF;                           \
-              switch (filter) {                            \
-             case GL_NEAREST:                             \
-                switch (format) {                         \
-                 case GL_RGB:                              \
-                   switch (envmode) {                     \
-                   case GL_MODULATE:                      \
-                       SPAN1(NEAREST_RGB;MODULATE,3);      \
-                       break;                              \
-                   case GL_DECAL:                         \
-                    case GL_REPLACE:                       \
-                       SPAN1(NEAREST_RGB_REPLACE,3);       \
-                       break;                              \
-                    case GL_BLEND:                         \
-                       SPAN1(NEAREST_RGB;BLEND,3);         \
-                       break;                              \
-                   case GL_ADD:                           \
-                      SPAN1(NEAREST_RGB;ADD,3);           \
-                      break;                              \
-                    default: /* unexpected env mode */     \
-                       abort();                            \
-                   }                                      \
-                    break;                                 \
-                case GL_RGBA:                             \
-                   switch(envmode) {                      \
-                   case GL_MODULATE:                      \
-                       SPAN1(NEAREST_RGBA;MODULATE,4);     \
-                       break;                              \
-                   case GL_DECAL:                         \
-                       SPAN1(NEAREST_RGBA;DECAL,4);        \
-                       break;                              \
-                   case GL_BLEND:                         \
-                       SPAN1(NEAREST_RGBA;BLEND,4);        \
-                       break;                              \
-                   case GL_ADD:                           \
-                      SPAN1(NEAREST_RGBA;ADD,4);          \
-                      break;                              \
-                   case GL_REPLACE:                       \
-                       SPAN1(NEAREST_RGBA_REPLACE,4);      \
-                       break;                              \
-                    default: /* unexpected env mode */     \
-                       abort();                            \
-                   }                                      \
-                    break;                                 \
-                }                                         \
-                 break;                                    \
-             case GL_LINEAR:                              \
-                 ffs -= FIXED_HALF;                        \
-                 fft -= FIXED_HALF;                        \
-                switch (format) {                         \
-                case GL_RGB:                              \
-                   switch (envmode) {                     \
-                   case GL_MODULATE:                      \
-                      SPAN2(LINEAR_RGB;MODULATE,3);       \
-                       break;                              \
-                   case GL_DECAL:                         \
-                   case GL_REPLACE:                       \
-                       SPAN2(LINEAR_RGB;REPLACE,3);        \
-                       break;                              \
-                   case GL_BLEND:                         \
-                      SPAN2(LINEAR_RGB;BLEND,3);          \
-                      break;                              \
-                   case GL_ADD:                           \
-                      SPAN2(LINEAR_RGB;ADD,3);            \
-                      break;                              \
-                    default: /* unexpected env mode */     \
-                       abort();                            \
-                   }                                      \
-                   break;                                 \
-                case GL_RGBA:                             \
-                   switch (envmode) {                     \
-                   case GL_MODULATE:                      \
-                      SPAN2(LINEAR_RGBA;MODULATE,4);      \
-                      break;                              \
-                   case GL_DECAL:                         \
-                      SPAN2(LINEAR_RGBA;DECAL,4);         \
-                      break;                              \
-                   case GL_BLEND:                         \
-                      SPAN2(LINEAR_RGBA;BLEND,4);         \
-                      break;                              \
-                   case GL_ADD:                           \
-                      SPAN2(LINEAR_RGBA;ADD,4);           \
-                      break;                              \
-                   case GL_REPLACE:                       \
-                      SPAN2(LINEAR_RGBA;REPLACE,4);       \
-                      break;                              \
-                    default: /* unexpected env mode */     \
-                       abort();                            \
-                   }                                      \
-                   break;                                 \
-                }                                         \
-                 break;                                    \
-             }                                            \
-              _mesa_write_rgba_span(ctx, n, LEFT, Y, zspan,   \
-                                 fogspan,                  \
-                                 rgba, GL_POLYGON);        \
-              /* explicit kill of variables: */            \
-              ffr = ffg = ffb = ffa = 0;                   \
-           }                                               \
-       }
+#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
+
+   GLuint i;
+   GLdepth zspan[MAX_WIDTH];
+   GLfloat fogspan[MAX_WIDTH];
+   GLchan rgba[MAX_WIDTH][4];
+   GLchan *dest = rgba[0];
+   const GLint fixedToDepthShift = info->fixedToDepthShift;
+
+   span->intTex[0] -= FIXED_HALF;
+   span->intTex[1] -= FIXED_HALF;
+   switch (info->filter) {
+   case GL_NEAREST:
+      switch (info->format) {
+      case GL_RGB:
+         switch (info->envmode) {
+         case GL_MODULATE:
+            SPAN1(NEAREST_RGB;MODULATE,3);
+            break;
+         case GL_DECAL:
+         case GL_REPLACE:
+            SPAN1(NEAREST_RGB_REPLACE,3);
+            break;
+         case GL_BLEND:
+            SPAN1(NEAREST_RGB;BLEND,3);
+            break;
+         case GL_ADD:
+            SPAN1(NEAREST_RGB;ADD,3);
+            break;
+         default:
+            abort();
+         }
+         break;
+      case GL_RGBA:
+         switch(info->envmode) {
+         case GL_MODULATE:
+            SPAN1(NEAREST_RGBA;MODULATE,4);
+            break;
+         case GL_DECAL:
+            SPAN1(NEAREST_RGBA;DECAL,4);
+            break;
+         case GL_BLEND:
+            SPAN1(NEAREST_RGBA;BLEND,4);
+            break;
+         case GL_ADD:
+            SPAN1(NEAREST_RGBA;ADD,4);
+            break;
+         case GL_REPLACE:
+            SPAN1(NEAREST_RGBA_REPLACE,4);
+            break;
+         default:
+            abort();
+         }
+         break;
+      }
+      break;
+
+   case GL_LINEAR:
+      span->intTex[0] -= FIXED_HALF;
+      span->intTex[1] -= FIXED_HALF;
+      switch (info->format) {
+      case GL_RGB:
+         switch (info->envmode) {
+         case GL_MODULATE:
+            SPAN2(LINEAR_RGB;MODULATE,3);
+            break;
+         case GL_DECAL:
+         case GL_REPLACE:
+            SPAN2(LINEAR_RGB;REPLACE,3);
+            break;
+         case GL_BLEND:
+            SPAN2(LINEAR_RGB;BLEND,3);
+            break;
+         case GL_ADD:
+            SPAN2(LINEAR_RGB;ADD,3);
+            break;
+         default:
+            abort();
+         }
+         break;
+      case GL_RGBA:
+         switch (info->envmode) {
+         case GL_MODULATE:
+            SPAN2(LINEAR_RGBA;MODULATE,4);
+            break;
+         case GL_DECAL:
+            SPAN2(LINEAR_RGBA;DECAL,4);
+            break;
+         case GL_BLEND:
+            SPAN2(LINEAR_RGBA;BLEND,4);
+            break;
+         case GL_ADD:
+            SPAN2(LINEAR_RGBA;ADD,4);
+            break;
+         case GL_REPLACE:
+            SPAN2(LINEAR_RGBA;REPLACE,4);
+            break;
+         default:
+            abort();
+         }                 break;
+      }
+      break;
+   }
+   _mesa_write_rgba_span(ctx, span->count, span->x, span->y,
+                         zspan, fogspan, rgba, GL_POLYGON);
 
-#include "s_tritemp.h"
 #undef SPAN1
 #undef SPAN2
+#undef FixedToDepth
 }
 
 
 
+/*
+ * Render an RGB/RGBA textured triangle without perspective correction.
+ */
+static void affine_textured_triangle( GLcontext *ctx,
+                                     const SWvertex *v0,
+                                     const SWvertex *v1,
+                                     const SWvertex *v2 )
+{
+#define INTERP_Z 1
+#define INTERP_FOG 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INTERP_INT_TEX 1
+#define S_SCALE twidth
+#define T_SCALE theight
+
+#define SETUP_CODE
+   struct affine_info info;
+   struct gl_texture_unit *unit = ctx->Texture.Unit+0;                 \
+   struct gl_texture_object *obj = unit->Current2D;                    \
+   GLint b = obj->BaseLevel;                                           \
+   GLfloat twidth = (GLfloat) obj->Image[b]->Width;                    \
+   GLfloat theight = (GLfloat) obj->Image[b]->Height;                  \
+   info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
+   info.texture = (const GLchan *) obj->Image[b]->Data;                        \
+   info.twidth_log2 = obj->Image[b]->WidthLog2;                                \
+   info.smask = obj->Image[b]->Width - 1;                              \
+   info.tmask = obj->Image[b]->Height - 1;                             \
+   info.format = obj->Image[b]->Format;                                        \
+   info.filter = obj->MinFilter;                                       \
+   info.envmode = unit->EnvMode;                                       \
+                                                                       \
+   if (info.envmode == GL_BLEND) {                                     \
+      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */       \
+      info.er = FloatToFixed(unit->EnvColor[RCOMP]);                   \
+      info.eg = FloatToFixed(unit->EnvColor[GCOMP]);                   \
+      info.eb = FloatToFixed(unit->EnvColor[BCOMP]);                   \
+      info.ea = FloatToFixed(unit->EnvColor[ACOMP]);                   \
+   }                                                                   \
+   if (!info.texture) {                                                        \
+      /* this shouldn't happen */                                      \
+      return;                                                          \
+   }                                                                   \
+                                                                       \
+   switch (info.format) {                                              \
+   case GL_ALPHA:                                                      \
+   case GL_LUMINANCE:                                                  \
+   case GL_INTENSITY:                                                  \
+      info.tbytesline = obj->Image[b]->Width;                          \
+      break;                                                           \
+   case GL_LUMINANCE_ALPHA:                                            \
+      info.tbytesline = obj->Image[b]->Width * 2;                      \
+      break;                                                           \
+   case GL_RGB:                                                                \
+      info.tbytesline = obj->Image[b]->Width * 3;                      \
+      break;                                                           \
+   case GL_RGBA:                                                       \
+      info.tbytesline = obj->Image[b]->Width * 4;                      \
+      break;                                                           \
+   default:                                                            \
+      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
+      return;                                                          \
+   }                                                                   \
+   info.tsize = obj->Image[b]->Height * info.tbytesline;
+
+#define RENDER_SPAN( span )            \
+   affine_span(ctx, &span, &info);
+
+#include "s_tritemp.h"
+
+}
+
+
+#if 0 /* XXX disabled because of texcoord interpolation errors */
 /*
  * Render an perspective corrected RGB/RGBA textured triangle.
  * The Q (aka V in Mesa) coordinate must be zero such that the divide
@@ -681,7 +687,6 @@ static void affine_textured_triangle( GLcontext *ctx,
  * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
  * Send all questions and bug reports to him.
  */
-#if 0 /* XXX disabled because of texcoord interpolation errors */
 static void near_persp_textured_triangle(GLcontext *ctx,
                                         const SWvertex *v0,
                                         const SWvertex *v1,
@@ -701,6 +706,7 @@ static void near_persp_textured_triangle(GLcontext *ctx,
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
 #define INTERP_TEX 1
+
 #define SETUP_CODE                                                     \
    struct gl_texture_unit *unit = ctx->Texture.Unit+0;                 \
    struct gl_texture_object *obj = unit->Current2D;                    \
@@ -737,15 +743,15 @@ static void near_persp_textured_triangle(GLcontext *ctx,
       GLint t = (int)(TT * invQ + BIAS) & tmask;      \
       GLint pos = COMP * ((t << twidth_log2) + s);    \
       const GLchan *tex00 = texture + pos;            \
-      zspan[i] = FixedToDepth(ffz);                   \
-      fogspan[i] = ffog;                              \
+      zspan[i] = FixedToDepth(span.z);                   \
+      fogspan[i] = span.fog;                              \
       DO_TEX;                                         \
-      ffog += dfogdx;                                 \
-      ffz += fdzdx;                                   \
-      ffr += fdrdx;                                   \
-      ffg += fdgdx;                                   \
-      ffb += fdbdx;                                   \
-      ffa += fdadx;                                   \
+      span.fog += span.fogStep;                                 \
+      span.z += span.zStep;                                   \
+      span.red += span.redStep;                                   \
+      span.green += span.greenStep;                                   \
+      span.blue += span.blueStep;                                   \
+      span.alpha += span.alphaStep;                                   \
       SS += dSdx;                                     \
       TT += dTdx;                                     \
       vv += dvdx;                                     \
@@ -907,15 +913,15 @@ static void near_persp_textured_triangle(GLcontext *ctx,
       if (j>n || j<-100000)            \
          j = n;                                \
       while (i<j) {                    \
-         zspan[i] = FixedToDepth(ffz); \
-         fogspan[i] = ffog;             \
+         zspan[i] = FixedToDepth(span.z);      \
+         fogspan[i] = span.fog;             \
          DO_TEX;                       \
-         ffog += dfogdx;                \
-         ffz += fdzdx;                 \
-         ffr += fdrdx;                 \
-         ffg += fdgdx;                 \
-         ffb += fdbdx;                 \
-         ffa += fdadx;                 \
+         span.fog += span.fogStep;                \
+         span.z += span.zStep;                 \
+         span.red += span.redStep;                     \
+         span.green += span.greenStep;                 \
+         span.blue += span.blueStep;                   \
+         span.alpha += span.alphaStep;                 \
          dest += 4;                    \
          i++;                          \
       }                                        \
@@ -1395,7 +1401,7 @@ static void near_persp_textured_triangle(GLcontext *ctx,
          }                                                             \
          _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan,                        \
                              fogspan, rgba, GL_POLYGON);               \
-         ffr = ffg = ffb = ffa = 0;                                    \
+         span.red = span.green = span.blue = span.alpha = 0;                                   \
       }                                                                        \
    }                                                                   \
 
@@ -1413,6 +1419,7 @@ static void near_persp_textured_triangle(GLcontext *ctx,
 #endif
 
 
+#if 0 /* XXX disabled because of texcoord interpolation errors */
 /*
  * Render an perspective corrected RGB/RGBA textured triangle.
  * The Q (aka V in Mesa) coordinate must be zero such that the divide
@@ -1421,7 +1428,6 @@ static void near_persp_textured_triangle(GLcontext *ctx,
  * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
  * Send all questions and bug reports to him.
  */
-#if 0 /* XXX disabled because of texcoord interpolation errors */
 static void lin_persp_textured_triangle( GLcontext *ctx,
                                         const SWvertex *v0,
                                         const SWvertex *v1,
@@ -1433,6 +1439,7 @@ static void lin_persp_textured_triangle( GLcontext *ctx,
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
 #define INTERP_TEX 1
+
 #define SETUP_CODE                                                     \
    struct gl_texture_unit *unit = ctx->Texture.Unit+0;                 \
    struct gl_texture_object *obj = unit->Current2D;                    \
@@ -1483,43 +1490,43 @@ static void lin_persp_textured_triangle( GLcontext *ctx,
    tsize = theight * tbytesline;
 
 
-#define SPAN(DO_TEX,COMP)                                  \
-        for (i=0;i<n;i++) {                                \
-           GLfloat invQ = 1.0f / vv;                       \
-           GLfixed ffs = (int)(SS * invQ);                 \
-           GLfixed fft = (int)(TT * invQ);                 \
-          GLint s = FixedToInt(ffs) & smask;              \
-          GLint t = FixedToInt(fft) & tmask;              \
-           GLint sf = ffs & FIXED_FRAC_MASK;               \
-           GLint tf = fft & FIXED_FRAC_MASK;               \
-           GLint si = FIXED_FRAC_MASK - sf;                \
-           GLint ti = FIXED_FRAC_MASK - tf;                \
-           GLint pos = COMP * ((t << twidth_log2) + s);    \
-           GLchan *tex00 = texture + pos;                  \
-           GLchan *tex10 = tex00 + tbytesline;             \
-           GLchan *tex01 = tex00 + COMP;                   \
-           GLchan *tex11 = tex10 + COMP;                   \
-           if (t == tmask) {                               \
-              tex10 -= tsize;                              \
-              tex11 -= tsize;                              \
-           }                                               \
-           if (s == smask) {                               \
-              tex01 -= tbytesline;                         \
-              tex11 -= tbytesline;                         \
-           }                                               \
-          zspan[i] = FixedToDepth(ffz);                   \
-          fogspan[i] = ffog;                              \
-           DO_TEX;                                         \
-          ffog += dfogdx;                                 \
-          ffz += fdzdx;                                   \
-           ffr += fdrdx;                                   \
-          ffg += fdgdx;                                   \
-           ffb += fdbdx;                                   \
-          ffa += fdadx;                                   \
-           SS += dSdx;                                     \
-           TT += dTdx;                                     \
-          vv += dvdx;                                     \
-           dest += 4;                                      \
+#define SPAN(DO_TEX,COMP)                                      \
+        for (i=0;i<n;i++) {                                    \
+           GLfloat invQ = 1.0f / vv;                           \
+           GLfixed span.intTex[0] = (int)(SS * invQ);          \
+           GLfixed span.intTex[1] = (int)(TT * invQ);          \
+          GLint s = FixedToInt(span.intTex[0]) & smask;        \
+          GLint t = FixedToInt(span.intTex[1]) & tmask;        \
+           GLint sf = span.intTex[0] & FIXED_FRAC_MASK;                \
+           GLint tf = span.intTex[1] & FIXED_FRAC_MASK;                \
+           GLint si = FIXED_FRAC_MASK - sf;                    \
+           GLint ti = FIXED_FRAC_MASK - tf;                    \
+           GLint pos = COMP * ((t << twidth_log2) + s);                \
+           GLchan *tex00 = texture + pos;                      \
+           GLchan *tex10 = tex00 + tbytesline;                 \
+           GLchan *tex01 = tex00 + COMP;                       \
+           GLchan *tex11 = tex10 + COMP;                       \
+           if (t == tmask) {                                   \
+              tex10 -= tsize;                                  \
+              tex11 -= tsize;                                  \
+           }                                                   \
+           if (s == smask) {                                   \
+              tex01 -= tbytesline;                             \
+              tex11 -= tbytesline;                             \
+           }                                                   \
+          zspan[i] = FixedToDepth(span.z);                     \
+          fogspan[i] = span.fog;                               \
+           DO_TEX;                                             \
+          span.fog += span.fogStep;                            \
+          span.z += span.zStep;                                \
+           span.red += span.redStep;                           \
+          span.green += span.greenStep;                        \
+           span.blue += span.blueStep;                         \
+          span.alpha += span.alphaStep;                        \
+           SS += dSdx;                                         \
+           TT += dTdx;                                         \
+          vv += dvdx;                                          \
+           dest += 4;                                          \
        }
 
 #define INNER_LOOP( LEFT, RIGHT, Y )                   \
@@ -1582,7 +1589,6 @@ static void lin_persp_textured_triangle( GLcontext *ctx,
          _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan,        \
                              fogspan,                   \
                              rgba, GL_POLYGON );       \
-         ffr = ffg = ffb = ffa = 0;                    \
       }                                                        \
    }
 
@@ -1592,11 +1598,253 @@ static void lin_persp_textured_triangle( GLcontext *ctx,
 #endif
 
 
+/*
+ * Generate arrays of fragment colors, z, fog, texcoords, etc from a
+ * triangle span object.  Then call the span/fragment processsing
+ * functions in s_span.[ch].
+ */
+static void
+rasterize_span(GLcontext *ctx, const struct triangle_span *span)
+{
+   GLchan rgba[MAX_WIDTH][4];
+   GLchan spec[MAX_WIDTH][4];
+   GLuint index[MAX_WIDTH];
+   GLuint z[MAX_WIDTH];
+   GLfloat fog[MAX_WIDTH];
+   GLfloat sTex[MAX_WIDTH], tTex[MAX_WIDTH], rTex[MAX_WIDTH];
+   GLfloat lambda[MAX_WIDTH];
+   GLfloat msTex[MAX_TEXTURE_UNITS][MAX_WIDTH];
+   GLfloat mtTex[MAX_TEXTURE_UNITS][MAX_WIDTH];
+   GLfloat mrTex[MAX_TEXTURE_UNITS][MAX_WIDTH];
+   GLfloat mLambda[MAX_TEXTURE_UNITS][MAX_WIDTH];
+
+   if (span->activeMask & SPAN_RGBA) {
+      GLfixed r = span->red;
+      GLfixed g = span->green;
+      GLfixed b = span->blue;
+      GLfixed a = span->alpha;
+      GLuint i;
+      for (i = 0; i < span->count; i++) {
+         rgba[i][RCOMP] = FixedToInt(r);
+         rgba[i][GCOMP] = FixedToInt(g);
+         rgba[i][BCOMP] = FixedToInt(b);
+         rgba[i][ACOMP] = FixedToInt(a);
+         r += span->redStep;
+         g += span->greenStep;
+         b += span->blueStep;
+         a += span->alphaStep;
+      }
+   }
+   if (span->activeMask & SPAN_SPEC) {
+      GLfixed r = span->specRed;
+      GLfixed g = span->specGreen;
+      GLfixed b = span->specBlue;
+      GLuint i;
+      for (i = 0; i < span->count; i++) {
+         spec[i][RCOMP] = FixedToInt(r);
+         spec[i][GCOMP] = FixedToInt(g);
+         spec[i][BCOMP] = FixedToInt(b);
+         r += span->specRedStep;
+         g += span->specGreenStep;
+         b += span->specBlueStep;
+      }
+   }
+   if (span->activeMask & SPAN_INDEX) {
+      GLuint i;
+      GLfixed ind = span->index;
+      for (i = 0; i < span->count; i++) {
+         index[i] = FixedToInt(ind);
+         ind += span->indexStep;
+      }
+   }
+   if (span->activeMask & SPAN_Z) {
+      if (ctx->Visual.depthBits <= 16) {
+         GLuint i;
+         GLfixed zval = span->z;
+         for (i = 0; i < span->count; i++) {
+            z[i] = FixedToInt(zval);
+            zval += span->zStep;
+         }
+      }
+      else {
+         /* Deep Z buffer, no fixed->int shift */
+         GLuint i;
+         GLfixed zval = span->z;
+         for (i = 0; i < span->count; i++) {
+            z[i] = zval;
+            zval += span->zStep;
+         }
+      }
+   }
+   if (span->activeMask & SPAN_FOG) {
+      GLuint i;
+      GLfloat f = span->fog;
+      for (i = 0; i < span->count; i++) {
+         fog[i] = f;
+         f += span->fogStep;
+      }
+   }
+   if (span->activeMask & SPAN_TEXTURE) {
+      if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
+         /* multitexture */
+         if (span->activeMask & SPAN_LAMBDA) {
+            /* with lambda */
+            GLuint u;
+            for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
+               if (ctx->Texture.Unit[u]._ReallyEnabled) {
+                  GLfloat s = span->tex[u][0];
+                  GLfloat t = span->tex[u][1];
+                  GLfloat r = span->tex[u][2];
+                  GLfloat q = span->tex[u][3];
+                  GLuint i;
+                  for (i = 0; i < span->count; i++) {
+                     const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
+                     msTex[u][i] = s * invQ;
+                     mtTex[u][i] = t * invQ;
+                     mrTex[u][i] = r * invQ;
+                     mLambda[u][i] = log(span->rho[u] * invQ * invQ) * 1.442695F * 0.5F;
+                     s += span->texStep[u][0];
+                     t += span->texStep[u][1];
+                     r += span->texStep[u][2];
+                     q += span->texStep[u][3];
+                  }
+               }
+            }
+         }
+         else {
+            /* without lambda */
+            GLuint u;
+            for (u = 0; u < MAX_TEXTURE_UNITS; u++) {
+               if (ctx->Texture.Unit[u]._ReallyEnabled) {
+                  GLfloat s = span->tex[u][0];
+                  GLfloat t = span->tex[u][1];
+                  GLfloat r = span->tex[u][2];
+                  GLfloat q = span->tex[u][3];
+                  GLuint i;
+                  for (i = 0; i < span->count; i++) {
+                     const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
+                     msTex[u][i] = s * invQ;
+                     mtTex[u][i] = t * invQ;
+                     mrTex[u][i] = r * invQ;
+                     s += span->texStep[u][0];
+                     t += span->texStep[u][1];
+                     r += span->texStep[u][2];
+                     q += span->texStep[u][3];
+                  }
+               }
+            }
+         }
+      }
+      else {
+         /* just texture unit 0 */
+         if (span->activeMask & SPAN_LAMBDA) {
+            /* with lambda */
+            GLfloat s = span->tex[0][0];
+            GLfloat t = span->tex[0][1];
+            GLfloat r = span->tex[0][2];
+            GLfloat q = span->tex[0][3];
+            GLuint i;
+            for (i = 0; i < span->count; i++) {
+               const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
+               sTex[i] = s * invQ;
+               tTex[i] = t * invQ;
+               rTex[i] = r * invQ;
+               lambda[i] = log(span->rho[0] * invQ * invQ) * 1.442695F * 0.5F;
+               s += span->texStep[0][0];
+               t += span->texStep[0][1];
+               r += span->texStep[0][2];
+               q += span->texStep[0][3];
+            }
+         }
+         else {
+            /* without lambda */
+            GLfloat s = span->tex[0][0];
+            GLfloat t = span->tex[0][1];
+            GLfloat r = span->tex[0][2];
+            GLfloat q = span->tex[0][3];
+            GLuint i;
+            for (i = 0; i < span->count; i++) {
+               const GLfloat invQ = (q == 0.0F) ? 1.0 : (1.0F / q);
+               sTex[i] = s * invQ;
+               tTex[i] = t * invQ;
+               rTex[i] = r * invQ;
+               s += span->texStep[0][0];
+               t += span->texStep[0][1];
+               r += span->texStep[0][2];
+               q += span->texStep[0][3];
+            }
+         }
+      }
+   }
+   /* XXX keep this? */
+   if (span->activeMask & SPAN_INT_TEXTURE) {
+      GLint intTexcoord[MAX_WIDTH][2];
+      GLfixed s = span->intTex[0];
+      GLfixed t = span->intTex[1];
+      GLuint i;
+      for (i = 0; i < span->count; i++) {
+         intTexcoord[i][0] = FixedToInt(s);
+         intTexcoord[i][1] = FixedToInt(t);
+         s += span->intTexStep[0];
+         t += span->intTexStep[1];
+      }
+   }
+
+   /* examine activeMask and call a s_span.c function */
+   if (span->activeMask & SPAN_TEXTURE) {
+      const GLfloat *fogPtr;
+      if (span->activeMask & SPAN_FOG)
+         fogPtr = fog;
+      else
+         fogPtr = NULL;
+
+      if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
+         if (span->activeMask & SPAN_SPEC) {
+            _mesa_write_multitexture_span(ctx, span->count, span->x, span->y,
+                                          z, fogPtr,
+                                          (const GLfloat (*)[MAX_WIDTH]) msTex,
+                                          (const GLfloat (*)[MAX_WIDTH]) mtTex,
+                                          (const GLfloat (*)[MAX_WIDTH]) mrTex,
+                                          (GLfloat (*)[MAX_WIDTH]) mLambda,
+                                          rgba, (CONST GLchan (*)[4]) spec,
+                                          GL_POLYGON );
+         }
+         else {
+            _mesa_write_multitexture_span(ctx, span->count, span->x, span->y,
+                                          z, fogPtr,
+                                          (const GLfloat (*)[MAX_WIDTH]) msTex,
+                                          (const GLfloat (*)[MAX_WIDTH]) mtTex,
+                                          (const GLfloat (*)[MAX_WIDTH]) mrTex,
+                                          (GLfloat (*)[MAX_WIDTH]) mLambda,
+                                          rgba, NULL, GL_POLYGON);
+         }
+      }
+      else {
+         /* single texture */
+         if (span->activeMask & SPAN_SPEC) {
+            _mesa_write_texture_span(ctx, span->count, span->x, span->y,
+                                     z, fogPtr, sTex, tTex, rTex, lambda,
+                                     rgba, (CONST GLchan (*)[4]) spec,
+                                     GL_POLYGON);
+         }
+         else {
+            _mesa_write_texture_span(ctx, span->count, span->x, span->y,
+                                     z, fogPtr, sTex, tTex, rTex, lambda,
+                                     rgba, NULL, GL_POLYGON);
+         }
+      }
+   }
+   else {
+      _mesa_problem(ctx, "rasterize_span() should only be used for texturing");
+   }
+}
+
+                
+
+
 /*
  * Render a smooth-shaded, textured, RGBA triangle.
- * Interpolate S,T,U with perspective correction, w/out mipmapping.
- * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
- * R is already used for red.
+ * Interpolate S,T,R with perspective correction, w/out mipmapping.
  */
 static void general_textured_triangle( GLcontext *ctx,
                                       const SWvertex *v0,
@@ -1609,73 +1857,60 @@ static void general_textured_triangle( GLcontext *ctx,
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
 #define INTERP_TEX 1
-#define SETUP_CODE                                             \
-   GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);    \
-   GLint r, g, b, a;                                           \
-   if (flat_shade) {                                           \
-      r = v2->color[RCOMP];                                    \
-      g = v2->color[GCOMP];                                    \
-      b = v2->color[BCOMP];                                    \
-      a = v2->color[ACOMP];                                    \
-   }
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          GLint i;                                             \
-           const GLint n = RIGHT-LEFT;                         \
-          GLdepth zspan[MAX_WIDTH];                            \
-          GLfloat fogspan[MAX_WIDTH];                          \
-          GLchan rgba[MAX_WIDTH][4];                           \
-           GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];   \
-          if (n>0) {                                           \
-              if (flat_shade) {                                        \
-                 for (i=0;i<n;i++) {                           \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;      \
-                   zspan[i] = FixedToDepth(ffz);               \
-                   fogspan[i] = ffog;                          \
-                   rgba[i][RCOMP] = r;                         \
-                   rgba[i][GCOMP] = g;                         \
-                   rgba[i][BCOMP] = b;                         \
-                   rgba[i][ACOMP] = a;                         \
-                   s[i] = ss*invQ;                             \
-                   t[i] = tt*invQ;                             \
-                   u[i] = uu*invQ;                             \
-                   ffog += dfogdx;                             \
-                   ffz += fdzdx;                               \
-                   ss += dsdx;                                 \
-                   tt += dtdx;                                 \
-                   uu += dudx;                                 \
-                   vv += dvdx;                                 \
-                }                                              \
-              }                                                        \
-              else {                                           \
-                 for (i=0;i<n;i++) {                           \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;      \
-                   zspan[i] = FixedToDepth(ffz);               \
-                   rgba[i][RCOMP] = FixedToInt(ffr);           \
-                   rgba[i][GCOMP] = FixedToInt(ffg);           \
-                   rgba[i][BCOMP] = FixedToInt(ffb);           \
-                   rgba[i][ACOMP] = FixedToInt(ffa);           \
-                   fogspan[i] = ffog;                          \
-                   s[i] = ss*invQ;                             \
-                   t[i] = tt*invQ;                             \
-                   u[i] = uu*invQ;                             \
-                   ffog += dfogdx;                             \
-                   ffz += fdzdx;                               \
-                   ffr += fdrdx;                               \
-                   ffg += fdgdx;                               \
-                   ffb += fdbdx;                               \
-                   ffa += fdadx;                               \
-                   ss += dsdx;                                 \
-                   tt += dtdx;                                 \
-                   uu += dudx;                                 \
-                   vv += dvdx;                                 \
-                }                                              \
-              }                                                        \
-             _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, \
-                                     fogspan, s, t, u, NULL,   \
-                                    rgba, NULL, GL_POLYGON );  \
-          }                                                    \
-       }
+
+#define SETUP_CODE                                                     \
+   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;        \
+   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
+   const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT);       \
+   GLfixed rFlat, gFlat, bFlat, aFlat;                                 \
+   if (flatShade) {                                                    \
+      rFlat = IntToFixed(v2->color[RCOMP]);                            \
+      gFlat = IntToFixed(v2->color[GCOMP]);                            \
+      bFlat = IntToFixed(v2->color[BCOMP]);                            \
+      aFlat = IntToFixed(v2->color[ACOMP]);                            \
+   }                                                                   \
+   span.texWidth[0] = (GLfloat) texImage->Width;                       \
+   span.texHeight[0] = (GLfloat) texImage->Height;                     \
+   (void) fixedToDepthShift;
+
+#define RENDER_SPAN( span )                                            \
+   GLdepth zSpan[MAX_WIDTH];                                           \
+   GLfloat fogSpan[MAX_WIDTH];                                         \
+   GLchan rgbaSpan[MAX_WIDTH][4];                                      \
+   GLfloat sSpan[MAX_WIDTH], tSpan[MAX_WIDTH], uSpan[MAX_WIDTH];       \
+   GLuint i;                                                           \
+   if (flatShade) {                                                    \
+      span.red = rFlat;    span.redStep = 0;                           \
+      span.green = gFlat;  span.greenStep = 0;                         \
+      span.blue = bFlat;   span.blueStep = 0;                          \
+      span.alpha = aFlat;  span.alphaStep = 0;                         \
+   }                                                                   \
+   /* NOTE: we could just call rasterize_span() here instead */                \
+   for (i = 0; i < span.count; i++) {                                  \
+      GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0;   \
+      zSpan[i] = FixedToDepth(span.z);                                 \
+      span.z += span.zStep;                                            \
+      fogSpan[i] = span.fog;                                           \
+      span.fog += span.fogStep;                                                \
+      rgbaSpan[i][RCOMP] = FixedToInt(span.red);                       \
+      rgbaSpan[i][GCOMP] = FixedToInt(span.green);                     \
+      rgbaSpan[i][BCOMP] = FixedToInt(span.blue);                      \
+      rgbaSpan[i][ACOMP] = FixedToInt(span.alpha);                     \
+      span.red += span.redStep;                                                \
+      span.green += span.greenStep;                                    \
+      span.blue += span.blueStep;                                      \
+      span.alpha += span.alphaStep;                                    \
+      sSpan[i] = span.tex[0][0] * invQ;                                        \
+      tSpan[i] = span.tex[0][1] * invQ;                                        \
+      uSpan[i] = span.tex[0][2] * invQ;                                        \
+      span.tex[0][0] += span.texStep[0][0];                            \
+      span.tex[0][1] += span.texStep[0][1];                            \
+      span.tex[0][2] += span.texStep[0][2];                            \
+      span.tex[0][3] += span.texStep[0][3];                            \
+   }                                                                   \
+   _mesa_write_texture_span(ctx, span.count, span.x, span.y,           \
+                            zSpan, fogSpan, sSpan, tSpan, uSpan,       \
+                            NULL, rgbaSpan, NULL, GL_POLYGON );
 
 #include "s_tritemp.h"
 }
@@ -1684,18 +1919,12 @@ static void general_textured_triangle( GLcontext *ctx,
 /*
  * Render a smooth-shaded, textured, RGBA triangle with separate specular
  * color interpolation.
- * Interpolate S,T,U with perspective correction, w/out mipmapping.
- * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
- * R is already used for red.
+ * Interpolate texcoords with perspective correction, w/out mipmapping.
  */
-static void general_textured_spec_triangle1( GLcontext *ctx,
-                                            const SWvertex *v0,
-                                            const SWvertex *v1,
-                                            const SWvertex *v2,
-                                             GLdepth zspan[MAX_WIDTH],
-                                             GLfloat fogspan[MAX_WIDTH],
-                                             GLchan rgba[MAX_WIDTH][4],
-                                             GLchan spec[MAX_WIDTH][4] )
+static void general_textured_spec_triangle( GLcontext *ctx,
+                                           const SWvertex *v0,
+                                           const SWvertex *v1,
+                                           const SWvertex *v2 )
 {
 #define INTERP_Z 1
 #define INTERP_FOG 1
@@ -1704,84 +1933,37 @@ static void general_textured_spec_triangle1( GLcontext *ctx,
 #define INTERP_SPEC 1
 #define INTERP_ALPHA 1
 #define INTERP_TEX 1
-#define SETUP_CODE                                             \
-   GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);    \
-   GLint r, g, b, a, sr, sg, sb;                               \
-   if (flat_shade) {                                           \
-      r = v2->color[RCOMP];                                    \
-      g = v2->color[GCOMP];                                    \
-      b = v2->color[BCOMP];                                    \
-      a = v2->color[ACOMP];                                    \
-      sr = v2->specular[RCOMP];                                        \
-      sg = v2->specular[GCOMP];                                        \
-      sb = v2->specular[BCOMP];                                        \
-   }
-#define INNER_LOOP( LEFT, RIGHT, Y )                           \
-       {                                                       \
-          GLint i;                                             \
-           const GLint n = RIGHT-LEFT;                         \
-           GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];   \
-          if (n>0) {                                           \
-              if (flat_shade) {                                        \
-                 for (i=0;i<n;i++) {                           \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;      \
-                   zspan[i] = FixedToDepth(ffz);               \
-                   fogspan[i] = ffog;                          \
-                   rgba[i][RCOMP] = r;                         \
-                   rgba[i][GCOMP] = g;                         \
-                   rgba[i][BCOMP] = b;                         \
-                   rgba[i][ACOMP] = a;                         \
-                   spec[i][RCOMP] = sr;                        \
-                   spec[i][GCOMP] = sg;                        \
-                   spec[i][BCOMP] = sb;                        \
-                   s[i] = ss*invQ;                             \
-                   t[i] = tt*invQ;                             \
-                   u[i] = uu*invQ;                             \
-                   ffog += dfogdx;                             \
-                   ffz += fdzdx;                               \
-                   ss += dsdx;                                 \
-                   tt += dtdx;                                 \
-                   uu += dudx;                                 \
-                   vv += dvdx;                                 \
-                }                                              \
-              }                                                        \
-              else {                                           \
-                 for (i=0;i<n;i++) {                           \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;      \
-                   zspan[i] = FixedToDepth(ffz);               \
-                   fogspan[i] = ffog;                          \
-                   rgba[i][RCOMP] = FixedToInt(ffr);           \
-                   rgba[i][GCOMP] = FixedToInt(ffg);           \
-                   rgba[i][BCOMP] = FixedToInt(ffb);           \
-                   rgba[i][ACOMP] = FixedToInt(ffa);           \
-                   spec[i][RCOMP] = FixedToInt(ffsr);          \
-                   spec[i][GCOMP] = FixedToInt(ffsg);          \
-                   spec[i][BCOMP] = FixedToInt(ffsb);          \
-                   s[i] = ss*invQ;                             \
-                   t[i] = tt*invQ;                             \
-                   u[i] = uu*invQ;                             \
-                   ffog += dfogdx;                             \
-                   ffz += fdzdx;                               \
-                   ffr += fdrdx;                               \
-                   ffg += fdgdx;                               \
-                   ffb += fdbdx;                               \
-                   ffa += fdadx;                               \
-                   ffsr += fdsrdx;                             \
-                   ffsg += fdsgdx;                             \
-                   ffsb += fdsbdx;                             \
-                   ss += dsdx;                                 \
-                   tt += dtdx;                                 \
-                   uu += dudx;                                 \
-                   vv += dvdx;                                 \
-                }                                              \
-              }                                                        \
-             _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, \
-                                   fogspan,                     \
-                                   s, t, u, NULL, rgba,                \
-                                   (CONST GLchan (*)[4]) spec, \
-                                  GL_POLYGON );                \
-          }                                                    \
-       }
+
+#define SETUP_CODE                                                     \
+   const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;        \
+   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
+   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);     \
+   GLfixed rFlat, gFlat, bFlat, aFlat;                                 \
+   GLfixed srFlat, sgFlat, sbFlat;                                     \
+   if (flatShade) {                                                    \
+      rFlat = IntToFixed(v2->color[RCOMP]);                            \
+      gFlat = IntToFixed(v2->color[GCOMP]);                            \
+      bFlat = IntToFixed(v2->color[BCOMP]);                            \
+      aFlat = IntToFixed(v2->color[ACOMP]);                            \
+      srFlat = IntToFixed(v2->specular[RCOMP]);                                \
+      sgFlat = IntToFixed(v2->specular[GCOMP]);                                \
+      sbFlat = IntToFixed(v2->specular[BCOMP]);                                \
+   }                                                                   \
+   span.texWidth[0] = (GLfloat) texImage->Width;                       \
+   span.texHeight[0] = (GLfloat) texImage->Height;                     \
+   (void) fixedToDepthShift;
+
+#define RENDER_SPAN( span )                                    \
+   if (flatShade) {                                            \
+      span.red = rFlat;    span.redStep = 0;                   \
+      span.green = gFlat;  span.greenStep = 0;                 \
+      span.blue = bFlat;   span.blueStep = 0;                  \
+      span.alpha = aFlat;  span.alphaStep = 0;                 \
+      span.specRed = srFlat;    span.specRedStep = 0;          \
+      span.specGreen = sgFlat;  span.specGreenStep = 0;                \
+      span.specBlue = sbFlat;   span.specBlueStep = 0;         \
+   }                                                           \
+   rasterize_span(ctx, &span);
 
 #include "s_tritemp.h"
 }
@@ -1789,102 +1971,54 @@ static void general_textured_spec_triangle1( GLcontext *ctx,
 
 /*
  * Render a smooth-shaded, textured, RGBA triangle.
- * Interpolate S,T,U with perspective correction and compute lambda for
+ * Interpolate S,T,R with perspective correction and compute lambda for
  * each fragment.  Lambda is used to determine whether to use the
  * minification or magnification filter.  If minification and using
  * mipmaps, lambda is also used to select the texture level of detail.
  */
-static void lambda_textured_triangle1( GLcontext *ctx,
-                                      const SWvertex *v0,
-                                      const SWvertex *v1,
-                                      const SWvertex *v2,
-                                       GLfloat s[MAX_WIDTH],
-                                       GLfloat t[MAX_WIDTH],
-                                       GLfloat u[MAX_WIDTH] )
+static void lambda_textured_triangle( GLcontext *ctx,
+                                     const SWvertex *v0,
+                                     const SWvertex *v1,
+                                     const SWvertex *v2 )
 {
 #define INTERP_Z 1
 #define INTERP_FOG 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
-#define INTERP_LAMBDA 1
 #define INTERP_TEX 1
+#define INTERP_LAMBDA 1
 
 #define SETUP_CODE                                                     \
    const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;        \
-   const GLint baseLevel = obj->BaseLevel;                             \
-   const struct gl_texture_image *texImage = obj->Image[baseLevel];    \
-   const GLfloat twidth = (GLfloat) texImage->Width;                   \
-   const GLfloat theight = (GLfloat) texImage->Height;                 \
-   const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);      \
-   GLint r, g, b, a;                                                   \
-   if (flat_shade) {                                                   \
-      r = v2->color[RCOMP];                                            \
-      g = v2->color[GCOMP];                                            \
-      b = v2->color[BCOMP];                                            \
-      a = v2->color[ACOMP];                                            \
-   }
-
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-       {                                                               \
-          GLint i;                                                     \
-           const GLint n = RIGHT-LEFT;                                 \
-          GLdepth zspan[MAX_WIDTH];                                    \
-          GLfloat fogspan[MAX_WIDTH];                                  \
-          GLchan rgba[MAX_WIDTH][4];                                   \
-          GLfloat lambda[MAX_WIDTH];                                   \
-          if (n>0) {                                                   \
-             if (flat_shade) {                                         \
-                for (i=0;i<n;i++) {                                    \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;              \
-                   zspan[i] = FixedToDepth(ffz);                       \
-                   fogspan[i] = ffog;                                  \
-                   rgba[i][RCOMP] = r;                                 \
-                   rgba[i][GCOMP] = g;                                 \
-                   rgba[i][BCOMP] = b;                                 \
-                   rgba[i][ACOMP] = a;                                 \
-                   s[i] = ss*invQ;                                     \
-                   t[i] = tt*invQ;                                     \
-                   u[i] = uu*invQ;                                     \
-                    COMPUTE_LAMBDA(lambda[i], invQ);                   \
-                   ffz += fdzdx;                                       \
-                   ffog += dfogdx;                                     \
-                   ss += dsdx;                                         \
-                   tt += dtdx;                                         \
-                   uu += dudx;                                         \
-                   vv += dvdx;                                         \
-                }                                                      \
-              }                                                                \
-              else {                                                   \
-                for (i=0;i<n;i++) {                                    \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;              \
-                   zspan[i] = FixedToDepth(ffz);                       \
-                   fogspan[i] = ffog;                                  \
-                   rgba[i][RCOMP] = FixedToInt(ffr);                   \
-                   rgba[i][GCOMP] = FixedToInt(ffg);                   \
-                   rgba[i][BCOMP] = FixedToInt(ffb);                   \
-                   rgba[i][ACOMP] = FixedToInt(ffa);                   \
-                   s[i] = ss*invQ;                                     \
-                   t[i] = tt*invQ;                                     \
-                   u[i] = uu*invQ;                                     \
-                    COMPUTE_LAMBDA(lambda[i], invQ);                   \
-                   ffz += fdzdx;                                       \
-                   ffog += dfogdx;                                     \
-                   ffr += fdrdx;                                       \
-                   ffg += fdgdx;                                       \
-                   ffb += fdbdx;                                       \
-                   ffa += fdadx;                                       \
-                   ss += dsdx;                                         \
-                   tt += dtdx;                                         \
-                   uu += dudx;                                         \
-                   vv += dvdx;                                         \
-                }                                                      \
-              }                                                                \
-             _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan,        \
-                                     s, t, u, lambda,                  \
-                                    rgba, NULL, GL_POLYGON );          \
-          }                                                            \
-       }
+   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
+   const GLboolean flatShade = (ctx->Light.ShadeModel==GL_FLAT);       \
+   GLfixed rFlat, gFlat, bFlat, aFlat;                                 \
+   GLfixed srFlat, sgFlat, sbFlat;                                     \
+   if (flatShade) {                                                    \
+      rFlat = IntToFixed(v2->color[RCOMP]);                            \
+      gFlat = IntToFixed(v2->color[GCOMP]);                            \
+      bFlat = IntToFixed(v2->color[BCOMP]);                            \
+      aFlat = IntToFixed(v2->color[ACOMP]);                            \
+      srFlat = IntToFixed(v2->specular[RCOMP]);                                \
+      sgFlat = IntToFixed(v2->specular[GCOMP]);                                \
+      sbFlat = IntToFixed(v2->specular[BCOMP]);                                \
+   }                                                                   \
+   span.texWidth[0] = (GLfloat) texImage->Width;                       \
+   span.texHeight[0] = (GLfloat) texImage->Height;                     \
+   (void) fixedToDepthShift;
+
+#define RENDER_SPAN( span )                                    \
+   if (flatShade) {                                            \
+      span.red = rFlat;    span.redStep = 0;                   \
+      span.green = gFlat;  span.greenStep = 0;                 \
+      span.blue = bFlat;   span.blueStep = 0;                  \
+      span.alpha = aFlat;  span.alphaStep = 0;                 \
+      span.specRed = srFlat;    span.specRedStep = 0;          \
+      span.specGreen = sgFlat;  span.specGreenStep = 0;                \
+      span.specBlue = sbFlat;   span.specBlueStep = 0;         \
+   }                                                           \
+   rasterize_span(ctx, &span);
 
 #include "s_tritemp.h"
 }
@@ -1893,18 +2027,15 @@ static void lambda_textured_triangle1( GLcontext *ctx,
 /*
  * Render a smooth-shaded, textured, RGBA triangle with separate specular
  * interpolation.
- * Interpolate S,T,U with perspective correction and compute lambda for
+ * Interpolate S,T,R with perspective correction and compute lambda for
  * each fragment.  Lambda is used to determine whether to use the
  * minification or magnification filter.  If minification and using
  * mipmaps, lambda is also used to select the texture level of detail.
  */
-static void lambda_textured_spec_triangle1( GLcontext *ctx,
-                                           const SWvertex *v0,
-                                           const SWvertex *v1,
-                                           const SWvertex *v2,
-                                            GLfloat s[MAX_WIDTH],
-                                            GLfloat t[MAX_WIDTH],
-                                            GLfloat u[MAX_WIDTH] )
+static void lambda_textured_spec_triangle( GLcontext *ctx,
+                                          const SWvertex *v0,
+                                          const SWvertex *v1,
+                                          const SWvertex *v2 )
 {
 #define INTERP_Z 1
 #define INTERP_FOG 1
@@ -1917,93 +2048,34 @@ static void lambda_textured_spec_triangle1( GLcontext *ctx,
 
 #define SETUP_CODE                                                     \
    const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;        \
-   const GLint baseLevel = obj->BaseLevel;                             \
-   const struct gl_texture_image *texImage = obj->Image[baseLevel];    \
-   const GLfloat twidth = (GLfloat) texImage->Width;                   \
-   const GLfloat theight = (GLfloat) texImage->Height;                 \
-   const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);      \
-   GLint r, g, b, a, sr, sg, sb;                                       \
-   if (flat_shade) {                                                   \
-      r = v2->color[RCOMP];                                            \
-      g = v2->color[GCOMP];                                            \
-      b = v2->color[BCOMP];                                            \
-      a = v2->color[ACOMP];                                            \
-      sr = v2->specular[RCOMP];                                                \
-      sg = v2->specular[GCOMP];                                                \
-      sb = v2->specular[BCOMP];                                                \
-   }
-
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-       {                                                               \
-          GLint i;                                                     \
-           const GLint n = RIGHT-LEFT;                                 \
-          GLdepth zspan[MAX_WIDTH];                                    \
-          GLfloat fogspan[MAX_WIDTH];                                  \
-          GLchan spec[MAX_WIDTH][4];                                   \
-           GLchan rgba[MAX_WIDTH][4];                                  \
-          GLfloat lambda[MAX_WIDTH];                                   \
-          if (n>0) {                                                   \
-             if (flat_shade) {                                         \
-                for (i=0;i<n;i++) {                                    \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;              \
-                   zspan[i] = FixedToDepth(ffz);                       \
-                   fogspan[i] = ffog;                                  \
-                   rgba[i][RCOMP] = r;                                 \
-                   rgba[i][GCOMP] = g;                                 \
-                   rgba[i][BCOMP] = b;                                 \
-                   rgba[i][ACOMP] = a;                                 \
-                   spec[i][RCOMP] = sr;                                \
-                   spec[i][GCOMP] = sg;                                \
-                   spec[i][BCOMP] = sb;                                \
-                   s[i] = ss*invQ;                                     \
-                   t[i] = tt*invQ;                                     \
-                   u[i] = uu*invQ;                                     \
-                    COMPUTE_LAMBDA(lambda[i], invQ);                   \
-                   ffog += dfogdx;                                     \
-                   ffz += fdzdx;                                       \
-                   ss += dsdx;                                         \
-                   tt += dtdx;                                         \
-                   uu += dudx;                                         \
-                   vv += dvdx;                                         \
-                }                                                      \
-              }                                                                \
-              else {                                                   \
-                for (i=0;i<n;i++) {                                    \
-                   GLdouble invQ = vv ? (1.0 / vv) : 1.0;              \
-                   zspan[i] = FixedToDepth(ffz);                       \
-                   fogspan[i] = ffog;                                  \
-                   rgba[i][RCOMP] = FixedToInt(ffr);                   \
-                   rgba[i][GCOMP] = FixedToInt(ffg);                   \
-                   rgba[i][BCOMP] = FixedToInt(ffb);                   \
-                   rgba[i][ACOMP] = FixedToInt(ffa);                   \
-                   spec[i][RCOMP] = FixedToInt(ffsr);                  \
-                   spec[i][GCOMP] = FixedToInt(ffsg);                  \
-                   spec[i][BCOMP] = FixedToInt(ffsb);                  \
-                   s[i] = ss*invQ;                                     \
-                   t[i] = tt*invQ;                                     \
-                   u[i] = uu*invQ;                                     \
-                    COMPUTE_LAMBDA(lambda[i], invQ);                   \
-                   ffog += dfogdx;                                     \
-                   ffz += fdzdx;                                       \
-                   ffr += fdrdx;                                       \
-                   ffg += fdgdx;                                       \
-                   ffb += fdbdx;                                       \
-                   ffa += fdadx;                                       \
-                   ffsr += fdsrdx;                                     \
-                   ffsg += fdsgdx;                                     \
-                   ffsb += fdsbdx;                                     \
-                   ss += dsdx;                                         \
-                   tt += dtdx;                                         \
-                   uu += dudx;                                         \
-                   vv += dvdx;                                         \
-                }                                                      \
-              }                                                                \
-             _mesa_write_texture_span( ctx, n, LEFT, Y, zspan,         \
-                                     fogspan, s, t, u, lambda,         \
-                                    rgba, (CONST GLchan (*)[4]) spec,  \
-                                     GL_POLYGON );                     \
-          }                                                            \
-       }
+   const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
+   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);     \
+   GLfixed rFlat, gFlat, bFlat, aFlat;                                 \
+   GLfixed srFlat, sgFlat, sbFlat;                                     \
+   if (flatShade) {                                                    \
+      rFlat = IntToFixed(v2->color[RCOMP]);                            \
+      gFlat = IntToFixed(v2->color[GCOMP]);                            \
+      bFlat = IntToFixed(v2->color[BCOMP]);                            \
+      aFlat = IntToFixed(v2->color[ACOMP]);                            \
+      srFlat = IntToFixed(v2->specular[RCOMP]);                                \
+      sgFlat = IntToFixed(v2->specular[GCOMP]);                                \
+      sbFlat = IntToFixed(v2->specular[BCOMP]);                                \
+   }                                                                   \
+   span.texWidth[0] = (GLfloat) texImage->Width;                       \
+   span.texHeight[0] = (GLfloat) texImage->Height;                     \
+   (void) fixedToDepthShift;
+
+#define RENDER_SPAN( span )                                    \
+   if (flatShade) {                                            \
+      span.red = rFlat;    span.redStep = 0;                   \
+      span.green = gFlat;  span.greenStep = 0;                 \
+      span.blue = bFlat;   span.blueStep = 0;                  \
+      span.alpha = aFlat;  span.alphaStep = 0;                 \
+      span.specRed = srFlat;    span.specRedStep = 0;          \
+      span.specGreen = sgFlat;  span.specGreenStep = 0;                \
+      span.specBlue = sbFlat;   span.specBlueStep = 0;         \
+   }                                                           \
+   rasterize_span(ctx, &span);
 
 #include "s_tritemp.h"
 }
@@ -2011,182 +2083,69 @@ static void lambda_textured_spec_triangle1( GLcontext *ctx,
 
 /*
  * This is the big one!
- * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
+ * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates
+ * with lambda (LOD).
  * Yup, it's slow.
  */
 static void
-lambda_multitextured_triangle1( GLcontext *ctx,
-                               const SWvertex *v0,
-                               const SWvertex *v1,
-                               const SWvertex *v2,
-                               GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH],
-                               GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH],
-                               GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH])
+lambda_multitextured_triangle( GLcontext *ctx,
+                               const SWvertex *v0,
+                               const SWvertex *v1,
+                               const SWvertex *v2 )
 {
+
 #define INTERP_Z 1
 #define INTERP_FOG 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 #define INTERP_RGB 1
 #define INTERP_ALPHA 1
+#define INTERP_SPEC 1
 #define INTERP_MULTITEX 1
-#define INTERP_MULTILAMBDA 1
+#define INTERP_LAMBDA 1
 
 #define SETUP_CODE                                                     \
-   GLchan rgba[MAX_WIDTH][4];                                          \
-   const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);      \
-   GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS];      \
-   GLint r, g, b, a;                                                   \
-   if (flat_shade) {                                                   \
-      r = v2->color[0];                                                        \
-      g = v2->color[1];                                                        \
-      b = v2->color[2];                                                        \
-      a = v2->color[3];                                                        \
+   const GLboolean flatShade = (ctx->Light.ShadeModel == GL_FLAT);     \
+   GLfixed rFlat, gFlat, bFlat, aFlat;                                 \
+   GLfixed srFlat, sgFlat, sbFlat;                                     \
+   GLuint u;                                                           \
+   if (flatShade) {                                                    \
+      rFlat = IntToFixed(v2->color[RCOMP]);                            \
+      gFlat = IntToFixed(v2->color[GCOMP]);                            \
+      bFlat = IntToFixed(v2->color[BCOMP]);                            \
+      aFlat = IntToFixed(v2->color[ACOMP]);                            \
+      srFlat = IntToFixed(v2->specular[RCOMP]);                                \
+      sgFlat = IntToFixed(v2->specular[GCOMP]);                                \
+      sbFlat = IntToFixed(v2->specular[BCOMP]);                                \
    }                                                                   \
-   {                                                                   \
-      GLuint unit;                                                     \
-      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {      \
-         if (ctx->Texture.Unit[unit]._ReallyEnabled) {                 \
-            const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \
-            const GLint baseLevel = obj->BaseLevel;                    \
-            const struct gl_texture_image *texImage = obj->Image[baseLevel];\
-            twidth[unit] = (GLfloat) texImage->Width;                  \
-            theight[unit] = (GLfloat) texImage->Height;                        \
-         }                                                             \
-      }                                                                        \
-   }
-
-#define INNER_LOOP( LEFT, RIGHT, Y )                                   \
-   {                                                                   \
-      GLint i;                                                         \
-      const GLint n = RIGHT-LEFT;                                      \
-      GLdepth zspan[MAX_WIDTH];                                                \
-      GLfloat fogspan[MAX_WIDTH];                                      \
-      GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH];                    \
-      if (n > 0) {                                                     \
-         if (flat_shade) {                                             \
-           for (i=0;i<n;i++) {                                         \
-               GLuint unit;                                            \
-              zspan[i] = FixedToDepth(ffz);                            \
-              fogspan[i] = ffog;                                       \
-               ffog += dfogdx;                                         \
-              ffz += fdzdx;                                            \
-              rgba[i][RCOMP] = r;                                      \
-              rgba[i][GCOMP] = g;                                      \
-              rgba[i][BCOMP] = b;                                      \
-              rgba[i][ACOMP] = a;                                      \
-              for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\
-                  if (ctx->Texture.Unit[unit]._ReallyEnabled) {                \
-                    GLdouble invQ = 1.0 / vv[unit];                    \
-                    s[unit][i] = ss[unit] * invQ;                      \
-                    t[unit][i] = tt[unit] * invQ;                      \
-                    u[unit][i] = uu[unit] * invQ;                      \
-                     COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit); \
-                    ss[unit] += dsdx[unit];                            \
-                    tt[unit] += dtdx[unit];                            \
-                    uu[unit] += dudx[unit];                            \
-                    vv[unit] += dvdx[unit];                            \
-                 }                                                     \
-              }                                                        \
-           }                                                           \
-        }                                                              \
-        else { /* smooth shade */                                      \
-           for (i=0;i<n;i++) {                                         \
-               GLuint unit;                                            \
-              zspan[i] = FixedToDepth(ffz);                            \
-              fogspan[i] = ffog;                                       \
-              ffz += fdzdx;                                            \
-              ffog += dfogdx;                                          \
-              rgba[i][RCOMP] = FixedToInt(ffr);                        \
-              rgba[i][GCOMP] = FixedToInt(ffg);                        \
-              rgba[i][BCOMP] = FixedToInt(ffb);                        \
-              rgba[i][ACOMP] = FixedToInt(ffa);                        \
-              ffr += fdrdx;                                            \
-              ffg += fdgdx;                                            \
-              ffb += fdbdx;                                            \
-              ffa += fdadx;                                            \
-               for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\
-                 if (ctx->Texture.Unit[unit]._ReallyEnabled) {         \
-                    GLdouble invQ = 1.0 / vv[unit];                    \
-                    s[unit][i] = ss[unit] * invQ;                      \
-                    t[unit][i] = tt[unit] * invQ;                      \
-                    u[unit][i] = uu[unit] * invQ;                      \
-                     COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit);  \
-                    ss[unit] += dsdx[unit];                            \
-                    tt[unit] += dtdx[unit];                            \
-                    uu[unit] += dudx[unit];                            \
-                    vv[unit] += dvdx[unit];                            \
-                 }                                                     \
-              }                                                        \
-           }                                                           \
-        }                                                              \
-        _mesa_write_multitexture_span(ctx, n, LEFT, Y, zspan, fogspan, \
-                                      (const GLfloat (*)[MAX_WIDTH]) s,\
-                                       (const GLfloat (*)[MAX_WIDTH]) t,\
-                                       (const GLfloat (*)[MAX_WIDTH]) u,\
-                                       (GLfloat (*)[MAX_WIDTH]) lambda,        \
-                                       rgba, NULL, GL_POLYGON );       \
+   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {                  \
+      if (ctx->Texture.Unit[u]._ReallyEnabled) {                       \
+         const struct gl_texture_object *texObj;                       \
+         const struct gl_texture_image *texImage;                      \
+         texObj = ctx->Texture.Unit[u]._Current;                       \
+         texImage = texObj->Image[texObj->BaseLevel];                  \
+         span.texWidth[u] = (GLfloat) texImage->Width;                 \
+         span.texHeight[u] = (GLfloat) texImage->Height;               \
       }                                                                        \
-   }
+   }                                                                   \
+   (void) fixedToDepthShift;
+
+#define RENDER_SPAN( span )                                    \
+   if (flatShade) {                                            \
+      span.red = rFlat;    span.redStep = 0;                   \
+      span.green = gFlat;  span.greenStep = 0;                 \
+      span.blue = bFlat;   span.blueStep = 0;                  \
+      span.alpha = aFlat;  span.alphaStep = 0;                 \
+      span.specRed = srFlat;    span.specRedStep = 0;          \
+      span.specGreen = sgFlat;  span.specGreenStep = 0;                \
+      span.specBlue = sbFlat;   span.specBlueStep = 0;         \
+   }                                                           \
+   rasterize_span(ctx, &span);
 
 #include "s_tritemp.h"
-}
-
-
-/*
- * These wrappers are needed to deal with the 32KB / stack frame limit
- * on Mac / PowerPC systems.
- */
-
-static void general_textured_spec_triangle(GLcontext *ctx,
-                                          const SWvertex *v0,
-                                          const SWvertex *v1,
-                                          const SWvertex *v2 )
-{
-   GLdepth zspan[MAX_WIDTH];
-   GLfloat fogspan[MAX_WIDTH];
-   GLchan rgba[MAX_WIDTH][4], spec[MAX_WIDTH][4];
-   general_textured_spec_triangle1(ctx,v0,v1,v2,zspan,fogspan,rgba,spec);
-}
-
-static void lambda_textured_triangle( GLcontext *ctx,
-                                     const SWvertex *v0,
-                                     const SWvertex *v1,
-                                     const SWvertex *v2 )
-{
-   GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];
-   lambda_textured_triangle1(ctx,v0,v1,v2,s,t,u);
-}
-
-static void lambda_textured_spec_triangle( GLcontext *ctx,
-                                          const SWvertex *v0,
-                                          const SWvertex *v1,
-                                          const SWvertex *v2 )
-{
-   GLfloat s[MAX_WIDTH];
-   GLfloat t[MAX_WIDTH];
-   GLfloat u[MAX_WIDTH];
-   lambda_textured_spec_triangle1(ctx,v0,v1,v2,s,t,u);
-}
-
-
-static void lambda_multitextured_triangle( GLcontext *ctx,
-                                          const SWvertex *v0,
-                                          const SWvertex *v1,
-                                          const SWvertex *v2 )
-{
-
-   GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH];
-   GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH];
-   DEFMARRAY(GLfloat,u,MAX_TEXTURE_UNITS,MAX_WIDTH);
-   CHECKARRAY(u,return);
-
-   lambda_multitextured_triangle1(ctx,v0,v1,v2,s,t,u);
 
-   UNDEFARRAY(u);
 }
 
 
-
 static void occlusion_zless_triangle( GLcontext *ctx,
                                      const SWvertex *v0,
                                      const SWvertex *v1,
@@ -2199,19 +2158,18 @@ static void occlusion_zless_triangle( GLcontext *ctx,
 #define DO_OCCLUSION_TEST
 #define INTERP_Z 1
 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
-#define INNER_LOOP( LEFT, RIGHT, Y )           \
-   {                                           \
-      GLint i;                                  \
-      const GLint len = RIGHT-LEFT;            \
-      for (i=0;i<len;i++) {                    \
-        GLdepth z = FixedToDepth(ffz);         \
-        if (z < zRow[i]) {                     \
-           ctx->OcclusionResult = GL_TRUE;     \
-           return;                             \
-        }                                      \
-        ffz += fdzdx;                          \
-      }                                                \
+
+#define RENDER_SPAN( span )                            \
+   GLuint i;                                           \
+   for (i = 0; i < span.count; i++) {                  \
+      GLdepth z = FixedToDepth(span.z);                        \
+      if (z < zRow[i]) {                               \
+         ctx->OcclusionResult = GL_TRUE;               \
+         return;                                       \
+      }                                                        \
+      span.z += span.zStep;                            \
    }
+
 #include "s_tritemp.h"
 }
 
@@ -2335,14 +2293,14 @@ _swrast_choose_triangle( GLcontext *ctx )
             && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
            if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
               if (minFilter == GL_NEAREST
-                  && format == GL_RGB
+                  && format == MESA_FORMAT_RGB
                   && (envMode == GL_REPLACE || envMode == GL_DECAL)
-                  && ((swrast->_RasterMask == DEPTH_BIT
+                  && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
                        && ctx->Depth.Func == GL_LESS
                        && ctx->Depth.Mask == GL_TRUE)
-                      || swrast->_RasterMask == 0)
+                      || swrast->_RasterMask == TEXTURE_BIT)
                   && ctx->Polygon.StippleFlag == GL_FALSE) {
-                 if (swrast->_RasterMask==DEPTH_BIT) {
+                 if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
                     USE(simple_z_textured_triangle);
                  }
                  else {
diff --git a/src/mesa/swrast/s_trispan.h b/src/mesa/swrast/s_trispan.h
new file mode 100644 (file)
index 0000000..cd577f5
--- /dev/null
@@ -0,0 +1,79 @@
+/* $Id: s_trispan.h,v 1.1 2001/05/14 16:23:04 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef S_TRISPAN_H
+#define S_TRISPAN_H
+
+
+/*
+ * The triangle_span structure is used by the triangle template code in
+ * s_tritemp.h.  It describes how colors, Z, texcoords, etc are to be
+ * interpolated across each scanline of triangle.
+ * With this structure it's easy to hand-off span rasterization to a
+ * subroutine instead of doing it all inline like we used to do.
+ * It also cleans up the local variable namespace a great deal.
+ *
+ * It would be interesting to experiment with multiprocessor rasterization
+ * with this structure.  The triangle rasterizer could simply emit a
+ * stream of these structures which would be consumed by one or more
+ * span-processing threads which could run in parallel.
+ */
+
+
+#define SPAN_RGBA         0x01
+#define SPAN_SPEC         0x02
+#define SPAN_INDEX        0x04
+#define SPAN_Z            0x08
+#define SPAN_FOG          0x10
+#define SPAN_TEXTURE      0x20
+#define SPAN_INT_TEXTURE  0x40
+#define SPAN_LAMBDA       0x80
+
+
+struct triangle_span {
+   GLint x, y;
+   GLuint count;
+   GLuint activeMask;  /* OR of the SPAN_* flags */
+   GLfixed red, redStep;
+   GLfixed green, greenStep;
+   GLfixed blue, blueStep;
+   GLfixed alpha, alphaStep;
+   GLfixed specRed, specRedStep;
+   GLfixed specGreen, specGreenStep;
+   GLfixed specBlue, specBlueStep;
+   GLfixed index, indexStep;
+   GLfixed z, zStep;
+   GLfloat fog, fogStep;
+   GLfloat tex[MAX_TEXTURE_UNITS][4], texStep[MAX_TEXTURE_UNITS][4];
+   GLfixed intTex[2], intTexStep[2];
+   /* Needed for texture lambda (LOD) computation */
+   GLfloat rho[MAX_TEXTURE_UNITS];
+   GLfloat texWidth[MAX_TEXTURE_UNITS], texHeight[MAX_TEXTURE_UNITS];
+};
+
+
+#endif /* S_TRISPAN_H */
index 3bdb1537a0102f1b457ac997913b389f24655786..09e122350673ba63cbfbe2d1aad5d4ff30ef2576 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_tritemp.h,v 1.15 2001/05/03 22:13:32 brianp Exp $ */
+/* $Id: s_tritemp.h,v 1.16 2001/05/14 16:23:04 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -43,9 +43,7 @@
  *    INTERP_TEX      - if defined, interpolate set 0 float STRQ texcoords
  *                         NOTE:  OpenGL STRQ = Mesa STUV (R was taken for red)
  *    INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords
- *    INTERP_LAMBDA   - if defined, the lambda value is computed at every
- *                         pixel, to apply MIPMAPPING, and min/maxification
- *    INTERP_MULTILAMBDA - like above but for multitexturing, i.e.
+ *    INTERP_LAMBDA   - if defined, compute lambda value (for mipmapping)
  *                         a lambda value for every texture unit
  *
  * When one can directly address pixels in the color buffer the following
  *    SETUP_CODE    - code which is to be executed once per triangle
  *
  * The following macro MUST be defined:
- *    INNER_LOOP(LEFT,RIGHT,Y) - code to write a span of pixels.
- *        Something like:
- *
- *                    for (x=LEFT; x<RIGHT;x++) {
- *                       put_pixel(x,Y);
- *                       // increment fixed point interpolants
- *                    }
+ *    RENDER_SPAN(span) - code to write a span of pixels.
  *
  * This code was designed for the origin to be in the lower-left corner.
  *
  * Inspired by triangle rasterizer code written by Allen Akin.  Thanks Allen!
  */
 
-
 /*void triangle( GLcontext *ctx, SWvertex *v0, SWvertex *v1, SWvertex *v2 )*/
 {
    typedef struct {
    float bf = SWRAST_CONTEXT(ctx)->_backface_sign;
    GLboolean tiny;
 
+   struct triangle_span span;
+
+#ifdef INTERP_Z
+   (void) fixedToDepthShift;
+#endif
+
    /* find the order of the 3 vertices along the Y axis */
    {
       GLfloat y0 = v0->win[1];
    {
       GLint ltor;              /* true if scanning left-to-right */
 #ifdef INTERP_Z
-      GLfloat dzdx, dzdy;      GLfixed fdzdx;
+      GLfloat dzdx, dzdy;
 #endif
 #ifdef INTERP_FOG
-      GLfloat dfogdx, dfogdy;
+      GLfloat dfogdy;
 #endif
 #ifdef INTERP_RGB
-      GLfloat drdx, drdy;      GLfixed fdrdx;
-      GLfloat dgdx, dgdy;      GLfixed fdgdx;
-      GLfloat dbdx, dbdy;      GLfixed fdbdx;
-#endif
-#ifdef INTERP_SPEC
-      GLfloat dsrdx, dsrdy;    GLfixed fdsrdx;
-      GLfloat dsgdx, dsgdy;    GLfixed fdsgdx;
-      GLfloat dsbdx, dsbdy;    GLfixed fdsbdx;
+      GLfloat drdx, drdy;
+      GLfloat dgdx, dgdy;
+      GLfloat dbdx, dbdy;
 #endif
 #ifdef INTERP_ALPHA
-      GLfloat dadx, dady;      GLfixed fdadx;
+      GLfloat dadx, dady;
+#endif
+#ifdef INTERP_SPEC
+      GLfloat dsrdx, dsrdy;
+      GLfloat dsgdx, dsgdy;
+      GLfloat dsbdx, dsbdy;
 #endif
 #ifdef INTERP_INDEX
-      GLfloat didx, didy;      GLfixed fdidx;
+      GLfloat didx, didy;
 #endif
 #ifdef INTERP_INT_TEX
-      GLfloat dsdx, dsdy;      GLfixed fdsdx;
-      GLfloat dtdx, dtdy;      GLfixed fdtdx;
-#endif
-#ifdef INTERP_TEX
       GLfloat dsdx, dsdy;
       GLfloat dtdx, dtdy;
-      GLfloat dudx, dudy;
-      GLfloat dvdx, dvdy;
+#endif
+#ifdef INTERP_TEX
+      GLfloat dsdy;
+      GLfloat dtdy;
+      GLfloat dudy;
+      GLfloat dvdy;
 #endif
 #ifdef INTERP_MULTITEX
-      GLfloat dsdx[MAX_TEXTURE_UNITS], dsdy[MAX_TEXTURE_UNITS];
-      GLfloat dtdx[MAX_TEXTURE_UNITS], dtdy[MAX_TEXTURE_UNITS];
-      GLfloat dudx[MAX_TEXTURE_UNITS], dudy[MAX_TEXTURE_UNITS];
-      GLfloat dvdx[MAX_TEXTURE_UNITS], dvdy[MAX_TEXTURE_UNITS];
+      GLfloat dsdy[MAX_TEXTURE_UNITS];
+      GLfloat dtdy[MAX_TEXTURE_UNITS];
+      GLfloat dudy[MAX_TEXTURE_UNITS];
+      GLfloat dvdy[MAX_TEXTURE_UNITS];
 #endif
 
-#ifdef INTERP_LAMBDA
-#ifndef INTERP_TEX
+#if defined(INTERP_LAMBDA) && !defined(INTERP_TEX) && !defined(INTERP_MULTITEX)
 #error "Mipmapping without texturing doesn't make sense."
 #endif
-      GLfloat lambda_nominator;
-#endif /* INTERP_LAMBDA */
-
-#ifdef INTERP_MULTILAMBDA
-#ifndef INTERP_MULTITEX
-#error "Multi-Mipmapping without multi-texturing doesn't make sense."
-#endif
-      GLfloat lambda_nominator[MAX_TEXTURE_UNITS];
-#endif /* INTERP_MULTILAMBDA */
-
 
       /*
        * Execute user-supplied setup code
 
       ltor = (oneOverArea < 0.0F);
 
+      span.activeMask = 0;
+
       /* compute d?/dx and d?/dy derivatives */
 #ifdef INTERP_Z
+      span.activeMask |= SPAN_Z;
       {
          GLfloat eMaj_dz, eBot_dz;
          eMaj_dz = vMax->win[2] - vMin->win[2];
             dzdy = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
          }
          if (depthBits <= 16)
-            fdzdx = SignedFloatToFixed(dzdx);
+            span.zStep = SignedFloatToFixed(dzdx);
          else
-            fdzdx = (GLint) dzdx;
+            span.zStep = (GLint) dzdx;
       }
 #endif
 #ifdef INTERP_FOG
+      span.activeMask |= SPAN_FOG;
       {
          const GLfloat eMaj_dfog = vMax->fog - vMin->fog;
          const GLfloat eBot_dfog = vMid->fog - vMin->fog;
-         dfogdx = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog);
+         span.fogStep = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog);
          dfogdy = oneOverArea * (eMaj.dx * eBot_dfog - eMaj_dfog * eBot.dx);
       }
 #endif
 #ifdef INTERP_RGB
+      span.activeMask |= SPAN_RGBA;
       if (tiny) {
          /* This is kind of a hack to eliminate RGB color over/underflow
           * problems when rendering very tiny triangles.  We're not doing
           * anything with alpha or specular color at this time.
           */
-         drdx = drdy = 0.0;  fdrdx = 0;
-         dgdx = dgdy = 0.0;  fdgdx = 0;
-         dbdx = dbdy = 0.0;  fdbdx = 0;
+         drdx = drdy = 0.0;  span.redStep = 0;
+         dgdx = dgdy = 0.0;  span.greenStep = 0;
+         dbdx = dbdy = 0.0;  span.blueStep = 0;
       }
       else {
          GLfloat eMaj_dr, eBot_dr;
          eMaj_dr = (GLint) vMax->color[0] - (GLint) vMin->color[0];
          eBot_dr = (GLint) vMid->color[0] - (GLint) vMin->color[0];
          drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
-         fdrdx = SignedFloatToFixed(drdx);
+         span.redStep = SignedFloatToFixed(drdx);
          drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
          eMaj_dg = (GLint) vMax->color[1] - (GLint) vMin->color[1];
         eBot_dg = (GLint) vMid->color[1] - (GLint) vMin->color[1];
          dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
-         fdgdx = SignedFloatToFixed(dgdx);
+         span.greenStep = SignedFloatToFixed(dgdx);
          dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
          eMaj_db = (GLint) vMax->color[2] - (GLint) vMin->color[2];
          eBot_db = (GLint) vMid->color[2] - (GLint) vMin->color[2];
          dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
-         fdbdx = SignedFloatToFixed(dbdx);
+         span.blueStep = SignedFloatToFixed(dbdx);
         dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
       }
 #endif
+#ifdef INTERP_ALPHA
+      {
+         GLfloat eMaj_da, eBot_da;
+         eMaj_da = (GLint) vMax->color[3] - (GLint) vMin->color[3];
+         eBot_da = (GLint) vMid->color[3] - (GLint) vMin->color[3];
+         dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
+         span.alphaStep = SignedFloatToFixed(dadx);
+         dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
+      }
+#endif
 #ifdef INTERP_SPEC
+      span.activeMask |= SPAN_SPEC;
       {
          GLfloat eMaj_dsr, eBot_dsr;
          eMaj_dsr = (GLint) vMax->specular[0] - (GLint) vMin->specular[0];
          eBot_dsr = (GLint) vMid->specular[0] - (GLint) vMin->specular[0];
          dsrdx = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
-         fdsrdx = SignedFloatToFixed(dsrdx);
+         span.specRedStep = SignedFloatToFixed(dsrdx);
          dsrdy = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
       }
       {
          eMaj_dsg = (GLint) vMax->specular[1] - (GLint) vMin->specular[1];
         eBot_dsg = (GLint) vMid->specular[1] - (GLint) vMin->specular[1];
          dsgdx = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
-         fdsgdx = SignedFloatToFixed(dsgdx);
+         span.specGreenStep = SignedFloatToFixed(dsgdx);
          dsgdy = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
       }
       {
          eMaj_dsb = (GLint) vMax->specular[2] - (GLint) vMin->specular[2];
          eBot_dsb = (GLint) vMid->specular[2] - (GLint) vMin->specular[2];
          dsbdx = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
-         fdsbdx = SignedFloatToFixed(dsbdx);
+         span.specBlueStep = SignedFloatToFixed(dsbdx);
         dsbdy = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
       }
 #endif
-#ifdef INTERP_ALPHA
-      {
-         GLfloat eMaj_da, eBot_da;
-         eMaj_da = (GLint) vMax->color[3] - (GLint) vMin->color[3];
-         eBot_da = (GLint) vMid->color[3] - (GLint) vMin->color[3];
-         dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
-         fdadx = SignedFloatToFixed(dadx);
-         dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
-      }
-#endif
 #ifdef INTERP_INDEX
+      span.activeMask |= SPAN_INDEX;
       {
          GLfloat eMaj_di, eBot_di;
          eMaj_di = (GLint) vMax->index - (GLint) vMin->index;
          eBot_di = (GLint) vMid->index - (GLint) vMin->index;
          didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
-         fdidx = SignedFloatToFixed(didx);
+         span.indexStep = SignedFloatToFixed(didx);
          didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
       }
 #endif
 #ifdef INTERP_INT_TEX
+      span.activeMask |= SPAN_INT_TEXTURE;
       {
          GLfloat eMaj_ds, eBot_ds;
          eMaj_ds = (vMax->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
          eBot_ds = (vMid->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
          dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
-         fdsdx = SignedFloatToFixed(dsdx);
+         span.intTexStep[0] = SignedFloatToFixed(dsdx);
          dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
       }
       {
          eMaj_dt = (vMax->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
          eBot_dt = (vMid->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
          dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
-         fdtdx = SignedFloatToFixed(dtdx);
+         span.intTexStep[1] = SignedFloatToFixed(dtdx);
          dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
       }
 
 #endif
+
 #ifdef INTERP_TEX
+      span.activeMask |= SPAN_TEXTURE;
       {
          GLfloat wMax = vMax->win[3];
          GLfloat wMin = vMin->win[3];
 
          eMaj_ds = vMax->texcoord[0][0] * wMax - vMin->texcoord[0][0] * wMin;
          eBot_ds = vMid->texcoord[0][0] * wMid - vMin->texcoord[0][0] * wMin;
-         dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
+         span.texStep[0][0] = oneOverArea * (eMaj_ds * eBot.dy
+                                             - eMaj.dy * eBot_ds);
          dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
 
         eMaj_dt = vMax->texcoord[0][1] * wMax - vMin->texcoord[0][1] * wMin;
         eBot_dt = vMid->texcoord[0][1] * wMid - vMin->texcoord[0][1] * wMin;
-        dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
+        span.texStep[0][1] = oneOverArea * (eMaj_dt * eBot.dy
+                                             - eMaj.dy * eBot_dt);
         dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
 
         eMaj_du = vMax->texcoord[0][2] * wMax - vMin->texcoord[0][2] * wMin;
         eBot_du = vMid->texcoord[0][2] * wMid - vMin->texcoord[0][2] * wMin;
-        dudx = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
+        span.texStep[0][2] = oneOverArea * (eMaj_du * eBot.dy
+                                             - eMaj.dy * eBot_du);
         dudy = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
 
         eMaj_dv = vMax->texcoord[0][3] * wMax - vMin->texcoord[0][3] * wMin;
         eBot_dv = vMid->texcoord[0][3] * wMid - vMin->texcoord[0][3] * wMin;
-        dvdx = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
+        span.texStep[0][3] = oneOverArea * (eMaj_dv * eBot.dy
+                                             - eMaj.dy * eBot_dv);
         dvdy = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
       }
+#  ifdef INTERP_LAMBDA
+      {
+         GLfloat dudx = span.texStep[0][0] * span.texWidth[0];
+         GLfloat dudy = dsdy * span.texWidth[0];
+         GLfloat dvdx = span.texStep[0][1] * span.texHeight[0];
+         GLfloat dvdy = dtdy * span.texHeight[0];
+         GLfloat r1 = dudx * dudx + dudy * dudy;
+         GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
+         span.rho[0] = r1 + r2; /* was rho2 = MAX2(r1,r2) */
+         span.activeMask |= SPAN_LAMBDA;
+      }
+#  endif
 #endif
+
 #ifdef INTERP_MULTITEX
+      span.activeMask |= SPAN_TEXTURE;
+#  ifdef INTERP_LAMBDA
+      span.activeMask |= SPAN_LAMBDA;
+#  endif
       {
          GLfloat wMax = vMax->win[3];
          GLfloat wMin = vMin->win[3];
                        - vMin->texcoord[u][0] * wMin;
                eBot_ds = vMid->texcoord[u][0] * wMid
                        - vMin->texcoord[u][0] * wMin;
-               dsdx[u] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
+               span.texStep[u][0] = oneOverArea * (eMaj_ds * eBot.dy
+                                                   - eMaj.dy * eBot_ds);
                dsdy[u] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
 
               eMaj_dt = vMax->texcoord[u][1] * wMax
                       - vMin->texcoord[u][1] * wMin;
               eBot_dt = vMid->texcoord[u][1] * wMid
                       - vMin->texcoord[u][1] * wMin;
-              dtdx[u] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
+              span.texStep[u][1] = oneOverArea * (eMaj_dt * eBot.dy
+                                                   - eMaj.dy * eBot_dt);
               dtdy[u] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
 
               eMaj_du = vMax->texcoord[u][2] * wMax
                        - vMin->texcoord[u][2] * wMin;
               eBot_du = vMid->texcoord[u][2] * wMid
                        - vMin->texcoord[u][2] * wMin;
-              dudx[u] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
+              span.texStep[u][2] = oneOverArea * (eMaj_du * eBot.dy
+                                                   - eMaj.dy * eBot_du);
               dudy[u] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
 
               eMaj_dv = vMax->texcoord[u][3] * wMax
                        - vMin->texcoord[u][3] * wMin;
               eBot_dv = vMid->texcoord[u][3] * wMid
                        - vMin->texcoord[u][3] * wMin;
-              dvdx[u] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
+              span.texStep[u][3] = oneOverArea * (eMaj_dv * eBot.dy
+                                                   - eMaj.dy * eBot_dv);
               dvdy[u] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
+#  ifdef INTERP_LAMBDA
+               {
+                  GLfloat dudx = span.texStep[u][0] * span.texWidth[u];
+                  GLfloat dudy = dsdy[u] * span.texWidth[u];
+                  GLfloat dvdx = span.texStep[u][1] * span.texHeight[u];
+                  GLfloat dvdy = dtdy[u] * span.texHeight[u];
+                  GLfloat r1 = dudx * dudx + dudy * dudy;
+                  GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
+                  span.rho[u] = r1 + r2; /* was rho2 = MAX2(r1,r2) */
+               }
+#  endif
             }
          }
       }
       {
          int subTriangle;
          GLfixed fx;
-         GLfixed fxLeftEdge=0, fxRightEdge=0, fdxLeftEdge=0, fdxRightEdge=0;
+         GLfixed fxLeftEdge, fxRightEdge, fdxLeftEdge, fdxRightEdge;
          GLfixed fdxOuter;
          int idxOuter;
          float dxOuter;
-         GLfixed fError=0, fdError=0;
+         GLfixed fError, fdError;
          float adjx, adjy;
          GLfixed fy;
-         int iy=0;
 #ifdef PIXEL_ADDRESS
-         PIXEL_TYPE *pRow=NULL;
-         int dPRowOuter=0, dPRowInner=0;  /* offset in bytes */
+         PIXEL_TYPE *pRow;
+         int dPRowOuter, dPRowInner;  /* offset in bytes */
 #endif
 #ifdef INTERP_Z
 #  ifdef DEPTH_TYPE
-         DEPTH_TYPE *zRow=NULL;
-         int dZRowOuter=0, dZRowInner=0;  /* offset in bytes */
+         DEPTH_TYPE *zRow;
+         int dZRowOuter, dZRowInner;  /* offset in bytes */
 #  endif
-         GLfixed fz=0, fdzOuter=0, fdzInner;
+         GLfixed fz, fdzOuter, fdzInner;
 #endif
 #ifdef INTERP_FOG
          GLfloat fogLeft, dfogOuter, dfogInner;
 #endif
 #ifdef INTERP_RGB
-         GLfixed fr=0, fdrOuter=0, fdrInner;
-         GLfixed fg=0, fdgOuter=0, fdgInner;
-         GLfixed fb=0, fdbOuter=0, fdbInner;
+         GLfixed fr, fdrOuter, fdrInner;
+         GLfixed fg, fdgOuter, fdgInner;
+         GLfixed fb, fdbOuter, fdbInner;
+#endif
+#ifdef INTERP_ALPHA
+         GLfixed fa=0, fdaOuter=0, fdaInner;
 #endif
 #ifdef INTERP_SPEC
          GLfixed fsr=0, fdsrOuter=0, fdsrInner;
          GLfixed fsg=0, fdsgOuter=0, fdsgInner;
          GLfixed fsb=0, fdsbOuter=0, fdsbInner;
 #endif
-#ifdef INTERP_ALPHA
-         GLfixed fa=0, fdaOuter=0, fdaInner;
-#endif
 #ifdef INTERP_INDEX
          GLfixed fi=0, fdiOuter=0, fdiInner;
 #endif
                (void) dxOuter;
 
                fy = eLeft->fsy;
-               iy = FixedToInt(fy);
+               span.y = FixedToInt(fy);
 
                adjx = (float)(fx - eLeft->fx0);  /* SCALED! */
                adjy = eLeft->adjy;              /* SCALED! */
 
 #ifdef PIXEL_ADDRESS
                {
-                  pRow = PIXEL_ADDRESS( FixedToInt(fxLeftEdge), iy );
+                  pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
                   dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
                   /* negative because Y=0 at bottom and increases upward */
                }
                   }
                   else {
                      /* interpolate depth values exactly */
-                     fz = (GLint) (z0 + dzdx*FixedToFloat(adjx) + dzdy*FixedToFloat(adjy));
+                     fz = (GLint) (z0 + dzdx * FixedToFloat(adjx)
+                                   + dzdy * FixedToFloat(adjy));
                      fdzOuter = (GLint) (dzdy + dxOuter * dzdx);
                   }
 #  ifdef DEPTH_TYPE
-                  zRow = (DEPTH_TYPE *) _mesa_zbuffer_address(ctx, FixedToInt(fxLeftEdge), iy);
+                  zRow = (DEPTH_TYPE *)
+                    _mesa_zbuffer_address(ctx, FixedToInt(fxLeftEdge), span.y);
                   dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
 #  endif
                }
 #endif
 #ifdef INTERP_FOG
-               fogLeft = vLower->fog + (dfogdx * adjx + dfogdy * adjy)
+               fogLeft = vLower->fog + (span.fogStep * adjx + dfogdy * adjy)
                                        * (1.0F/FIXED_SCALE);
-               dfogOuter = dfogdy + dxOuter * dfogdx;
+               dfogOuter = dfogdy + dxOuter * span.fogStep;
 #endif
 #ifdef INTERP_RGB
                fr = (GLfixed)(IntToFixed(vLower->color[0])
                               + dbdx * adjx + dbdy * adjy) + FIXED_HALF;
                fdbOuter = SignedFloatToFixed(dbdy + dxOuter * dbdx);
 #endif
+#ifdef INTERP_ALPHA
+               fa = (GLfixed)(IntToFixed(vLower->color[3])
+                              + dadx * adjx + dady * adjy) + FIXED_HALF;
+               fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
+#endif
 #ifdef INTERP_SPEC
                fsr = (GLfixed)(IntToFixed(vLower->specular[0])
                                + dsrdx * adjx + dsrdy * adjy) + FIXED_HALF;
                                + dsbdx * adjx + dsbdy * adjy) + FIXED_HALF;
                fdsbOuter = SignedFloatToFixed(dsbdy + dxOuter * dsbdx);
 #endif
-#ifdef INTERP_ALPHA
-               fa = (GLfixed)(IntToFixed(vLower->color[3])
-                              + dadx * adjx + dady * adjy) + FIXED_HALF;
-               fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
-#endif
 #ifdef INTERP_INDEX
                fi = (GLfixed)(vLower->index * FIXED_SCALE
                               + didx * adjx + didy * adjy) + FIXED_HALF;
                {
                   GLfloat s0, t0;
                   s0 = vLower->texcoord[0][0] * S_SCALE;
-                  fs = (GLfixed)(s0 * FIXED_SCALE + dsdx * adjx + dsdy * adjy) + FIXED_HALF;
+                  fs = (GLfixed)(s0 * FIXED_SCALE + dsdx * adjx
+                                 + dsdy * adjy) + FIXED_HALF;
                   fdsOuter = SignedFloatToFixed(dsdy + dxOuter * dsdx);
 
                  t0 = vLower->texcoord[0][1] * T_SCALE;
-                 ft = (GLfixed)(t0 * FIXED_SCALE + dtdx * adjx + dtdy * adjy) + FIXED_HALF;
+                 ft = (GLfixed)(t0 * FIXED_SCALE + dtdx * adjx
+                                 + dtdy * adjy) + FIXED_HALF;
                  fdtOuter = SignedFloatToFixed(dtdy + dxOuter * dtdx);
               }
 #endif
                   GLfloat invW = vLower->win[3];
                   GLfloat s0, t0, u0, v0;
                   s0 = vLower->texcoord[0][0] * invW;
-                  sLeft = s0 + (dsdx * adjx + dsdy * adjy) * (1.0F/FIXED_SCALE);
-                  dsOuter = dsdy + dxOuter * dsdx;
+                  sLeft = s0 + (span.texStep[0][0] * adjx + dsdy * adjy)
+                     * (1.0F/FIXED_SCALE);
+                  dsOuter = dsdy + dxOuter * span.texStep[0][0];
                  t0 = vLower->texcoord[0][1] * invW;
-                 tLeft = t0 + (dtdx * adjx + dtdy * adjy) * (1.0F/FIXED_SCALE);
-                 dtOuter = dtdy + dxOuter * dtdx;
+                 tLeft = t0 + (span.texStep[0][1] * adjx + dtdy * adjy)
+                     * (1.0F/FIXED_SCALE);
+                 dtOuter = dtdy + dxOuter * span.texStep[0][1];
                  u0 = vLower->texcoord[0][2] * invW;
-                 uLeft = u0 + (dudx * adjx + dudy * adjy) * (1.0F/FIXED_SCALE);
-                 duOuter = dudy + dxOuter * dudx;
+                 uLeft = u0 + (span.texStep[0][2] * adjx + dudy * adjy)
+                     * (1.0F/FIXED_SCALE);
+                 duOuter = dudy + dxOuter * span.texStep[0][2];
                  v0 = vLower->texcoord[0][3] * invW;
-                 vLeft = v0 + (dvdx * adjx + dvdy * adjy) * (1.0F/FIXED_SCALE);
-                 dvOuter = dvdy + dxOuter * dvdx;
+                 vLeft = v0 + (span.texStep[0][3] * adjx + dvdy * adjy)
+                     * (1.0F/FIXED_SCALE);
+                 dvOuter = dvdy + dxOuter * span.texStep[0][3];
                }
 #endif
 #ifdef INTERP_MULTITEX
                         GLfloat invW = vLower->win[3];
                         GLfloat s0, t0, u0, v0;
                         s0 = vLower->texcoord[u][0] * invW;
-                        sLeft[u] = s0 + (dsdx[u] * adjx + dsdy[u] * adjy) * (1.0F/FIXED_SCALE);
-                        dsOuter[u] = dsdy[u] + dxOuter * dsdx[u];
+                        sLeft[u] = s0 + (span.texStep[u][0] * adjx + dsdy[u]
+                                         * adjy) * (1.0F/FIXED_SCALE);
+                        dsOuter[u] = dsdy[u] + dxOuter * span.texStep[u][0];
                        t0 = vLower->texcoord[u][1] * invW;
-                       tLeft[u] = t0 + (dtdx[u] * adjx + dtdy[u] * adjy) * (1.0F/FIXED_SCALE);
-                       dtOuter[u] = dtdy[u] + dxOuter * dtdx[u];
+                       tLeft[u] = t0 + (span.texStep[u][1] * adjx + dtdy[u]
+                                         * adjy) * (1.0F/FIXED_SCALE);
+                       dtOuter[u] = dtdy[u] + dxOuter * span.texStep[u][1];
                        u0 = vLower->texcoord[u][2] * invW;
-                       uLeft[u] = u0 + (dudx[u] * adjx + dudy[u] * adjy) * (1.0F/FIXED_SCALE);
-                       duOuter[u] = dudy[u] + dxOuter * dudx[u];
+                       uLeft[u] = u0 + (span.texStep[u][2] * adjx + dudy[u]
+                                         * adjy) * (1.0F/FIXED_SCALE);
+                       duOuter[u] = dudy[u] + dxOuter * span.texStep[u][2];
                        v0 = vLower->texcoord[u][3] * invW;
-                        vLeft[u] = v0 + (dvdx[u] * adjx + dvdy[u] * adjy) * (1.0F/FIXED_SCALE);
-                        dvOuter[u] = dvdy[u] + dxOuter * dvdx[u];
+                        vLeft[u] = v0 + (span.texStep[u][3] * adjx + dvdy[u]
+                                         * adjy) * (1.0F/FIXED_SCALE);
+                        dvOuter[u] = dvdy[u] + dxOuter * span.texStep[u][3];
                      }
                   }
                }
 #  ifdef DEPTH_TYPE
             dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
 #  endif
-            fdzInner = fdzOuter + fdzdx;
+            fdzInner = fdzOuter + span.zStep;
 #endif
 #ifdef INTERP_FOG
-            dfogInner = dfogOuter + dfogdx;
+            dfogInner = dfogOuter + span.fogStep;
 #endif
 #ifdef INTERP_RGB
-            fdrInner = fdrOuter + fdrdx;
-            fdgInner = fdgOuter + fdgdx;
-            fdbInner = fdbOuter + fdbdx;
-#endif
-#ifdef INTERP_SPEC
-            fdsrInner = fdsrOuter + fdsrdx;
-            fdsgInner = fdsgOuter + fdsgdx;
-            fdsbInner = fdsbOuter + fdsbdx;
+            fdrInner = fdrOuter + span.redStep;
+            fdgInner = fdgOuter + span.greenStep;
+            fdbInner = fdbOuter + span.blueStep;
 #endif
 #ifdef INTERP_ALPHA
-            fdaInner = fdaOuter + fdadx;
+            fdaInner = fdaOuter + span.alphaStep;
+#endif
+#ifdef INTERP_SPEC
+            fdsrInner = fdsrOuter + span.specRedStep;
+            fdsgInner = fdsgOuter + span.specGreenStep;
+            fdsbInner = fdsbOuter + span.specBlueStep;
 #endif
 #ifdef INTERP_INDEX
-            fdiInner = fdiOuter + fdidx;
+            fdiInner = fdiOuter + span.indexStep;
 #endif
 #ifdef INTERP_INT_TEX
-            fdsInner = fdsOuter + fdsdx;
-            fdtInner = fdtOuter + fdtdx;
+            fdsInner = fdsOuter + span.intTexStep[0];
+            fdtInner = fdtOuter + span.intTexStep[1];
 #endif
 #ifdef INTERP_TEX
-           dsInner = dsOuter + dsdx;
-           dtInner = dtOuter + dtdx;
-           duInner = duOuter + dudx;
-           dvInner = dvOuter + dvdx;
+           dsInner = dsOuter + span.texStep[0][0];
+           dtInner = dtOuter + span.texStep[0][1];
+           duInner = duOuter + span.texStep[0][2];
+           dvInner = dvOuter + span.texStep[0][3];
 #endif
 #ifdef INTERP_MULTITEX
             {
                GLuint u;
                for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
                   if (ctx->Texture.Unit[u]._ReallyEnabled) {
-                     dsInner[u] = dsOuter[u] + dsdx[u];
-                     dtInner[u] = dtOuter[u] + dtdx[u];
-                     duInner[u] = duOuter[u] + dudx[u];
-                     dvInner[u] = dvOuter[u] + dvdx[u];
+                     dsInner[u] = dsOuter[u] + span.texStep[u][0];
+                     dtInner[u] = dtOuter[u] + span.texStep[u][1];
+                     duInner[u] = duOuter[u] + span.texStep[u][2];
+                     dvInner[u] = dvOuter[u] + span.texStep[u][3];
                   }
                }
             }
 #endif
 
-            while (lines>0) {
+            while (lines > 0) {
                /* initialize the span interpolants to the leftmost value */
                /* ff = fixed-pt fragment */
-               GLint left = FixedToInt(fxLeftEdge);
-               GLint right = FixedToInt(fxRightEdge);
+               const GLint right = FixedToInt(fxRightEdge);
+               span.x = FixedToInt(fxLeftEdge);
+               if (right <= span.x)
+                  span.count = 0;
+               else
+                  span.count = right - span.x;
+
 #ifdef INTERP_Z
-               GLfixed ffz = fz;
+               span.z = fz;
 #endif
 #ifdef INTERP_FOG
-               GLfloat ffog = fogLeft;
+               span.fog = fogLeft;
 #endif
 #ifdef INTERP_RGB
-               GLfixed ffr = fr,  ffg = fg,  ffb = fb;
-#endif
-#ifdef INTERP_SPEC
-               GLfixed ffsr = fsr,  ffsg = fsg,  ffsb = fsb;
+               span.red = fr;
+               span.green = fg;
+               span.blue = fb;
 #endif
 #ifdef INTERP_ALPHA
-               GLfixed ffa = fa;
+               span.alpha = fa;
+#endif
+#ifdef INTERP_SPEC
+               span.specRed = fsr;
+               span.specGreen = fsg;
+               span.specBlue = fsb;
 #endif
 #ifdef INTERP_INDEX
-               GLfixed ffi = fi;
+               span.index = fi;
 #endif
 #ifdef INTERP_INT_TEX
-               GLfixed ffs = fs,  fft = ft;
+               span.intTex[0] = fs;
+               span.intTex[1] = ft;
 #endif
+
 #ifdef INTERP_TEX
-               GLfloat ss = sLeft, tt = tLeft, uu = uLeft, vv = vLeft;
+               span.tex[0][0] = sLeft;
+               span.tex[0][1] = tLeft;
+               span.tex[0][2] = uLeft;
+               span.tex[0][3] = vLeft;
 #endif
+
 #ifdef INTERP_MULTITEX
-               GLfloat ss[MAX_TEXTURE_UNITS];
-               GLfloat tt[MAX_TEXTURE_UNITS];
-               GLfloat uu[MAX_TEXTURE_UNITS];
-               GLfloat vv[MAX_TEXTURE_UNITS];
                {
                   GLuint u;
                   for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
                      if (ctx->Texture.Unit[u]._ReallyEnabled) {
-                        ss[u] = sLeft[u];
-                        tt[u] = tLeft[u];
-                        uu[u] = uLeft[u];
-                        vv[u] = vLeft[u];
+                        span.tex[u][0] = sLeft[u];
+                        span.tex[u][1] = tLeft[u];
+                        span.tex[u][2] = uLeft[u];
+                        span.tex[u][3] = vLeft[u];
                      }
                   }
                }
 #ifdef INTERP_RGB
                {
                   /* need this to accomodate round-off errors */
-                  GLfixed ffrend = ffr+(right-left-1)*fdrdx;
-                  GLfixed ffgend = ffg+(right-left-1)*fdgdx;
-                  GLfixed ffbend = ffb+(right-left-1)*fdbdx;
-                  if (ffrend<0) ffr -= ffrend;
-                  if (ffgend<0) ffg -= ffgend;
-                  if (ffbend<0) ffb -= ffbend;
-                  if (ffr<0) ffr = 0;
-                  if (ffg<0) ffg = 0;
-                  if (ffb<0) ffb = 0;
+                  const GLint len = right - span.x - 1;
+                  GLfixed ffrend = span.red + len * span.redStep;
+                  GLfixed ffgend = span.green + len * span.greenStep;
+                  GLfixed ffbend = span.blue + len * span.blueStep;
+                  if (ffrend < 0) {
+                     span.red -= ffrend;
+                     if (span.red < 0)
+                        span.red = 0;
+                  }
+                  if (ffgend < 0) {
+                     span.green -= ffgend;
+                     if (span.green < 0)
+                        span.green = 0;
+                  }
+                  if (ffbend < 0) {
+                     span.blue -= ffbend;
+                     if (span.blue < 0)
+                        span.blue = 0;
+                  }
                }
 #endif
-#ifdef INTERP_SPEC
+#ifdef INTERP_ALPHA
                {
-                  /* need this to accomodate round-off errors */
-                  GLfixed ffsrend = ffsr+(right-left-1)*fdsrdx;
-                  GLfixed ffsgend = ffsg+(right-left-1)*fdsgdx;
-                  GLfixed ffsbend = ffsb+(right-left-1)*fdsbdx;
-                  if (ffsrend<0) ffsr -= ffsrend;
-                  if (ffsgend<0) ffsg -= ffsgend;
-                  if (ffsbend<0) ffsb -= ffsbend;
-                  if (ffsr<0) ffsr = 0;
-                  if (ffsg<0) ffsg = 0;
-                  if (ffsb<0) ffsb = 0;
+                  const GLint len = right - span.x - 1;
+                  GLfixed ffaend = span.alpha + len * span.alphaStep;
+                  if (ffaend < 0) {
+                     span.alpha -= ffaend;
+                     if (span.alpha < 0)
+                        span.alpha = 0;
+                  }
                }
 #endif
-#ifdef INTERP_ALPHA
+#ifdef INTERP_SPEC
                {
-                  GLfixed ffaend = ffa+(right-left-1)*fdadx;
-                  if (ffaend<0) ffa -= ffaend;
-                  if (ffa<0) ffa = 0;
+                  /* need this to accomodate round-off errors */
+                  const GLint len = right - span.x - 1;
+                  GLfixed ffsrend = span.specRed + len * span.specRedStep;
+                  GLfixed ffsgend = span.specGreen + len * span.specGreenStep;
+                  GLfixed ffsbend = span.specBlue + len * span.specBlueStep;
+                  if (ffsrend < 0) {
+                     span.specRed -= ffsrend;
+                     if (span.specRed < 0)
+                        span.specRed = 0;
+                  }
+                  if (ffsgend < 0) {
+                     span.specGreen -= ffsgend;
+                     if (span.specGreen < 0)
+                        span.specGreen = 0;
+                  }
+                  if (ffsbend < 0) {
+                     span.specBlue -= ffsbend;
+                     if (span.specBlue < 0)
+                        span.specBlue = 0;
+                  }
                }
 #endif
 #ifdef INTERP_INDEX
-               if (ffi<0) ffi = 0;
-#endif
-
-#ifdef INTERP_LAMBDA
-/*
- * The lambda value is:
- *        log_2(sqrt(f(n))) = 1/2*log_2(f(n)), where f(n) is a function
- *     defined by
- *        f(n):=  dudx * dudx + dudy * dudy  +  dvdx * dvdx + dvdy * dvdy;
- *     and each of this terms is resp.
- *        dudx = dsdx * invQ(n) * tex_width;
- *        dudy = dsdy * invQ(n) * tex_width;
- *        dvdx = dtdx * invQ(n) * tex_height;
- *        dvdy = dtdy * invQ(n) * tex_height;
- *     Therefore the function lambda can be represented (by factoring out) as:
- *        f(n) = lambda_nominator * invQ(n) * invQ(n),
- *     which saves some computation time.
- */
-              {
-                  GLfloat dudx = dsdx /* * invQ*/ * twidth;
-                  GLfloat dudy = dsdy /* * invQ*/ * twidth;
-                  GLfloat dvdx = dtdx /* * invQ*/ * theight;
-                  GLfloat dvdy = dtdy /* * invQ*/ * theight;
-                  GLfloat r1 = dudx * dudx + dudy * dudy;
-                  GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
-                  GLfloat rho2 = r1 + r2; /* was:  rho2 = MAX2(r1,r2); */
-                  lambda_nominator = rho2;
-              }
-
-              /* set DEST to log_(base 2) of sqrt(rho) */
-               /* 1.442695 = 1/log(2) */
-#define COMPUTE_LAMBDA(DEST, X)  \
-   DEST = log( lambda_nominator * (X)*(X) ) * 1.442695F * 0.5F
-#endif
-
-#ifdef INTERP_MULTILAMBDA
-/*
- *  Read the comment for INTERP_LAMBDA, but apply to each texture unit
- */
-              {
-                  GLuint unit;
-                  for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
-                     if (ctx->Texture.Unit[unit]._ReallyEnabled) {
-                        GLfloat dudx = dsdx[unit] /* * invQ*/ * twidth[unit];
-                        GLfloat dudy = dsdy[unit] /* * invQ*/ * twidth[unit];
-                        GLfloat dvdx = dtdx[unit] /* * invQ*/ * theight[unit];
-                        GLfloat dvdy = dtdy[unit] /* * invQ*/ * theight[unit];
-                        GLfloat r1 = dudx * dudx + dudy * dudy;
-                        GLfloat r2 = dvdx * dvdx + dvdy * dvdy;
-                        GLfloat rho2 = r1 + r2; /* used to be:  rho2 = MAX2(r1,r2); */
-                        lambda_nominator[unit] = rho2;
-                     }
-                  }
-              }
-              /* set DEST to log_(base 2) of sqrt(rho) */
-#define COMPUTE_MULTILAMBDA(DEST, X, unit)  \
-   DEST = log( lambda_nominator[unit] * (X)*(X) ) * 1.442695F * 0.5F
+               if (span.index < 0)  span.index = 0;
 #endif
 
-
-               INNER_LOOP( left, right, iy );
+               /* This is where we actually generate fragments */
+               if (span.count > 0) {
+                  RENDER_SPAN( span );
+               }
 
                /*
                 * Advance to the next scan line.  Compute the
                 * pixel-center x coordinate so that it stays
                 * on or inside the major edge.
                 */
-               iy++;
+               span.y++;
                lines--;
 
                fxLeftEdge += fdxLeftEdge;
                if (fError >= 0) {
                   fError -= FIXED_ONE;
 #ifdef PIXEL_ADDRESS
-                  pRow = (PIXEL_TYPE *) ((GLubyte*)pRow + dPRowOuter);
+                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
 #endif
 #ifdef INTERP_Z
 #  ifdef DEPTH_TYPE
-                  zRow = (DEPTH_TYPE *) ((GLubyte*)zRow + dZRowOuter);
+                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
 #  endif
                   fz += fdzOuter;
 #endif
                   fogLeft += dfogOuter;
 #endif
 #ifdef INTERP_RGB
-                  fr += fdrOuter;   fg += fdgOuter;   fb += fdbOuter;
-#endif
-#ifdef INTERP_SPEC
-                  fsr += fdsrOuter;   fsg += fdsgOuter;   fsb += fdsbOuter;
+                  fr += fdrOuter;
+                  fg += fdgOuter;
+                  fb += fdbOuter;
 #endif
 #ifdef INTERP_ALPHA
                   fa += fdaOuter;
 #endif
+#ifdef INTERP_SPEC
+                  fsr += fdsrOuter;
+                  fsg += fdsgOuter;
+                  fsb += fdsbOuter;
+#endif
 #ifdef INTERP_INDEX
                   fi += fdiOuter;
 #endif
 #ifdef INTERP_INT_TEX
-                  fs += fdsOuter;   ft += fdtOuter;
+                  fs += fdsOuter;
+                  ft += fdtOuter;
 #endif
 #ifdef INTERP_TEX
                  sLeft += dsOuter;
                }
                else {
 #ifdef PIXEL_ADDRESS
-                  pRow = (PIXEL_TYPE *) ((GLubyte*)pRow + dPRowInner);
+                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
 #endif
 #ifdef INTERP_Z
 #  ifdef DEPTH_TYPE
-                  zRow = (DEPTH_TYPE *) ((GLubyte*)zRow + dZRowInner);
+                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
 #  endif
                   fz += fdzInner;
 #endif
                   fogLeft += dfogInner;
 #endif
 #ifdef INTERP_RGB
-                  fr += fdrInner;   fg += fdgInner;   fb += fdbInner;
-#endif
-#ifdef INTERP_SPEC
-                  fsr += fdsrInner;   fsg += fdsgInner;   fsb += fdsbInner;
+                  fr += fdrInner;
+                  fg += fdgInner;
+                  fb += fdbInner;
 #endif
 #ifdef INTERP_ALPHA
                   fa += fdaInner;
 #endif
+#ifdef INTERP_SPEC
+                  fsr += fdsrInner;
+                  fsg += fdsgInner;
+                  fsb += fdsbInner;
+#endif
 #ifdef INTERP_INDEX
                   fi += fdiInner;
 #endif
 #ifdef INTERP_INT_TEX
-                  fs += fdsInner;   ft += fdtInner;
+                  fs += fdsInner;
+                  ft += fdtInner;
 #endif
 #ifdef INTERP_TEX
                  sLeft += dsInner;
 }
 
 #undef SETUP_CODE
-#undef INNER_LOOP
+#undef RENDER_SPAN
 
 #undef PIXEL_TYPE
 #undef BYTES_PER_ROW
 #undef INTERP_Z
 #undef INTERP_FOG
 #undef INTERP_RGB
-#undef INTERP_SPEC
 #undef INTERP_ALPHA
+#undef INTERP_SPEC
 #undef INTERP_INDEX
 #undef INTERP_INT_TEX
 #undef INTERP_TEX
 #undef INTERP_MULTITEX
 #undef INTERP_LAMBDA
-#undef COMPUTE_LAMBDA
-#undef INTERP_MULTILAMBDA
-#undef COMPUTE_MULTILAMBDA
 
 #undef S_SCALE
 #undef T_SCALE