swrast: Fix fixed-function fragment processing
[mesa.git] / src / mesa / swrast / s_lines.c
index 3fb895f160053362027e9f20a9a5bfbd1d2739ce..ee997b08a7b1c5c285a49da050dcf89063928b0e 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: s_lines.c,v 1.25 2002/02/02 21:40:33 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  4.1
+ * Version:  7.1
  *
- * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  */
 
 
-#include "glheader.h"
-#include "colormac.h"
-#include "macros.h"
-#include "mmath.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/macros.h"
 #include "s_aaline.h"
 #include "s_context.h"
-#include "s_depth.h"
 #include "s_feedback.h"
 #include "s_lines.h"
 #include "s_span.h"
@@ -41,7 +38,7 @@
  * Init the mask[] array to implement a line stipple.
  */
 static void
-compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
+compute_stipple_mask( struct gl_context *ctx, GLuint len, GLubyte mask[] )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    GLuint i;
@@ -63,55 +60,50 @@ compute_stipple_mask( GLcontext *ctx, GLuint len, GLubyte mask[] )
  * To draw a wide line we can simply redraw the span N times, side by side.
  */
 static void
-draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor )
+draw_wide_line( struct gl_context *ctx, SWspan *span, GLboolean xMajor )
 {
-   GLint width, start;
+   const GLint width = (GLint) CLAMP(ctx->Line.Width,
+                                     ctx->Const.MinLineWidth,
+                                     ctx->Const.MaxLineWidth);
+   GLint start;
 
    ASSERT(span->end < MAX_WIDTH);
 
-   width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
-
    if (width & 1)
       start = width / 2;
    else
       start = width / 2 - 1;
 
    if (xMajor) {
-      GLuint i, w;
+      GLint *y = span->array->y;
+      GLuint i;
+      GLint w;
       for (w = 0; w < width; w++) {
          if (w == 0) {
             for (i = 0; i < span->end; i++)
-               span->yArray[i] -= start;
+               y[i] -= start;
          }
          else {
             for (i = 0; i < span->end; i++)
-               span->yArray[i]++;
+               y[i]++;
          }
-         if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
-            _mesa_write_texture_span(ctx, span, GL_LINE);
-         else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
-            _mesa_write_rgba_span(ctx, span, GL_LINE);
-         else
-            _mesa_write_index_span(ctx, span, GL_LINE);
+        _swrast_write_rgba_span(ctx, span);
       }
    }
    else {
-      GLuint i, w;
+      GLint *x = span->array->x;
+      GLuint i;
+      GLint w;
       for (w = 0; w < width; w++) {
          if (w == 0) {
             for (i = 0; i < span->end; i++)
-               span->xArray[i] -= start;
+               x[i] -= start;
          }
          else {
             for (i = 0; i < span->end; i++)
-               span->xArray[i]++;
+               x[i]++;
          }
-         if ((span->interpMask | span->arrayMask) & SPAN_TEXTURE)
-            _mesa_write_texture_span(ctx, span, GL_LINE);
-         else if ((span->interpMask | span->arrayMask) & SPAN_RGBA)
-            _mesa_write_rgba_span(ctx, span, GL_LINE);
-         else
-            _mesa_write_index_span(ctx, span, GL_LINE);
+        _swrast_write_rgba_span(ctx, span);
       }
    }
 }
@@ -122,621 +114,83 @@ draw_wide_line( GLcontext *ctx, struct sw_span *span, GLboolean xMajor )
 /*****                    Rasterization                           *****/
 /**********************************************************************/
 
-
-/* Flat, color index line */
-static void flat_ci_line( GLcontext *ctx,
-                          const SWvertex *vert0,
-                         const SWvertex *vert1 )
-{
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_FLAT);
-   ASSERT(!ctx->Line.StippleFlag);
-   ASSERT(ctx->Line.Width == 1.0F);
-
-   INIT_SPAN(span);
-   span.arrayMask |= SPAN_XY;
-   span.interpMask |= SPAN_INDEX;
-   span.index = IntToFixed(vert1->index);
-   span.indexStep = 0;
-
-#define INTERP_XY 1
-#define PLOT(X,Y)                      \
-   {                                   \
-      span.xArray[span.end] = X;       \
-      span.yArray[span.end] = Y;       \
-      span.end++;                      \
-   }
-
-#include "s_linetemp.h"
-
-   _mesa_write_index_span(ctx, &span, GL_LINE);
-}
-
-
-/* Flat-shaded, RGBA line */
-static void flat_rgba_line( GLcontext *ctx,
-                            const SWvertex *vert0,
-                           const SWvertex *vert1 )
-{
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_FLAT);
-   ASSERT(!ctx->Line.StippleFlag);
-   ASSERT(ctx->Line.Width == 1.0F);
-
-   INIT_SPAN(span);
-   span.arrayMask |= SPAN_XY;
-   span.interpMask |= SPAN_RGBA;
-   span.red = ChanToFixed(vert1->color[0]);
-   span.green = ChanToFixed(vert1->color[1]);
-   span.blue = ChanToFixed(vert1->color[2]);
-   span.alpha = ChanToFixed(vert1->color[3]);
-   span.redStep = 0;
-   span.greenStep = 0;
-   span.blueStep = 0;
-   span.alphaStep = 0;
-
-#define INTERP_XY 1
-#define PLOT(X,Y)                      \
-   {                                   \
-      span.xArray[span.end] = X;       \
-      span.yArray[span.end] = Y;       \
-      span.end++;                      \
-   }
-
-#include "s_linetemp.h"
-
-   _mesa_write_rgba_span(ctx, &span, GL_LINE);
-}
-
-
-/* Smooth shaded, color index line */
-static void smooth_ci_line( GLcontext *ctx,
-                            const SWvertex *vert0,
-                           const SWvertex *vert1 )
-{
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
-   ASSERT(!ctx->Line.StippleFlag);
-   ASSERT(ctx->Line.Width == 1.0F);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_INDEX);
-
-#define INTERP_XY 1
-#define INTERP_INDEX 1
-#define PLOT(X,Y)                      \
-   {                                   \
-      span.xArray[span.end] = X;       \
-      span.yArray[span.end] = Y;       \
-      span.color.index[span.end] = I;  \
-      span.end++;                      \
-   }
-
-#include "s_linetemp.h"
-
-   _mesa_write_index_span(ctx, &span, GL_LINE);
-}
-
-
-/* Smooth-shaded, RGBA line */
-static void smooth_rgba_line( GLcontext *ctx,
-                                     const SWvertex *vert0,
-                             const SWvertex *vert1 )
-{
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
-   ASSERT(!ctx->Line.StippleFlag);
-   ASSERT(ctx->Line.Width == 1.0F);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_RGBA);
-
-#define INTERP_XY 1
-#define INTERP_RGB 1
-#define INTERP_ALPHA 1
-#define PLOT(X,Y)                                              \
-   {                                                           \
-      span.xArray[span.end] = X;                               \
-      span.yArray[span.end] = Y;                               \
-      span.color.rgba[span.end][RCOMP] = FixedToInt(r0);       \
-      span.color.rgba[span.end][GCOMP] = FixedToInt(g0);       \
-      span.color.rgba[span.end][BCOMP] = FixedToInt(b0);       \
-      span.color.rgba[span.end][ACOMP] = FixedToInt(a0);       \
-      span.end++;                                              \
-   }
-
-#include "s_linetemp.h"
-
-   _mesa_write_rgba_span(ctx, &span, GL_LINE);
-}
-
-
-/* Smooth shaded, color index, any width, maybe stippled */
-static void general_smooth_ci_line( GLcontext *ctx,
-                                   const SWvertex *vert0,
-                                   const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_INDEX);
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define INTERP_INDEX 1
-#define PLOT(X,Y)                      \
-   {                                   \
-      span.xArray[span.end] = X;       \
-      span.yArray[span.end] = Y;       \
-      span.zArray[span.end] = Z;       \
-      span.fogArray[span.end] = fog0;  \
-      span.color.index[span.end] = I;  \
-      span.end++;                      \
-   }
-#include "s_linetemp.h"
-
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
-
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_index_span(ctx, &span, GL_LINE);
-   }
-}
-
-
-/* Flat shaded, color index, any width, maybe stippled */
-static void general_flat_ci_line( GLcontext *ctx,
-                                  const SWvertex *vert0,
-                                 const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_FLAT);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG);
-   span.interpMask |= SPAN_INDEX;
-   span.index = IntToFixed(vert1->index);
-   span.indexStep = 0;
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define PLOT(X,Y)                      \
-   {                                   \
-      span.xArray[span.end] = X;       \
-      span.yArray[span.end] = Y;       \
-      span.zArray[span.end] = Z;       \
-      span.fogArray[span.end] = fog0;  \
-      span.end++;                      \
-   }
-#include "s_linetemp.h"
-
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
-
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_index_span(ctx, &span, GL_LINE);
-   }
-}
-
-
-
-static void general_smooth_rgba_line( GLcontext *ctx,
-                                      const SWvertex *vert0,
-                                     const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA);
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define INTERP_RGB 1
-#define INTERP_ALPHA 1
-#define PLOT(X,Y)                                              \
-   {                                                           \
-      span.xArray[span.end] = X;                               \
-      span.yArray[span.end] = Y;                               \
-      span.zArray[span.end] = Z;                               \
-      span.color.rgba[span.end][RCOMP] = FixedToInt(r0);       \
-      span.color.rgba[span.end][GCOMP] = FixedToInt(g0);       \
-      span.color.rgba[span.end][BCOMP] = FixedToInt(b0);       \
-      span.color.rgba[span.end][ACOMP] = FixedToInt(a0);       \
-      span.fogArray[span.end] = fog0;                          \
-      span.end++;                                              \
-   }
-#include "s_linetemp.h"
-
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
-
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_rgba_span(ctx, &span, GL_LINE);
-   }
-}
-
-
-static void general_flat_rgba_line( GLcontext *ctx,
-                                    const SWvertex *vert0,
-                                   const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_FLAT);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG);
-   span.interpMask |= SPAN_RGBA;
-   span.red = ChanToFixed(vert1->color[0]);
-   span.green = ChanToFixed(vert1->color[1]);
-   span.blue = ChanToFixed(vert1->color[2]);
-   span.alpha = ChanToFixed(vert1->color[3]);
-   span.redStep = 0;
-   span.greenStep = 0;
-   span.blueStep = 0;
-   span.alphaStep = 0;
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define PLOT(X,Y)                                              \
-   {                                                           \
-      span.xArray[span.end] = X;                               \
-      span.yArray[span.end] = Y;                               \
-      span.zArray[span.end] = Z;                               \
-      span.fogArray[span.end] = fog0;                          \
-      span.end++;                                              \
-   }
-#include "s_linetemp.h"
-
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
-
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_rgba_span(ctx, &span, GL_LINE);
-   }
-}
-
-
-/* Flat-shaded, textured, any width, maybe stippled */
-static void flat_textured_line( GLcontext *ctx,
-                                const SWvertex *vert0,
-                               const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_FLAT);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA);
-   span.interpMask |= (SPAN_RGBA | SPAN_SPEC);
-   span.red = ChanToFixed(vert1->color[0]);
-   span.green = ChanToFixed(vert1->color[1]);
-   span.blue = ChanToFixed(vert1->color[2]);
-   span.alpha = ChanToFixed(vert1->color[3]);
-   span.redStep = 0;
-   span.greenStep = 0;
-   span.blueStep = 0;
-   span.alphaStep = 0;
-   span.specRed = ChanToFixed(vert1->specular[0]);
-   span.specGreen = ChanToFixed(vert1->specular[1]);
-   span.specBlue = ChanToFixed(vert1->specular[2]);
-   span.specRedStep = 0;
-   span.specGreenStep = 0;
-   span.specBlueStep = 0;
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define INTERP_TEX 1
-#define PLOT(X,Y)                                              \
-   {                                                           \
-      span.xArray[span.end] = X;                               \
-      span.yArray[span.end] = Y;                               \
-      span.zArray[span.end] = Z;                               \
-      span.fogArray[span.end] = fog0;                          \
-      span.texcoords[0][span.end][0] = fragTexcoord[0];                \
-      span.texcoords[0][span.end][1] = fragTexcoord[1];                \
-      span.texcoords[0][span.end][2] = fragTexcoord[2];                \
-      span.lambda[0][span.end] = 0.0;                          \
-      span.end++;                                              \
-   }
-#include "s_linetemp.h"
-
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
-
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_texture_span(ctx, &span, GL_LINE);
-   }
-}
-
-
-
-/* Smooth-shaded, textured, any width, maybe stippled */
-static void smooth_textured_line( GLcontext *ctx,
-                                  const SWvertex *vert0,
-                                 const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-
-   ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_TEXTURE | SPAN_LAMBDA);
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define INTERP_RGB 1
-#define INTERP_ALPHA 1
-#define INTERP_TEX 1
-#define PLOT(X,Y)                                              \
-   {                                                           \
-      span.xArray[span.end] = X;                               \
-      span.yArray[span.end] = Y;                               \
-      span.zArray[span.end] = Z;                               \
-      span.fogArray[span.end] = fog0;                          \
-      span.color.rgba[span.end][RCOMP] = FixedToInt(r0);       \
-      span.color.rgba[span.end][GCOMP] = FixedToInt(g0);       \
-      span.color.rgba[span.end][BCOMP] = FixedToInt(b0);       \
-      span.color.rgba[span.end][ACOMP] = FixedToInt(a0);       \
-      span.texcoords[0][span.end][0] = fragTexcoord[0];                \
-      span.texcoords[0][span.end][1] = fragTexcoord[1];                \
-      span.texcoords[0][span.end][2] = fragTexcoord[2];                \
-      span.lambda[0][span.end] = 0.0;                          \
-      span.end++;                                              \
-   }
+/* Simple RGBA index line (no stipple, width=1, no Z, no fog, no tex)*/
+#define NAME simple_no_z_rgba_line
+#define INTERP_RGBA
+#define RENDER_SPAN(span) _swrast_write_rgba_span(ctx, &span);
 #include "s_linetemp.h"
 
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
 
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_texture_span(ctx, &span, GL_LINE);
-   }
-}
-
-
-/* Smooth-shaded, multitextured, any width, maybe stippled, separate specular
- * color interpolation.
- */
-static void smooth_multitextured_line( GLcontext *ctx,
-                                      const SWvertex *vert0,
-                                      const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-   GLuint u;
-
-   ASSERT(ctx->Light.ShadeModel == GL_SMOOTH);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_RGBA | SPAN_TEXTURE | SPAN_LAMBDA);
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define INTERP_RGB 1
-#define INTERP_SPEC 1
-#define INTERP_ALPHA 1
-#define INTERP_MULTITEX 1
-#define PLOT(X,Y)                                                      \
-   {                                                                   \
-      span.xArray[span.end] = X;                                       \
-      span.yArray[span.end] = Y;                                       \
-      span.zArray[span.end] = Z;                                       \
-      span.fogArray[span.end] = fog0;                                  \
-      span.color.rgba[span.end][RCOMP] = FixedToInt(r0);               \
-      span.color.rgba[span.end][GCOMP] = FixedToInt(g0);               \
-      span.color.rgba[span.end][BCOMP] = FixedToInt(b0);               \
-      span.color.rgba[span.end][ACOMP] = FixedToInt(a0);               \
-      span.specArray[span.end][RCOMP] = FixedToInt(sr0);               \
-      span.specArray[span.end][GCOMP] = FixedToInt(sb0);               \
-      span.specArray[span.end][BCOMP] = FixedToInt(sb0);               \
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {               \
-         if (ctx->Texture.Unit[u]._ReallyEnabled) {                    \
-            span.texcoords[u][span.end][0] = fragTexcoord[u][0];       \
-            span.texcoords[u][span.end][1] = fragTexcoord[u][1];       \
-            span.texcoords[u][span.end][2] = fragTexcoord[u][2];       \
-            span.lambda[u][span.end] = 0.0;                            \
-         }                                                             \
-      }                                                                        \
-      span.end++;                                                      \
+/* Z, fog, wide, stipple RGBA line */
+#define NAME rgba_line
+#define INTERP_RGBA
+#define INTERP_Z
+#define RENDER_SPAN(span)                                      \
+   if (ctx->Line.StippleFlag) {                                        \
+      span.arrayMask |= SPAN_MASK;                             \
+      compute_stipple_mask(ctx, span.end, span.array->mask);   \
+   }                                                           \
+   if (ctx->Line.Width > 1.0) {                                        \
+      draw_wide_line(ctx, &span, (GLboolean)(dx > dy));                \
+   }                                                           \
+   else {                                                      \
+      _swrast_write_rgba_span(ctx, &span);                     \
    }
 #include "s_linetemp.h"
 
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
 
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_texture_span(ctx, &span, GL_LINE);
-   }
-}
-
-
-/* Flat-shaded, multitextured, any width, maybe stippled, separate specular
- * color interpolation.
- */
-static void flat_multitextured_line( GLcontext *ctx,
-                                     const SWvertex *vert0,
-                                    const SWvertex *vert1 )
-{
-   GLboolean xMajor = GL_FALSE;
-   struct sw_span span;
-   GLuint u;
-
-   ASSERT(ctx->Light.ShadeModel == GL_FLAT);
-
-   INIT_SPAN(span);
-   span.arrayMask |= (SPAN_XY | SPAN_Z | SPAN_FOG | SPAN_TEXTURE | SPAN_LAMBDA);
-   span.interpMask |= (SPAN_RGBA | SPAN_SPEC);
-   span.red = ChanToFixed(vert1->color[0]);
-   span.green = ChanToFixed(vert1->color[1]);
-   span.blue = ChanToFixed(vert1->color[2]);
-   span.alpha = ChanToFixed(vert1->color[3]);
-   span.redStep = 0;
-   span.greenStep = 0;
-   span.blueStep = 0;
-   span.alphaStep = 0;
-   span.specRed = ChanToFixed(vert1->specular[0]);
-   span.specGreen = ChanToFixed(vert1->specular[1]);
-   span.specBlue = ChanToFixed(vert1->specular[2]);
-   span.specRedStep = 0;
-   span.specGreenStep = 0;
-   span.specBlueStep = 0;
-
-#define SET_XMAJOR 1
-#define INTERP_XY 1
-#define INTERP_Z 1
-#define INTERP_FOG 1
-#define INTERP_MULTITEX 1
-#define PLOT(X,Y)                                                      \
-   {                                                                   \
-      span.xArray[span.end] = X;                                       \
-      span.yArray[span.end] = Y;                                       \
-      span.zArray[span.end] = Z;                                       \
-      span.fogArray[span.end] = fog0;                                  \
-      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {               \
-         if (ctx->Texture.Unit[u]._ReallyEnabled) {                    \
-            span.texcoords[u][span.end][0] = fragTexcoord[u][0];       \
-            span.texcoords[u][span.end][1] = fragTexcoord[u][1];       \
-            span.texcoords[u][span.end][2] = fragTexcoord[u][2];       \
-            span.lambda[u][span.end] = 0.0;                            \
-         }                                                             \
-      }                                                                        \
-      span.end++;                                                      \
+/* General-purpose line (any/all features). */
+#define NAME general_line
+#define INTERP_RGBA
+#define INTERP_Z
+#define INTERP_ATTRIBS
+#define RENDER_SPAN(span)                                      \
+   if (ctx->Line.StippleFlag) {                                        \
+      span.arrayMask |= SPAN_MASK;                             \
+      compute_stipple_mask(ctx, span.end, span.array->mask);   \
+   }                                                           \
+   if (ctx->Line.Width > 1.0) {                                        \
+      draw_wide_line(ctx, &span, (GLboolean)(dx > dy));                \
+   }                                                           \
+   else {                                                      \
+      _swrast_write_rgba_span(ctx, &span);                     \
    }
 #include "s_linetemp.h"
 
-   if (ctx->Line.StippleFlag) {
-      span.arrayMask |= SPAN_MASK;
-      compute_stipple_mask(ctx, span.end, span.mask);
-   }
 
-   if (ctx->Line.Width > 1.0) {
-      draw_wide_line(ctx, &span, xMajor);
-   }
-   else {
-      _mesa_write_texture_span(ctx, &span, GL_LINE);
-   }
-}
 
-
-void _swrast_add_spec_terms_line( GLcontext *ctx,
-                                 const SWvertex *v0,
-                                 const SWvertex *v1 )
+void
+_swrast_add_spec_terms_line(struct gl_context *ctx,
+                            const SWvertex *v0, const SWvertex *v1)
 {
    SWvertex *ncv0 = (SWvertex *)v0;
    SWvertex *ncv1 = (SWvertex *)v1;
-   GLchan c[2][4];
-   COPY_CHAN4( c[0], ncv0->color );
-   COPY_CHAN4( c[1], ncv1->color );
-   ACC_3V( ncv0->color, ncv0->specular );
-   ACC_3V( ncv1->color, ncv1->specular );
+   GLfloat rSum, gSum, bSum;
+   GLchan cSave[2][4];
+
+   /* save original colors */
+   COPY_CHAN4(cSave[0], ncv0->color);
+   COPY_CHAN4(cSave[1], ncv1->color);
+   /* sum v0 */
+   rSum = CHAN_TO_FLOAT(ncv0->color[0]) + ncv0->attrib[FRAG_ATTRIB_COL1][0];
+   gSum = CHAN_TO_FLOAT(ncv0->color[1]) + ncv0->attrib[FRAG_ATTRIB_COL1][1];
+   bSum = CHAN_TO_FLOAT(ncv0->color[2]) + ncv0->attrib[FRAG_ATTRIB_COL1][2];
+   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[0], rSum);
+   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[1], gSum);
+   UNCLAMPED_FLOAT_TO_CHAN(ncv0->color[2], bSum);
+   /* sum v1 */
+   rSum = CHAN_TO_FLOAT(ncv1->color[0]) + ncv1->attrib[FRAG_ATTRIB_COL1][0];
+   gSum = CHAN_TO_FLOAT(ncv1->color[1]) + ncv1->attrib[FRAG_ATTRIB_COL1][1];
+   bSum = CHAN_TO_FLOAT(ncv1->color[2]) + ncv1->attrib[FRAG_ATTRIB_COL1][2];
+   UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[0], rSum);
+   UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[1], gSum);
+   UNCLAMPED_FLOAT_TO_CHAN(ncv1->color[2], bSum);
+   /* draw */
    SWRAST_CONTEXT(ctx)->SpecLine( ctx, ncv0, ncv1 );
-   COPY_CHAN4( ncv0->color, c[0] );
-   COPY_CHAN4( ncv1->color, c[1] );
-}
-
-
-#ifdef DEBUG
-extern void
-_mesa_print_line_function(GLcontext *ctx);  /* silence compiler warning */
-void
-_mesa_print_line_function(GLcontext *ctx)
-{
-   SWcontext *swrast = SWRAST_CONTEXT(ctx);
-
-   printf("Line Func == ");
-   if (swrast->Line == flat_ci_line)
-      printf("flat_ci_line\n");
-   else if (swrast->Line == flat_rgba_line)
-      printf("flat_rgba_line\n");
-   else if (swrast->Line == smooth_ci_line)
-      printf("smooth_ci_line\n");
-   else if (swrast->Line == smooth_rgba_line)
-      printf("smooth_rgba_line\n");
-   else if (swrast->Line == general_smooth_ci_line)
-      printf("general_smooth_ci_line\n");
-   else if (swrast->Line == general_flat_ci_line)
-      printf("general_flat_ci_line\n");
-   else if (swrast->Line == general_smooth_rgba_line)
-      printf("general_smooth_rgba_line\n");
-   else if (swrast->Line == general_flat_rgba_line)
-      printf("general_flat_rgba_line\n");
-   else if (swrast->Line == flat_textured_line)
-      printf("flat_textured_line\n");
-   else if (swrast->Line == smooth_textured_line)
-      printf("smooth_textured_line\n");
-   else if (swrast->Line == smooth_multitextured_line)
-      printf("smooth_multitextured_line\n");
-   else if (swrast->Line == flat_multitextured_line)
-      printf("flat_multitextured_line\n");
-   else
-      printf("Driver func %p\n", (void *) swrast->Line);
+   /* restore original colors */
+   COPY_CHAN4( ncv0->attrib[FRAG_ATTRIB_COL0], cSave[0] );
+   COPY_CHAN4( ncv1->attrib[FRAG_ATTRIB_COL0], cSave[1] );
 }
-#endif
 
 
 
@@ -760,7 +214,7 @@ do {                                    \
 
 
 
-/*
+/**
  * Determine which line drawing function to use given the current
  * rendering context.
  *
@@ -768,75 +222,47 @@ do {                                    \
  * tests to this code.
  */
 void
-_swrast_choose_line( GLcontext *ctx )
+_swrast_choose_line( struct gl_context *ctx )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const GLboolean rgbmode = ctx->Visual.rgbMode;
+   GLboolean specular = (ctx->Fog.ColorSumEnabled ||
+                         (ctx->Light.Enabled &&
+                          ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR));
 
    if (ctx->RenderMode == GL_RENDER) {
       if (ctx->Line.SmoothFlag) {
          /* antialiased lines */
          _swrast_choose_aa_line_function(ctx);
-         ASSERT(swrast->Triangle);
+         ASSERT(swrast->Line);
       }
-      else if (ctx->Texture._ReallyEnabled) {
-         if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY ||          
-            (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) {
-            /* multi-texture and/or separate specular color */
-            if (ctx->Light.ShadeModel == GL_SMOOTH)
-               USE(smooth_multitextured_line);
-            else
-               USE(flat_multitextured_line);
-         }
-         else {
-            if (ctx->Light.ShadeModel == GL_SMOOTH) {
-                USE(smooth_textured_line);
-            }
-            else {
-                USE(flat_textured_line);
-            }
-         }
+      else if (ctx->Texture._EnabledCoordUnits
+               || _swrast_use_fragment_program(ctx)
+               || swrast->_FogEnabled
+               || specular) {
+         USE(general_line);
+      }
+      else if (ctx->Depth.Test
+               || ctx->Line.Width != 1.0
+               || ctx->Line.StippleFlag) {
+         /* no texture, but Z, fog, width>1, stipple, etc. */
+#if CHAN_BITS == 32
+         USE(general_line);
+#else
+         USE(rgba_line);
+#endif
       }
       else {
-        if (ctx->Light.ShadeModel == GL_SMOOTH) {
-            if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
-                || ctx->Line.StippleFlag) {
-               if (rgbmode)
-                  USE(general_smooth_rgba_line);
-               else
-                  USE(general_smooth_ci_line);
-            }
-            else {
-               if (rgbmode)
-                  USE(smooth_rgba_line);
-               else
-                  USE(smooth_ci_line);
-            }
-        }
-         else {
-            if (ctx->Depth.Test || ctx->Fog.Enabled || ctx->Line.Width != 1.0
-                || ctx->Line.StippleFlag) {
-               if (rgbmode)
-                  USE(general_flat_rgba_line);
-               else
-                  USE(general_flat_ci_line);
-            }
-            else {
-               if (rgbmode)
-                  USE(flat_rgba_line);
-               else
-                  USE(flat_ci_line);
-            }
-         }
+         ASSERT(!ctx->Depth.Test);
+         ASSERT(ctx->Line.Width == 1.0);
+         /* simple lines */
+         USE(simple_no_z_rgba_line);
       }
    }
    else if (ctx->RenderMode == GL_FEEDBACK) {
-      USE(_mesa_feedback_line);
+      USE(_swrast_feedback_line);
    }
    else {
       ASSERT(ctx->RenderMode == GL_SELECT);
-      USE(_mesa_select_line);
+      USE(_swrast_select_line);
    }
-
-   /*_mesa_print_line_function(ctx);*/
 }