mesa/main: use call_once instead of open-coding
[mesa.git] / src / mesa / swrast / s_span.c
index 8931cdec1bc4569ba111ddc840eb84b83e8582b3..dcb2db01e6d09c204ce444195eb1b73fd1380125 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Mesa 3-D graphics library
- * Version:  7.5
  *
  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  * 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.
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
  */
 
 
  * \author Brian Paul
  */
 
+#include "c99_math.h"
+#include "main/errors.h"
 #include "main/glheader.h"
-#include "main/colormac.h"
+#include "main/format_pack.h"
+#include "main/format_unpack.h"
 #include "main/macros.h"
-#include "main/imports.h"
+
 #include "main/image.h"
+#include "main/samplerobj.h"
+#include "main/state.h"
+#include "main/stencil.h"
+#include "main/teximage.h"
 
 #include "s_atifragshader.h"
 #include "s_alpha.h"
@@ -50,6 +57,7 @@
 #include "s_stencil.h"
 #include "s_texcombine.h"
 
+#include <stdbool.h>
 
 /**
  * Set default fragment attributes for the span using the
@@ -57,7 +65,7 @@
  * and glBitmap.
  */
 void
-_swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
+_swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
 {
    GLchan r, g, b, a;
    /* Z*/
@@ -66,7 +74,7 @@ _swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
       if (ctx->DrawBuffer->Visual.depthBits <= 16)
          span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
       else {
-         GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax; 
+         GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax;
          tmpf = MIN2(tmpf, depthMax);
          span->z = (GLint)tmpf;
       }
@@ -75,9 +83,9 @@ _swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
    }
 
    /* W (for perspective correction) */
-   span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
-   span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
-   span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
+   span->attrStart[VARYING_SLOT_POS][3] = 1.0;
+   span->attrStepX[VARYING_SLOT_POS][3] = 0.0;
+   span->attrStepY[VARYING_SLOT_POS][3] = 0.0;
 
    /* primary color, or color index */
    UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
@@ -101,16 +109,16 @@ _swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
    span->alphaStep = 0;
    span->interpMask |= SPAN_RGBA;
 
-   COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor);
-   ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
-   ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
+   COPY_4V(span->attrStart[VARYING_SLOT_COL0], ctx->Current.RasterColor);
+   ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0);
+   ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0);
 
    /* Secondary color */
    if (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled)
    {
-      COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor);
-      ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
-      ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
+      COPY_4V(span->attrStart[VARYING_SLOT_COL1], ctx->Current.RasterSecondaryColor);
+      ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0);
+      ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0);
    }
 
    /* fog */
@@ -125,18 +133,19 @@ _swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
          /* fog blend factor should be computed from fogcoord now */
          fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
       }
-      span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
-      span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
-      span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
+      span->attrStart[VARYING_SLOT_FOGC][0] = fogVal;
+      span->attrStepX[VARYING_SLOT_FOGC][0] = 0.0;
+      span->attrStepY[VARYING_SLOT_FOGC][0] = 0.0;
    }
 
    /* texcoords */
    {
       GLuint i;
       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
-         const GLuint attr = FRAG_ATTRIB_TEX0 + i;
+         const GLuint attr = VARYING_SLOT_TEX0 + i;
          const GLfloat *tc = ctx->Current.RasterTexCoords[i];
-         if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
+         if (_swrast_use_fragment_program(ctx) ||
+             _mesa_ati_fragment_shader_enabled(ctx)) {
             COPY_4V(span->attrStart[attr], tc);
          }
          else if (tc[3] > 0.0F) {
@@ -160,10 +169,11 @@ _swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
  * Interpolate the active attributes (and'd with attrMask) to
  * fill in span->array->attribs[].
  * Perspective correction will be done.  The point/line/triangle function
- * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]!
+ * should have computed attrStart/Step values for VARYING_SLOT_POS[3]!
  */
-static INLINE void
-interpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask)
+static inline void
+interpolate_active_attribs(struct gl_context *ctx, SWspan *span,
+                           GLbitfield64 attrMask)
 {
    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
@@ -174,9 +184,9 @@ interpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask)
    attrMask &= ~span->arrayAttribs;
 
    ATTRIB_LOOP_BEGIN
-      if (attrMask & (1 << attr)) {
-         const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
-         GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
+      if (attrMask & BITFIELD64_BIT(attr)) {
+         const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
+         GLfloat w = span->attrStart[VARYING_SLOT_POS][3];
          const GLfloat dv0dx = span->attrStepX[attr][0];
          const GLfloat dv1dx = span->attrStepX[attr][1];
          const GLfloat dv2dx = span->attrStepX[attr][2];
@@ -198,8 +208,8 @@ interpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask)
             v3 += dv3dx;
             w += dwdx;
          }
-         ASSERT((span->arrayAttribs & (1 << attr)) == 0);
-         span->arrayAttribs |= (1 << attr);
+         assert((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0);
+         span->arrayAttribs |= BITFIELD64_BIT(attr);
       }
    ATTRIB_LOOP_END
 }
@@ -209,14 +219,14 @@ interpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask)
  * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
  * color array.
  */
-static INLINE void
-interpolate_int_colors(GLcontext *ctx, SWspan *span)
+static inline void
+interpolate_int_colors(struct gl_context *ctx, SWspan *span)
 {
+#if CHAN_BITS != 32
    const GLuint n = span->end;
    GLuint i;
 
-#if CHAN_BITS != 32
-   ASSERT(!(span->arrayMask & SPAN_RGBA));
+   assert(!(span->arrayMask & SPAN_RGBA));
 #endif
 
    switch (span->array->ChanType) {
@@ -296,26 +306,27 @@ interpolate_int_colors(GLcontext *ctx, SWspan *span)
       break;
 #endif
    case GL_FLOAT:
-      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+      interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
       break;
    default:
-      _mesa_problem(NULL, "bad datatype in interpolate_int_colors");
+      _mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors",
+                    span->array->ChanType);
    }
    span->arrayMask |= SPAN_RGBA;
 }
 
 
 /**
- * Populate the FRAG_ATTRIB_COL0 array.
+ * Populate the VARYING_SLOT_COL0 array.
  */
-static INLINE void
+static inline void
 interpolate_float_colors(SWspan *span)
 {
-   GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+   GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0];
    const GLuint n = span->end;
    GLuint i;
 
-   assert(!(span->arrayAttribs & FRAG_BIT_COL0));
+   assert(!(span->arrayAttribs & VARYING_BIT_COL0));
 
    if (span->arrayMask & SPAN_RGBA) {
       /* convert array of int colors */
@@ -328,7 +339,7 @@ interpolate_float_colors(SWspan *span)
    }
    else {
       /* interpolate red/green/blue/alpha to get float colors */
-      ASSERT(span->interpMask & SPAN_RGBA);
+      assert(span->interpMask & SPAN_RGBA);
       if (span->interpMask & SPAN_FLAT) {
          GLfloat r = FixedToFloat(span->red);
          GLfloat g = FixedToFloat(span->green);
@@ -360,7 +371,7 @@ interpolate_float_colors(SWspan *span)
       }
    }
 
-   span->arrayAttribs |= FRAG_BIT_COL0;
+   span->arrayAttribs |= VARYING_BIT_COL0;
    span->array->ChanType = GL_FLOAT;
 }
 
@@ -370,16 +381,16 @@ interpolate_float_colors(SWspan *span)
  * Fill in the span.zArray array from the span->z, zStep values.
  */
 void
-_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
+_swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span )
 {
    const GLuint n = span->end;
    GLuint i;
 
-   ASSERT(!(span->arrayMask & SPAN_Z));
+   assert(!(span->arrayMask & SPAN_Z));
 
    if (ctx->DrawBuffer->Visual.depthBits <= 16) {
       GLfixed zval = span->z;
-      GLuint *z = span->array->z; 
+      GLuint *z = span->array->z;
       for (i = 0; i < n; i++) {
          z[i] = FixedToInt(zval);
          zval += span->zStep;
@@ -412,10 +423,10 @@ _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
    GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
    GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
    GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
-   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
-   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
+   GLfloat x = sqrtf(dudx * dudx + dvdx * dvdx);
+   GLfloat y = sqrtf(dudy * dudy + dvdy * dvdy);
    GLfloat rho = MAX2(x, y);
-   GLfloat lambda = LOG2(rho);
+   GLfloat lambda = log2f(rho);
    return lambda;
 }
 
@@ -435,21 +446,21 @@ _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
    GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
    GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
    GLfloat maxU, maxV, rho, lambda;
-   dsdx2 = FABSF(dsdx2);
-   dsdy2 = FABSF(dsdy2);
-   dtdx2 = FABSF(dtdx2);
-   dtdy2 = FABSF(dtdy2);
+   dsdx2 = fabsf(dsdx2);
+   dsdy2 = fabsf(dsdy2);
+   dtdx2 = fabsf(dtdx2);
+   dtdy2 = fabsf(dtdy2);
    maxU = MAX2(dsdx2, dsdy2) * texW;
    maxV = MAX2(dtdx2, dtdy2) * texH;
    rho = MAX2(maxU, maxV);
-   lambda = LOG2(rho);
+   lambda = logf2(rho);
    return lambda;
 }
 #endif
 
 
 /**
- * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the
+ * Fill in the span.array->attrib[VARYING_SLOT_TEXn] arrays from the
  * using the attrStart/Step values.
  *
  * This function only used during fixed-function fragment processing.
@@ -460,7 +471,7 @@ _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
  * texels with (s/q, t/q, r/q).
  */
 static void
-interpolate_texcoords(GLcontext *ctx, SWspan *span)
+interpolate_texcoords(struct gl_context *ctx, SWspan *span)
 {
    const GLuint maxUnit
       = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
@@ -469,7 +480,7 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
    /* XXX CoordUnits vs. ImageUnits */
    for (u = 0; u < maxUnit; u++) {
       if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
-         const GLuint attr = FRAG_ATTRIB_TEX0 + u;
+         const GLuint attr = VARYING_SLOT_TEX0 + u;
          const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
          GLfloat texW, texH;
          GLboolean needLambda;
@@ -488,11 +499,22 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
          GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
 
          if (obj) {
-            const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
-            needLambda = (obj->MinFilter != obj->MagFilter)
-               || ctx->FragmentProgram._Current;
-            texW = img->WidthScale;
-            texH = img->HeightScale;
+            const struct gl_texture_image *img = _mesa_base_tex_image(obj);
+            const struct swrast_texture_image *swImg =
+               swrast_texture_image_const(img);
+            const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, u);
+
+            needLambda = (samp->MinFilter != samp->MagFilter)
+               || _swrast_use_fragment_program(ctx);
+            /* LOD is calculated directly in the ansiotropic filter, we can
+             * skip the normal lambda function as the result is ignored.
+             */
+            if (samp->MaxAnisotropy > 1.0F &&
+                samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
+               needLambda = GL_FALSE;
+            }
+            texW = swImg->WidthScale;
+            texH = swImg->HeightScale;
          }
          else {
             /* using a fragment program */
@@ -503,11 +525,11 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
 
          if (needLambda) {
             GLuint i;
-            if (ctx->FragmentProgram._Current
-                || ctx->ATIFragmentShader._Enabled) {
+            if (_swrast_use_fragment_program(ctx)
+                || _mesa_ati_fragment_shader_enabled(ctx)) {
                /* do perspective correction but don't divide s, t, r by q */
-               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
-               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
+               const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
+               GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx;
                for (i = 0; i < span->end; i++) {
                   const GLfloat invW = 1.0F / w;
                   texcoord[i][0] = s * invW;
@@ -544,11 +566,11 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
          }
          else {
             GLuint i;
-            if (ctx->FragmentProgram._Current ||
-                ctx->ATIFragmentShader._Enabled) {
+            if (_swrast_use_fragment_program(ctx) ||
+                _mesa_ati_fragment_shader_enabled(ctx)) {
                /* do perspective correction but don't divide s, t, r by q */
-               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
-               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
+               const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
+               GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx;
                for (i = 0; i < span->end; i++) {
                   const GLfloat invW = 1.0F / w;
                   texcoord[i][0] = s * invW;
@@ -598,12 +620,12 @@ interpolate_texcoords(GLcontext *ctx, SWspan *span)
 
 
 /**
- * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
+ * Fill in the arrays->attribs[VARYING_SLOT_POS] array.
  */
-static INLINE void
-interpolate_wpos(GLcontext *ctx, SWspan *span)
+static inline void
+interpolate_wpos(struct gl_context *ctx, SWspan *span)
 {
-   GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
+   GLfloat (*wpos)[4] = span->array->attribs[VARYING_SLOT_POS];
    GLuint i;
    const GLfloat zScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
    GLfloat w, dw;
@@ -621,8 +643,8 @@ interpolate_wpos(GLcontext *ctx, SWspan *span)
       }
    }
 
-   dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
-   w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dw;
+   dw = span->attrStepX[VARYING_SLOT_POS][3];
+   w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dw;
    for (i = 0; i < span->end; i++) {
       wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
       wpos[i][3] = w;
@@ -634,12 +656,12 @@ interpolate_wpos(GLcontext *ctx, SWspan *span)
 /**
  * Apply the current polygon stipple pattern to a span of pixels.
  */
-static INLINE void
-stipple_polygon_span(GLcontext *ctx, SWspan *span)
+static inline void
+stipple_polygon_span(struct gl_context *ctx, SWspan *span)
 {
    GLubyte *mask = span->array->mask;
 
-   ASSERT(ctx->Polygon.StippleFlag);
+   assert(ctx->Polygon.StippleFlag);
 
    if (span->arrayMask & SPAN_XY) {
       /* arrays of x/y pixel coords */
@@ -679,8 +701,8 @@ stipple_polygon_span(GLcontext *ctx, SWspan *span)
  * Return:   GL_TRUE   some pixels still visible
  *           GL_FALSE  nothing visible
  */
-static INLINE GLuint
-clip_span( GLcontext *ctx, SWspan *span )
+static inline GLuint
+clip_span( struct gl_context *ctx, SWspan *span )
 {
    const GLint xmin = ctx->DrawBuffer->_Xmin;
    const GLint xmax = ctx->DrawBuffer->_Xmax;
@@ -696,11 +718,13 @@ clip_span( GLcontext *ctx, SWspan *span )
       const GLint n = span->end;
       GLubyte *mask = span->array->mask;
       GLint i;
+      GLuint passed = 0;
       if (span->arrayMask & SPAN_MASK) {
          /* note: using & intead of && to reduce branches */
          for (i = 0; i < n; i++) {
             mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
                      & (y[i] >= ymin) & (y[i] < ymax);
+            passed += mask[i];
          }
       }
       else {
@@ -708,9 +732,10 @@ clip_span( GLcontext *ctx, SWspan *span )
          for (i = 0; i < n; i++) {
             mask[i] = (x[i] >= xmin) & (x[i] < xmax)
                     & (y[i] >= ymin) & (y[i] < ymax);
+            passed += mask[i];
          }
       }
-      return GL_TRUE;  /* some pixels visible */
+      return passed > 0;
    }
    else {
       /* horizontal span of pixels */
@@ -726,7 +751,7 @@ clip_span( GLcontext *ctx, SWspan *span )
 
       /* Clip to right */
       if (x + n > xmax) {
-         ASSERT(x < xmax);
+         assert(x < xmax);
          n = span->end = xmax - x;
       }
 
@@ -735,16 +760,16 @@ clip_span( GLcontext *ctx, SWspan *span )
          const GLint leftClip = xmin - x;
          GLuint i;
 
-         ASSERT(leftClip > 0);
-         ASSERT(x + n > xmin);
+         assert(leftClip > 0);
+         assert(x + n > xmin);
 
          /* Clip 'leftClip' pixels from the left side.
           * The span->leftClip field will be applied when we interpolate
           * fragment attributes.
           * For arrays of values, shift them left.
           */
-         for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
-            if (span->interpMask & (1 << i)) {
+         for (i = 0; i < VARYING_SLOT_MAX; i++) {
+            if (span->interpMask & (1u << i)) {
                GLuint j;
                for (j = 0; j < 4; j++) {
                   span->attrStart[i][j] += leftClip * span->attrStepX[i][j];
@@ -762,10 +787,10 @@ clip_span( GLcontext *ctx, SWspan *span )
          span->intTex[1] += leftClip * span->intTexStep[1];
 
 #define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \
-         memcpy(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
+         memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
 
-         for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
-            if (span->arrayAttribs & (1 << i)) {
+         for (i = 0; i < VARYING_SLOT_MAX; i++) {
+            if (span->arrayAttribs & BITFIELD64_BIT(i)) {
                /* shift array elements left by 'leftClip' */
                SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip);
             }
@@ -791,10 +816,10 @@ clip_span( GLcontext *ctx, SWspan *span )
          span->writeAll = GL_FALSE;
       }
 
-      ASSERT(span->x >= xmin);
-      ASSERT(span->x + span->end <= xmax);
-      ASSERT(span->y >= ymin);
-      ASSERT(span->y < ymax);
+      assert(span->x >= xmin);
+      assert(span->x + span->end <= xmax);
+      assert(span->y >= ymin);
+      assert(span->y < ymax);
 
       return GL_TRUE;  /* some pixels visible */
    }
@@ -804,41 +829,41 @@ clip_span( GLcontext *ctx, SWspan *span )
 /**
  * Add specular colors to primary colors.
  * Only called during fixed-function operation.
- * Result is float color array (FRAG_ATTRIB_COL0).
+ * Result is float color array (VARYING_SLOT_COL0).
  */
-static INLINE void
-add_specular(GLcontext *ctx, SWspan *span)
+static inline void
+add_specular(struct gl_context *ctx, SWspan *span)
 {
    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLubyte *mask = span->array->mask;
-   GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
-   GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
+   GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0];
+   GLfloat (*col1)[4] = span->array->attribs[VARYING_SLOT_COL1];
    GLuint i;
 
-   ASSERT(!ctx->FragmentProgram._Current);
-   ASSERT(span->arrayMask & SPAN_RGBA);
-   ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
+   assert(!_swrast_use_fragment_program(ctx));
+   assert(span->arrayMask & SPAN_RGBA);
+   assert(swrast->_ActiveAttribMask & VARYING_BIT_COL1);
    (void) swrast; /* silence warning */
 
    if (span->array->ChanType == GL_FLOAT) {
-      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
-         interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+      if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
+         interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
       }
    }
    else {
       /* need float colors */
-      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+      if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
          interpolate_float_colors(span);
       }
    }
 
-   if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
+   if ((span->arrayAttribs & VARYING_BIT_COL1) == 0) {
       /* XXX could avoid this and interpolate COL1 in the loop below */
-      interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
+      interpolate_active_attribs(ctx, span, VARYING_BIT_COL1);
    }
 
-   ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
-   ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
+   assert(span->arrayAttribs & VARYING_BIT_COL0);
+   assert(span->arrayAttribs & VARYING_BIT_COL1);
 
    for (i = 0; i < span->end; i++) {
       if (mask[i]) {
@@ -855,7 +880,7 @@ add_specular(GLcontext *ctx, SWspan *span)
 /**
  * Apply antialiasing coverage value to alpha values.
  */
-static INLINE void
+static inline void
 apply_aa_coverage(SWspan *span)
 {
    const GLfloat *coverage = span->array->coverage;
@@ -864,20 +889,20 @@ apply_aa_coverage(SWspan *span)
       GLubyte (*rgba)[4] = span->array->rgba8;
       for (i = 0; i < span->end; i++) {
          const GLfloat a = rgba[i][ACOMP] * coverage[i];
-         rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
-         ASSERT(coverage[i] >= 0.0);
-         ASSERT(coverage[i] <= 1.0);
+         rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0F, 255.0F);
+         assert(coverage[i] >= 0.0F);
+         assert(coverage[i] <= 1.0F);
       }
    }
    else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
       GLushort (*rgba)[4] = span->array->rgba16;
       for (i = 0; i < span->end; i++) {
          const GLfloat a = rgba[i][ACOMP] * coverage[i];
-         rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
+         rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0F, 65535.0F);
       }
    }
    else {
-      GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+      GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
       for (i = 0; i < span->end; i++) {
          rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
          /* clamp later */
@@ -889,12 +914,12 @@ apply_aa_coverage(SWspan *span)
 /**
  * Clamp span's float colors to [0,1]
  */
-static INLINE void
+static inline void
 clamp_colors(SWspan *span)
 {
-   GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+   GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
    GLuint i;
-   ASSERT(span->array->ChanType == GL_FLOAT);
+   assert(span->array->ChanType == GL_FLOAT);
    for (i = 0; i < span->end; i++) {
       rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
       rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
@@ -910,20 +935,20 @@ clamp_colors(SWspan *span)
  * program that writes to gl_FragData[1] or higher.
  * \param output  which fragment program color output is being processed
  */
-static INLINE void
-convert_color_type(SWspan *span, GLenum newType, GLuint output)
+static inline void
+convert_color_type(SWspan *span, GLenum srcType, GLenum newType, GLuint output)
 {
    GLvoid *src, *dst;
 
-   if (output > 0 || span->array->ChanType == GL_FLOAT) {
-      src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
+   if (output > 0 || srcType == GL_FLOAT) {
+      src = span->array->attribs[VARYING_SLOT_COL0 + output];
       span->array->ChanType = GL_FLOAT;
    }
-   else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+   else if (srcType == GL_UNSIGNED_BYTE) {
       src = span->array->rgba8;
    }
    else {
-      ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT);
+      assert(srcType == GL_UNSIGNED_SHORT);
       src = span->array->rgba16;
    }
 
@@ -934,7 +959,7 @@ convert_color_type(SWspan *span, GLenum newType, GLuint output)
       dst = span->array->rgba16;
    }
    else {
-      dst = span->array->attribs[FRAG_ATTRIB_COL0];
+      dst = span->array->attribs[VARYING_SLOT_COL0];
    }
 
    _mesa_convert_colors(span->array->ChanType, src,
@@ -950,28 +975,17 @@ convert_color_type(SWspan *span, GLenum newType, GLuint output)
 /**
  * Apply fragment shader, fragment program or normal texturing to span.
  */
-static INLINE void
-shade_texture_span(GLcontext *ctx, SWspan *span)
+static inline void
+shade_texture_span(struct gl_context *ctx, SWspan *span)
 {
-   GLbitfield inputsRead;
-
-   /* Determine which fragment attributes are actually needed */
-   if (ctx->FragmentProgram._Current) {
-      inputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
-   }
-   else {
-      /* XXX we could be a bit smarter about this */
-      inputsRead = ~0;
-   }
-
-   if (ctx->FragmentProgram._Current ||
-       ctx->ATIFragmentShader._Enabled) {
+   if (_swrast_use_fragment_program(ctx) ||
+       _mesa_ati_fragment_shader_enabled(ctx)) {
       /* programmable shading */
       if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
-         convert_color_type(span, GL_FLOAT, 0);
+         convert_color_type(span, span->array->ChanType, GL_FLOAT, 0);
       }
       else {
-         span->array->rgba = (void *) span->array->attribs[FRAG_ATTRIB_COL0];
+         span->array->rgba = (void *) span->array->attribs[VARYING_SLOT_COL0];
       }
 
       if (span->primitive != GL_POINT ||
@@ -986,18 +1000,18 @@ shade_texture_span(GLcontext *ctx, SWspan *span)
          _swrast_span_interpolate_z (ctx, span);
 
 #if 0
-      if (inputsRead & FRAG_BIT_WPOS)
+      if (inputsRead & VARYING_BIT_POS)
 #else
       /* XXX always interpolate wpos so that DDX/DDY work */
 #endif
          interpolate_wpos(ctx, span);
 
       /* Run fragment program/shader now */
-      if (ctx->FragmentProgram._Current) {
+      if (_swrast_use_fragment_program(ctx)) {
          _swrast_exec_fragment_program(ctx, span);
       }
       else {
-         ASSERT(ctx->ATIFragmentShader._Enabled);
+         assert(_mesa_ati_fragment_shader_enabled(ctx));
          _swrast_exec_fragment_shader(ctx, span);
       }
    }
@@ -1005,14 +1019,14 @@ shade_texture_span(GLcontext *ctx, SWspan *span)
       /* conventional texturing */
 
 #if CHAN_BITS == 32
-      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
+      if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
          interpolate_int_colors(ctx, span);
       }
 #else
       if (!(span->arrayMask & SPAN_RGBA))
          interpolate_int_colors(ctx, span);
 #endif
-      if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0)
+      if ((span->arrayAttribs & VARYING_BITS_TEX_ANY) == 0x0)
          interpolate_texcoords(ctx, span);
 
       _swrast_texture_span(ctx, span);
@@ -1020,6 +1034,94 @@ shade_texture_span(GLcontext *ctx, SWspan *span)
 }
 
 
+/** Put colors at x/y locations into a renderbuffer */
+static void
+put_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
+           GLenum datatype,
+           GLuint count, const GLint x[], const GLint y[],
+           const void *values, const GLubyte *mask)
+{
+   mesa_pack_ubyte_rgba_func pack_ubyte = NULL;
+   mesa_pack_float_rgba_func pack_float = NULL;
+   GLuint i;
+
+   if (datatype == GL_UNSIGNED_BYTE)
+      pack_ubyte = _mesa_get_pack_ubyte_rgba_function(rb->Format);
+   else
+      pack_float = _mesa_get_pack_float_rgba_function(rb->Format);
+
+   for (i = 0; i < count; i++) {
+      if (mask[i]) {
+         GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
+
+         if (datatype == GL_UNSIGNED_BYTE) {
+            pack_ubyte((const GLubyte *) values + 4 * i, dst);
+         }
+         else {
+            assert(datatype == GL_FLOAT);
+            pack_float((const GLfloat *) values + 4 * i, dst);
+         }
+      }
+   }
+}
+
+
+/** Put row of colors into renderbuffer */
+void
+_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
+                GLenum datatype,
+                GLuint count, GLint x, GLint y,
+                const void *values, const GLubyte *mask)
+{
+   GLubyte *dst = _swrast_pixel_address(rb, x, y);
+
+   if (!mask) {
+      if (datatype == GL_UNSIGNED_BYTE) {
+         _mesa_pack_ubyte_rgba_row(rb->Format, count,
+                                   (const GLubyte (*)[4]) values, dst);
+      }
+      else {
+         assert(datatype == GL_FLOAT);
+         _mesa_pack_float_rgba_row(rb->Format, count,
+                                   (const GLfloat (*)[4]) values, dst);
+      }
+   }
+   else {
+      const GLuint bpp = _mesa_get_format_bytes(rb->Format);
+      GLuint i, runLen, runStart;
+      /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions
+       * so look for runs where mask=1...
+       */
+      runLen = runStart = 0;
+      for (i = 0; i < count; i++) {
+         if (mask[i]) {
+            if (runLen == 0)
+               runStart = i;
+            runLen++;
+         }
+
+         if (!mask[i] || i == count - 1) {
+            /* might be the end of a run of pixels */
+            if (runLen > 0) {
+               if (datatype == GL_UNSIGNED_BYTE) {
+                  _mesa_pack_ubyte_rgba_row(rb->Format, runLen,
+                                     (const GLubyte (*)[4]) values + runStart,
+                                     dst + runStart * bpp);
+               }
+               else {
+                  assert(datatype == GL_FLOAT);
+                  _mesa_pack_float_rgba_row(rb->Format, runLen,
+                                   (const GLfloat (*)[4]) values + runStart,
+                                   dst + runStart * bpp);
+               }
+               runLen = 0;
+            }
+         }
+      }
+   }
+}
+
+
 
 /**
  * Apply all the per-fragment operations to a span.
@@ -1029,26 +1131,25 @@ shade_texture_span(GLcontext *ctx, SWspan *span)
  * to their original values before returning.
  */
 void
-_swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
+_swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
 {
    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   const GLuint *colorMask = (GLuint *) ctx->Color.ColorMask;
    const GLbitfield origInterpMask = span->interpMask;
    const GLbitfield origArrayMask = span->arrayMask;
-   const GLbitfield origArrayAttribs = span->arrayAttribs;
+   const GLbitfield64 origArrayAttribs = span->arrayAttribs;
    const GLenum origChanType = span->array->ChanType;
    void * const origRgba = span->array->rgba;
-   const GLboolean shader = (ctx->FragmentProgram._Current
-                             || ctx->ATIFragmentShader._Enabled);
+   const GLboolean shader = (_swrast_use_fragment_program(ctx)
+                             || _mesa_ati_fragment_shader_enabled(ctx));
    const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
    struct gl_framebuffer *fb = ctx->DrawBuffer;
 
    /*
-   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
+   printf("%s()  interp 0x%x  array 0x%x\n", __func__,
           span->interpMask, span->arrayMask);
    */
 
-   ASSERT(span->primitive == GL_POINT ||
+   assert(span->primitive == GL_POINT ||
           span->primitive == GL_LINE ||
          span->primitive == GL_POLYGON ||
           span->primitive == GL_BITMAP);
@@ -1068,7 +1169,7 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
       return;
    }
 
-   ASSERT(span->end <= MAX_WIDTH);
+   assert(span->end <= SWRAST_MAX_WIDTH);
 
    /* Depth bounds test */
    if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
@@ -1114,14 +1215,14 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
    }
 
    /* Stencil and Z testing */
-   if (ctx->Stencil._Enabled || ctx->Depth.Test) {
+   if (_mesa_stencil_is_enabled(ctx) || ctx->Depth.Test) {
       if (!(span->arrayMask & SPAN_Z))
          _swrast_span_interpolate_z(ctx, span);
 
-      if (ctx->Transform.DepthClamp)
+      if (ctx->Transform.DepthClampNear && ctx->Transform.DepthClampFar)
         _swrast_depth_clamp_span(ctx, span);
 
-      if (ctx->Stencil._Enabled) {
+      if (_mesa_stencil_is_enabled(ctx)) {
          /* Combined Z/stencil tests */
          if (!_swrast_stencil_and_ztest_span(ctx, span)) {
             /* all fragments failed test */
@@ -1130,8 +1231,8 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
       }
       else if (fb->Visual.depthBits > 0) {
          /* Just regular depth testing */
-         ASSERT(ctx->Depth.Test);
-         ASSERT(span->arrayMask & SPAN_Z);
+         assert(ctx->Depth.Test);
+         assert(span->arrayMask & SPAN_Z);
          if (!_swrast_depth_test_span(ctx, span)) {
             /* all fragments failed test */
             goto end;
@@ -1150,7 +1251,8 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
    /* We had to wait until now to check for glColorMask(0,0,0,0) because of
     * the occlusion test.
     */
-   if (fb->_NumColorDrawBuffers == 1 && colorMask[0] == 0x0) {
+   if (fb->_NumColorDrawBuffers == 1 &&
+       !GET_COLORMASK(ctx->Color.ColorMask, 0)) {
       /* no colors to write */
       goto end;
    }
@@ -1164,8 +1266,8 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
    }
 
 #if CHAN_BITS == 32
-   if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
-      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
+   if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
+      interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
    }
 #else
    if ((span->arrayMask & SPAN_RGBA) == 0) {
@@ -1173,7 +1275,7 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
    }
 #endif
 
-   ASSERT(span->arrayMask & SPAN_RGBA);
+   assert(span->arrayMask & SPAN_RGBA);
 
    if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) {
       /* Add primary and specular (diffuse + specular) colors */
@@ -1211,9 +1313,12 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
     */
    {
       const GLuint numBuffers = fb->_NumColorDrawBuffers;
-      const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
-      const GLboolean multiFragOutputs = 
-         (fp && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0));
+      const struct gl_program *fp = ctx->FragmentProgram._Current;
+      const GLboolean multiFragOutputs =
+         _swrast_use_fragment_program(ctx)
+         && fp->info.outputs_written >= (1 << FRAG_RESULT_DATA0);
+      /* Save srcColorType because convert_color_type() can change it */
+      const GLenum srcColorType = span->array->ChanType;
       GLuint buf;
 
       for (buf = 0; buf < numBuffers; buf++) {
@@ -1222,23 +1327,26 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
          /* color[fragOutput] will be written to buffer[buf] */
 
          if (rb) {
-            GLchan rgbaSave[MAX_WIDTH][4];
-            const GLuint fragOutput = multiFragOutputs ? buf : 0;
-
-            /* set span->array->rgba to colors for render buffer's datatype */
-            if (rb->DataType != span->array->ChanType || fragOutput > 0) {
-               convert_color_type(span, rb->DataType, fragOutput);
+            /* re-use one of the attribute array buffers for rgbaSave */
+            GLchan (*rgbaSave)[4] = (GLchan (*)[4]) span->array->attribs[0];
+            struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+            const GLenum dstColorType = srb->ColorType;
+
+            assert(dstColorType == GL_UNSIGNED_BYTE ||
+                   dstColorType == GL_FLOAT);
+
+            /* set span->array->rgba to colors for renderbuffer's datatype */
+            if (srcColorType != dstColorType) {
+               convert_color_type(span, srcColorType, dstColorType,
+                                  multiFragOutputs ? buf : 0);
             }
             else {
-               if (rb->DataType == GL_UNSIGNED_BYTE) {
+               if (srcColorType == GL_UNSIGNED_BYTE) {
                   span->array->rgba = span->array->rgba8;
                }
-               else if (rb->DataType == GL_UNSIGNED_SHORT) {
-                  span->array->rgba = (void *) span->array->rgba16;
-               }
                else {
                   span->array->rgba = (void *)
-                     span->array->attribs[FRAG_ATTRIB_COL0];
+                     span->array->attribs[VARYING_SLOT_COL0];
                }
             }
 
@@ -1248,32 +1356,37 @@ _swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
                       4 * span->end * sizeof(GLchan));
             }
 
-            ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
+            assert(rb->_BaseFormat == GL_RGBA ||
+                   rb->_BaseFormat == GL_RGB ||
+                   rb->_BaseFormat == GL_RED ||
+                   rb->_BaseFormat == GL_RG ||
+                  rb->_BaseFormat == GL_ALPHA);
 
-            if (ctx->Color._LogicOpEnabled) {
+            if (ctx->Color.ColorLogicOpEnabled) {
                _swrast_logicop_rgba_span(ctx, rb, span);
             }
             else if ((ctx->Color.BlendEnabled >> buf) & 1) {
                _swrast_blend_span(ctx, rb, span);
             }
 
-            if (colorMask[buf] != 0xffffffff) {
+            if (GET_COLORMASK(ctx->Color.ColorMask, buf) != 0xf) {
                _swrast_mask_rgba_span(ctx, rb, span, buf);
             }
 
             if (span->arrayMask & SPAN_XY) {
                /* array of pixel coords */
-               ASSERT(rb->PutValues);
-               rb->PutValues(ctx, rb, span->end,
-                             span->array->x, span->array->y,
-                             span->array->rgba, span->array->mask);
+               put_values(ctx, rb,
+                          span->array->ChanType, span->end,
+                          span->array->x, span->array->y,
+                          span->array->rgba, span->array->mask);
             }
             else {
                /* horizontal run of pixels */
-               ASSERT(rb->PutRow);
-               rb->PutRow(ctx, rb, span->end, span->x, span->y,
-                          span->array->rgba,
-                          span->writeAll ? NULL: span->array->mask);
+               _swrast_put_row(ctx, rb,
+                               span->array->ChanType,
+                               span->end, span->x, span->y,
+                               span->array->rgba,
+                               span->writeAll ? NULL: span->array->mask);
             }
 
             if (!multiFragOutputs && numBuffers > 1) {
@@ -1297,16 +1410,17 @@ end:
 
 
 /**
- * Read RGBA pixels from a renderbuffer.  Clipping will be done to prevent
- * reading ouside the buffer's boundaries.
- * \param dstType  datatype for returned colors
+ * Read float RGBA pixels from a renderbuffer.  Clipping will be done to
+ * prevent reading ouside the buffer's boundaries.
  * \param rgba  the returned colors
  */
 void
-_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
-                        GLuint n, GLint x, GLint y, GLenum dstType,
+_swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
+                        GLuint n, GLint x, GLint y,
                         GLvoid *rgba)
 {
+   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+   GLenum dstType = GL_FLOAT;
    const GLint bufWidth = (GLint) rb->Width;
    const GLint bufHeight = (GLint) rb->Height;
 
@@ -1317,6 +1431,8 @@ _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
    }
    else {
       GLint skip, length;
+      GLubyte *src;
+
       if (x < 0) {
          /* left edge clipping */
          skip = -x;
@@ -1344,74 +1460,80 @@ _swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
          length = (GLint) n;
       }
 
-      ASSERT(rb);
-      ASSERT(rb->GetRow);
-      ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
+      assert(rb);
+      assert(rb->_BaseFormat == GL_RGBA ||
+            rb->_BaseFormat == GL_RGB ||
+            rb->_BaseFormat == GL_RG ||
+            rb->_BaseFormat == GL_RED ||
+            rb->_BaseFormat == GL_LUMINANCE ||
+            rb->_BaseFormat == GL_INTENSITY ||
+            rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
+            rb->_BaseFormat == GL_ALPHA);
 
-      if (rb->DataType == dstType) {
-         rb->GetRow(ctx, rb, length, x + skip, y,
-                    (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
+      assert(srb->Map);
+      (void) srb; /* silence unused var warning */
+
+      src = _swrast_pixel_address(rb, x + skip, y);
+
+      if (dstType == GL_UNSIGNED_BYTE) {
+         _mesa_unpack_ubyte_rgba_row(rb->Format, length, src,
+                                     (GLubyte (*)[4]) rgba + skip);
+      }
+      else if (dstType == GL_FLOAT) {
+         _mesa_unpack_rgba_row(rb->Format, length, src,
+                               (GLfloat (*)[4]) rgba + skip);
       }
       else {
-         GLuint temp[MAX_WIDTH * 4];
-         rb->GetRow(ctx, rb, length, x + skip, y, temp);
-         _mesa_convert_colors(rb->DataType, temp,
-                   dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
-                   length, NULL);
+         _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()");
       }
    }
 }
 
 
 /**
- * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
- * reading values outside the buffer bounds.
- * We can use this for reading any format/type of renderbuffer.
- * \param valueSize is the size in bytes of each value (pixel) put into the
- *                  values array.
+ * Get colors at x/y positions with clipping.
+ * \param type  type of values to return
  */
-void
-_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
-                   GLuint count, const GLint x[], const GLint y[],
-                   void *values, GLuint valueSize)
+static void
+get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
+           GLuint count, const GLint x[], const GLint y[],
+           void *values, GLenum type)
 {
-   GLuint i, inCount = 0, inStart = 0;
+   GLuint i;
 
    for (i = 0; i < count; i++) {
       if (x[i] >= 0 && y[i] >= 0 &&
          x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
          /* inside */
-         if (inCount == 0)
-            inStart = i;
-         inCount++;
-      }
-      else {
-         if (inCount > 0) {
-            /* read [inStart, inStart + inCount) */
-            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
-                          (GLubyte *) values + inStart * valueSize);
-            inCount = 0;
+         const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]);
+
+         if (type == GL_UNSIGNED_BYTE) {
+            _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src,
+                                        (GLubyte (*)[4]) values + i);
+         }
+         else if (type == GL_FLOAT) {
+            _mesa_unpack_rgba_row(rb->Format, 1, src,
+                                  (GLfloat (*)[4]) values + i);
+         }
+         else {
+            _mesa_problem(ctx, "unexpected type in get_values()");
          }
       }
    }
-   if (inCount > 0) {
-      /* read last values */
-      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
-                    (GLubyte *) values + inStart * valueSize);
-   }
 }
 
 
 /**
- * Wrapper for gl_renderbuffer::PutRow() which does clipping.
- * \param valueSize  size of each value (pixel) in bytes
+ * Get row of colors with clipping.
+ * \param type  type of values to return
  */
-void
-_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
-                GLuint count, GLint x, GLint y,
-                const GLvoid *values, GLuint valueSize)
+static void
+get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
+        GLuint count, GLint x, GLint y,
+        GLvoid *values, GLenum type)
 {
    GLint skip = 0;
+   GLubyte *src;
 
    if (y < 0 || y >= (GLint) rb->Height)
       return; /* above or below */
@@ -1419,7 +1541,7 @@ _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
    if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
       return; /* entirely left or right */
 
-   if ((GLint) (x + count) > (GLint) rb->Width) {
+   if (x + count > rb->Width) {
       /* right clip */
       GLint clip = x + count - rb->Width;
       count -= clip;
@@ -1432,42 +1554,19 @@ _swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
       count -= skip;
    }
 
-   rb->PutRow(ctx, rb, count, x, y,
-              (const GLubyte *) values + skip * valueSize, NULL);
-}
-
-
-/**
- * Wrapper for gl_renderbuffer::GetRow() which does clipping.
- * \param valueSize  size of each value (pixel) in bytes
- */
-void
-_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
-                GLuint count, GLint x, GLint y,
-                GLvoid *values, GLuint valueSize)
-{
-   GLint skip = 0;
-
-   if (y < 0 || y >= (GLint) rb->Height)
-      return; /* above or below */
-
-   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
-      return; /* entirely left or right */
+   src = _swrast_pixel_address(rb, x, y);
 
-   if (x + count > rb->Width) {
-      /* right clip */
-      GLint clip = x + count - rb->Width;
-      count -= clip;
+   if (type == GL_UNSIGNED_BYTE) {
+      _mesa_unpack_ubyte_rgba_row(rb->Format, count, src,
+                                  (GLubyte (*)[4]) values + skip);
    }
-
-   if (x < 0) {
-      /* left clip */
-      skip = -x;
-      x = 0;
-      count -= skip;
+   else if (type == GL_FLOAT) {
+      _mesa_unpack_rgba_row(rb->Format, count, src,
+                            (GLfloat (*)[4]) values + skip);
+   }
+   else {
+      _mesa_problem(ctx, "unexpected type in get_row()");
    }
-
-   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
 }
 
 
@@ -1477,23 +1576,22 @@ _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
  * \return pointer to the colors we read.
  */
 void *
-_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+_swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
                       SWspan *span)
 {
-   const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
    void *rbPixels;
 
    /* Point rbPixels to a temporary space */
-   rbPixels = span->array->attribs[FRAG_ATTRIB_MAX - 1];
+   rbPixels = span->array->attribs[VARYING_SLOT_MAX - 1];
 
    /* Get destination values from renderbuffer */
    if (span->arrayMask & SPAN_XY) {
-      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
-                         rbPixels, pixelSize);
+      get_values(ctx, rb, span->end, span->array->x, span->array->y,
+                 rbPixels, span->array->ChanType);
    }
    else {
-      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
-                      rbPixels, pixelSize);
+      get_row(ctx, rb, span->end, span->x, span->y,
+              rbPixels, span->array->ChanType);
    }
 
    return rbPixels;