Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
      5  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 
     27 /**
     28  * \file swrast/s_span.c
     29  * \brief Span processing functions used by all rasterization functions.
     30  * This is where all the per-fragment tests are performed
     31  * \author Brian Paul
     32  */
     33 
     34 #include "c99_math.h"
     35 #include "main/glheader.h"
     36 #include "main/format_pack.h"
     37 #include "main/format_unpack.h"
     38 #include "main/macros.h"
     39 #include "main/imports.h"
     40 #include "main/image.h"
     41 #include "main/samplerobj.h"
     42 #include "main/state.h"
     43 #include "main/stencil.h"
     44 #include "main/teximage.h"
     45 
     46 #include "s_atifragshader.h"
     47 #include "s_alpha.h"
     48 #include "s_blend.h"
     49 #include "s_context.h"
     50 #include "s_depth.h"
     51 #include "s_fog.h"
     52 #include "s_logic.h"
     53 #include "s_masking.h"
     54 #include "s_fragprog.h"
     55 #include "s_span.h"
     56 #include "s_stencil.h"
     57 #include "s_texcombine.h"
     58 
     59 #include <stdbool.h>
     60 
     61 /**
     62  * Set default fragment attributes for the span using the
     63  * current raster values.  Used prior to glDraw/CopyPixels
     64  * and glBitmap.
     65  */
     66 void
     67 _swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
     68 {
     69    GLchan r, g, b, a;
     70    /* Z*/
     71    {
     72       const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
     73       if (ctx->DrawBuffer->Visual.depthBits <= 16)
     74          span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
     75       else {
     76          GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax;
     77          tmpf = MIN2(tmpf, depthMax);
     78          span->z = (GLint)tmpf;
     79       }
     80       span->zStep = 0;
     81       span->interpMask |= SPAN_Z;
     82    }
     83 
     84    /* W (for perspective correction) */
     85    span->attrStart[VARYING_SLOT_POS][3] = 1.0;
     86    span->attrStepX[VARYING_SLOT_POS][3] = 0.0;
     87    span->attrStepY[VARYING_SLOT_POS][3] = 0.0;
     88 
     89    /* primary color, or color index */
     90    UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
     91    UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
     92    UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
     93    UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
     94 #if CHAN_TYPE == GL_FLOAT
     95    span->red = r;
     96    span->green = g;
     97    span->blue = b;
     98    span->alpha = a;
     99 #else
    100    span->red   = IntToFixed(r);
    101    span->green = IntToFixed(g);
    102    span->blue  = IntToFixed(b);
    103    span->alpha = IntToFixed(a);
    104 #endif
    105    span->redStep = 0;
    106    span->greenStep = 0;
    107    span->blueStep = 0;
    108    span->alphaStep = 0;
    109    span->interpMask |= SPAN_RGBA;
    110 
    111    COPY_4V(span->attrStart[VARYING_SLOT_COL0], ctx->Current.RasterColor);
    112    ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0);
    113    ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0);
    114 
    115    /* Secondary color */
    116    if (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled)
    117    {
    118       COPY_4V(span->attrStart[VARYING_SLOT_COL1], ctx->Current.RasterSecondaryColor);
    119       ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0);
    120       ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0);
    121    }
    122 
    123    /* fog */
    124    {
    125       const SWcontext *swrast = SWRAST_CONTEXT(ctx);
    126       GLfloat fogVal; /* a coord or a blend factor */
    127       if (swrast->_PreferPixelFog) {
    128          /* fog blend factors will be computed from fog coordinates per pixel */
    129          fogVal = ctx->Current.RasterDistance;
    130       }
    131       else {
    132          /* fog blend factor should be computed from fogcoord now */
    133          fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
    134       }
    135       span->attrStart[VARYING_SLOT_FOGC][0] = fogVal;
    136       span->attrStepX[VARYING_SLOT_FOGC][0] = 0.0;
    137       span->attrStepY[VARYING_SLOT_FOGC][0] = 0.0;
    138    }
    139 
    140    /* texcoords */
    141    {
    142       GLuint i;
    143       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
    144          const GLuint attr = VARYING_SLOT_TEX0 + i;
    145          const GLfloat *tc = ctx->Current.RasterTexCoords[i];
    146          if (_swrast_use_fragment_program(ctx) ||
    147              _mesa_ati_fragment_shader_enabled(ctx)) {
    148             COPY_4V(span->attrStart[attr], tc);
    149          }
    150          else if (tc[3] > 0.0F) {
    151             /* use (s/q, t/q, r/q, 1) */
    152             span->attrStart[attr][0] = tc[0] / tc[3];
    153             span->attrStart[attr][1] = tc[1] / tc[3];
    154             span->attrStart[attr][2] = tc[2] / tc[3];
    155             span->attrStart[attr][3] = 1.0;
    156          }
    157          else {
    158             ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
    159          }
    160          ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
    161          ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
    162       }
    163    }
    164 }
    165 
    166 
    167 /**
    168  * Interpolate the active attributes (and'd with attrMask) to
    169  * fill in span->array->attribs[].
    170  * Perspective correction will be done.  The point/line/triangle function
    171  * should have computed attrStart/Step values for VARYING_SLOT_POS[3]!
    172  */
    173 static inline void
    174 interpolate_active_attribs(struct gl_context *ctx, SWspan *span,
    175                            GLbitfield64 attrMask)
    176 {
    177    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
    178 
    179    /*
    180     * Don't overwrite existing array values, such as colors that may have
    181     * been produced by glDraw/CopyPixels.
    182     */
    183    attrMask &= ~span->arrayAttribs;
    184 
    185    ATTRIB_LOOP_BEGIN
    186       if (attrMask & BITFIELD64_BIT(attr)) {
    187          const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
    188          GLfloat w = span->attrStart[VARYING_SLOT_POS][3];
    189          const GLfloat dv0dx = span->attrStepX[attr][0];
    190          const GLfloat dv1dx = span->attrStepX[attr][1];
    191          const GLfloat dv2dx = span->attrStepX[attr][2];
    192          const GLfloat dv3dx = span->attrStepX[attr][3];
    193          GLfloat v0 = span->attrStart[attr][0] + span->leftClip * dv0dx;
    194          GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx;
    195          GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx;
    196          GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx;
    197          GLuint k;
    198          for (k = 0; k < span->end; k++) {
    199             const GLfloat invW = 1.0f / w;
    200             span->array->attribs[attr][k][0] = v0 * invW;
    201             span->array->attribs[attr][k][1] = v1 * invW;
    202             span->array->attribs[attr][k][2] = v2 * invW;
    203             span->array->attribs[attr][k][3] = v3 * invW;
    204             v0 += dv0dx;
    205             v1 += dv1dx;
    206             v2 += dv2dx;
    207             v3 += dv3dx;
    208             w += dwdx;
    209          }
    210          assert((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0);
    211          span->arrayAttribs |= BITFIELD64_BIT(attr);
    212       }
    213    ATTRIB_LOOP_END
    214 }
    215 
    216 
    217 /**
    218  * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
    219  * color array.
    220  */
    221 static inline void
    222 interpolate_int_colors(struct gl_context *ctx, SWspan *span)
    223 {
    224 #if CHAN_BITS != 32
    225    const GLuint n = span->end;
    226    GLuint i;
    227 
    228    assert(!(span->arrayMask & SPAN_RGBA));
    229 #endif
    230 
    231    switch (span->array->ChanType) {
    232 #if CHAN_BITS != 32
    233    case GL_UNSIGNED_BYTE:
    234       {
    235          GLubyte (*rgba)[4] = span->array->rgba8;
    236          if (span->interpMask & SPAN_FLAT) {
    237             GLubyte color[4];
    238             color[RCOMP] = FixedToInt(span->red);
    239             color[GCOMP] = FixedToInt(span->green);
    240             color[BCOMP] = FixedToInt(span->blue);
    241             color[ACOMP] = FixedToInt(span->alpha);
    242             for (i = 0; i < n; i++) {
    243                COPY_4UBV(rgba[i], color);
    244             }
    245          }
    246          else {
    247             GLfixed r = span->red;
    248             GLfixed g = span->green;
    249             GLfixed b = span->blue;
    250             GLfixed a = span->alpha;
    251             GLint dr = span->redStep;
    252             GLint dg = span->greenStep;
    253             GLint db = span->blueStep;
    254             GLint da = span->alphaStep;
    255             for (i = 0; i < n; i++) {
    256                rgba[i][RCOMP] = FixedToChan(r);
    257                rgba[i][GCOMP] = FixedToChan(g);
    258                rgba[i][BCOMP] = FixedToChan(b);
    259                rgba[i][ACOMP] = FixedToChan(a);
    260                r += dr;
    261                g += dg;
    262                b += db;
    263                a += da;
    264             }
    265          }
    266       }
    267       break;
    268    case GL_UNSIGNED_SHORT:
    269       {
    270          GLushort (*rgba)[4] = span->array->rgba16;
    271          if (span->interpMask & SPAN_FLAT) {
    272             GLushort color[4];
    273             color[RCOMP] = FixedToInt(span->red);
    274             color[GCOMP] = FixedToInt(span->green);
    275             color[BCOMP] = FixedToInt(span->blue);
    276             color[ACOMP] = FixedToInt(span->alpha);
    277             for (i = 0; i < n; i++) {
    278                COPY_4V(rgba[i], color);
    279             }
    280          }
    281          else {
    282             GLushort (*rgba)[4] = span->array->rgba16;
    283             GLfixed r, g, b, a;
    284             GLint dr, dg, db, da;
    285             r = span->red;
    286             g = span->green;
    287             b = span->blue;
    288             a = span->alpha;
    289             dr = span->redStep;
    290             dg = span->greenStep;
    291             db = span->blueStep;
    292             da = span->alphaStep;
    293             for (i = 0; i < n; i++) {
    294                rgba[i][RCOMP] = FixedToChan(r);
    295                rgba[i][GCOMP] = FixedToChan(g);
    296                rgba[i][BCOMP] = FixedToChan(b);
    297                rgba[i][ACOMP] = FixedToChan(a);
    298                r += dr;
    299                g += dg;
    300                b += db;
    301                a += da;
    302             }
    303          }
    304       }
    305       break;
    306 #endif
    307    case GL_FLOAT:
    308       interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
    309       break;
    310    default:
    311       _mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors",
    312                     span->array->ChanType);
    313    }
    314    span->arrayMask |= SPAN_RGBA;
    315 }
    316 
    317 
    318 /**
    319  * Populate the VARYING_SLOT_COL0 array.
    320  */
    321 static inline void
    322 interpolate_float_colors(SWspan *span)
    323 {
    324    GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0];
    325    const GLuint n = span->end;
    326    GLuint i;
    327 
    328    assert(!(span->arrayAttribs & VARYING_BIT_COL0));
    329 
    330    if (span->arrayMask & SPAN_RGBA) {
    331       /* convert array of int colors */
    332       for (i = 0; i < n; i++) {
    333          col0[i][0] = UBYTE_TO_FLOAT(span->array->rgba8[i][0]);
    334          col0[i][1] = UBYTE_TO_FLOAT(span->array->rgba8[i][1]);
    335          col0[i][2] = UBYTE_TO_FLOAT(span->array->rgba8[i][2]);
    336          col0[i][3] = UBYTE_TO_FLOAT(span->array->rgba8[i][3]);
    337       }
    338    }
    339    else {
    340       /* interpolate red/green/blue/alpha to get float colors */
    341       assert(span->interpMask & SPAN_RGBA);
    342       if (span->interpMask & SPAN_FLAT) {
    343          GLfloat r = FixedToFloat(span->red);
    344          GLfloat g = FixedToFloat(span->green);
    345          GLfloat b = FixedToFloat(span->blue);
    346          GLfloat a = FixedToFloat(span->alpha);
    347          for (i = 0; i < n; i++) {
    348             ASSIGN_4V(col0[i], r, g, b, a);
    349          }
    350       }
    351       else {
    352          GLfloat r = FixedToFloat(span->red);
    353          GLfloat g = FixedToFloat(span->green);
    354          GLfloat b = FixedToFloat(span->blue);
    355          GLfloat a = FixedToFloat(span->alpha);
    356          GLfloat dr = FixedToFloat(span->redStep);
    357          GLfloat dg = FixedToFloat(span->greenStep);
    358          GLfloat db = FixedToFloat(span->blueStep);
    359          GLfloat da = FixedToFloat(span->alphaStep);
    360          for (i = 0; i < n; i++) {
    361             col0[i][0] = r;
    362             col0[i][1] = g;
    363             col0[i][2] = b;
    364             col0[i][3] = a;
    365             r += dr;
    366             g += dg;
    367             b += db;
    368             a += da;
    369          }
    370       }
    371    }
    372 
    373    span->arrayAttribs |= VARYING_BIT_COL0;
    374    span->array->ChanType = GL_FLOAT;
    375 }
    376 
    377 
    378 
    379 /**
    380  * Fill in the span.zArray array from the span->z, zStep values.
    381  */
    382 void
    383 _swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span )
    384 {
    385    const GLuint n = span->end;
    386    GLuint i;
    387 
    388    assert(!(span->arrayMask & SPAN_Z));
    389 
    390    if (ctx->DrawBuffer->Visual.depthBits <= 16) {
    391       GLfixed zval = span->z;
    392       GLuint *z = span->array->z;
    393       for (i = 0; i < n; i++) {
    394          z[i] = FixedToInt(zval);
    395          zval += span->zStep;
    396       }
    397    }
    398    else {
    399       /* Deep Z buffer, no fixed->int shift */
    400       GLuint zval = span->z;
    401       GLuint *z = span->array->z;
    402       for (i = 0; i < n; i++) {
    403          z[i] = zval;
    404          zval += span->zStep;
    405       }
    406    }
    407    span->interpMask &= ~SPAN_Z;
    408    span->arrayMask |= SPAN_Z;
    409 }
    410 
    411 
    412 /**
    413  * Compute mipmap LOD from partial derivatives.
    414  * This the ideal solution, as given in the OpenGL spec.
    415  */
    416 GLfloat
    417 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
    418                        GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
    419                        GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
    420 {
    421    GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
    422    GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
    423    GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
    424    GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
    425    GLfloat x = sqrtf(dudx * dudx + dvdx * dvdx);
    426    GLfloat y = sqrtf(dudy * dudy + dvdy * dvdy);
    427    GLfloat rho = MAX2(x, y);
    428    GLfloat lambda = LOG2(rho);
    429    return lambda;
    430 }
    431 
    432 
    433 /**
    434  * Compute mipmap LOD from partial derivatives.
    435  * This is a faster approximation than above function.
    436  */
    437 #if 0
    438 GLfloat
    439 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
    440                      GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
    441                      GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
    442 {
    443    GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
    444    GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
    445    GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
    446    GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
    447    GLfloat maxU, maxV, rho, lambda;
    448    dsdx2 = fabsf(dsdx2);
    449    dsdy2 = fabsf(dsdy2);
    450    dtdx2 = fabsf(dtdx2);
    451    dtdy2 = fabsf(dtdy2);
    452    maxU = MAX2(dsdx2, dsdy2) * texW;
    453    maxV = MAX2(dtdx2, dtdy2) * texH;
    454    rho = MAX2(maxU, maxV);
    455    lambda = LOG2(rho);
    456    return lambda;
    457 }
    458 #endif
    459 
    460 
    461 /**
    462  * Fill in the span.array->attrib[VARYING_SLOT_TEXn] arrays from the
    463  * using the attrStart/Step values.
    464  *
    465  * This function only used during fixed-function fragment processing.
    466  *
    467  * Note: in the places where we divide by Q (or mult by invQ) we're
    468  * really doing two things: perspective correction and texcoord
    469  * projection.  Remember, for texcoord (s,t,r,q) we need to index
    470  * texels with (s/q, t/q, r/q).
    471  */
    472 static void
    473 interpolate_texcoords(struct gl_context *ctx, SWspan *span)
    474 {
    475    const GLuint maxUnit
    476       = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
    477    GLuint u;
    478 
    479    /* XXX CoordUnits vs. ImageUnits */
    480    for (u = 0; u < maxUnit; u++) {
    481       if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
    482          const GLuint attr = VARYING_SLOT_TEX0 + u;
    483          const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
    484          GLfloat texW, texH;
    485          GLboolean needLambda;
    486          GLfloat (*texcoord)[4] = span->array->attribs[attr];
    487          GLfloat *lambda = span->array->lambda[u];
    488          const GLfloat dsdx = span->attrStepX[attr][0];
    489          const GLfloat dsdy = span->attrStepY[attr][0];
    490          const GLfloat dtdx = span->attrStepX[attr][1];
    491          const GLfloat dtdy = span->attrStepY[attr][1];
    492          const GLfloat drdx = span->attrStepX[attr][2];
    493          const GLfloat dqdx = span->attrStepX[attr][3];
    494          const GLfloat dqdy = span->attrStepY[attr][3];
    495          GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
    496          GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
    497          GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx;
    498          GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
    499 
    500          if (obj) {
    501             const struct gl_texture_image *img = _mesa_base_tex_image(obj);
    502             const struct swrast_texture_image *swImg =
    503                swrast_texture_image_const(img);
    504             const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, u);
    505 
    506             needLambda = (samp->MinFilter != samp->MagFilter)
    507                || _swrast_use_fragment_program(ctx);
    508             /* LOD is calculated directly in the ansiotropic filter, we can
    509              * skip the normal lambda function as the result is ignored.
    510              */
    511             if (samp->MaxAnisotropy > 1.0F &&
    512                 samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
    513                needLambda = GL_FALSE;
    514             }
    515             texW = swImg->WidthScale;
    516             texH = swImg->HeightScale;
    517          }
    518          else {
    519             /* using a fragment program */
    520             texW = 1.0;
    521             texH = 1.0;
    522             needLambda = GL_FALSE;
    523          }
    524 
    525          if (needLambda) {
    526             GLuint i;
    527             if (_swrast_use_fragment_program(ctx)
    528                 || _mesa_ati_fragment_shader_enabled(ctx)) {
    529                /* do perspective correction but don't divide s, t, r by q */
    530                const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
    531                GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx;
    532                for (i = 0; i < span->end; i++) {
    533                   const GLfloat invW = 1.0F / w;
    534                   texcoord[i][0] = s * invW;
    535                   texcoord[i][1] = t * invW;
    536                   texcoord[i][2] = r * invW;
    537                   texcoord[i][3] = q * invW;
    538                   lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
    539                                                      dqdx, dqdy, texW, texH,
    540                                                      s, t, q, invW);
    541                   s += dsdx;
    542                   t += dtdx;
    543                   r += drdx;
    544                   q += dqdx;
    545                   w += dwdx;
    546                }
    547             }
    548             else {
    549                for (i = 0; i < span->end; i++) {
    550                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
    551                   texcoord[i][0] = s * invQ;
    552                   texcoord[i][1] = t * invQ;
    553                   texcoord[i][2] = r * invQ;
    554                   texcoord[i][3] = q;
    555                   lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
    556                                                      dqdx, dqdy, texW, texH,
    557                                                      s, t, q, invQ);
    558                   s += dsdx;
    559                   t += dtdx;
    560                   r += drdx;
    561                   q += dqdx;
    562                }
    563             }
    564             span->arrayMask |= SPAN_LAMBDA;
    565          }
    566          else {
    567             GLuint i;
    568             if (_swrast_use_fragment_program(ctx) ||
    569                 _mesa_ati_fragment_shader_enabled(ctx)) {
    570                /* do perspective correction but don't divide s, t, r by q */
    571                const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3];
    572                GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx;
    573                for (i = 0; i < span->end; i++) {
    574                   const GLfloat invW = 1.0F / w;
    575                   texcoord[i][0] = s * invW;
    576                   texcoord[i][1] = t * invW;
    577                   texcoord[i][2] = r * invW;
    578                   texcoord[i][3] = q * invW;
    579                   lambda[i] = 0.0;
    580                   s += dsdx;
    581                   t += dtdx;
    582                   r += drdx;
    583                   q += dqdx;
    584                   w += dwdx;
    585                }
    586             }
    587             else if (dqdx == 0.0F) {
    588                /* Ortho projection or polygon's parallel to window X axis */
    589                const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
    590                for (i = 0; i < span->end; i++) {
    591                   texcoord[i][0] = s * invQ;
    592                   texcoord[i][1] = t * invQ;
    593                   texcoord[i][2] = r * invQ;
    594                   texcoord[i][3] = q;
    595                   lambda[i] = 0.0;
    596                   s += dsdx;
    597                   t += dtdx;
    598                   r += drdx;
    599                }
    600             }
    601             else {
    602                for (i = 0; i < span->end; i++) {
    603                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
    604                   texcoord[i][0] = s * invQ;
    605                   texcoord[i][1] = t * invQ;
    606                   texcoord[i][2] = r * invQ;
    607                   texcoord[i][3] = q;
    608                   lambda[i] = 0.0;
    609                   s += dsdx;
    610                   t += dtdx;
    611                   r += drdx;
    612                   q += dqdx;
    613                }
    614             }
    615          } /* lambda */
    616       } /* if */
    617    } /* for */
    618 }
    619 
    620 
    621 /**
    622  * Fill in the arrays->attribs[VARYING_SLOT_POS] array.
    623  */
    624 static inline void
    625 interpolate_wpos(struct gl_context *ctx, SWspan *span)
    626 {
    627    GLfloat (*wpos)[4] = span->array->attribs[VARYING_SLOT_POS];
    628    GLuint i;
    629    const GLfloat zScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
    630    GLfloat w, dw;
    631 
    632    if (span->arrayMask & SPAN_XY) {
    633       for (i = 0; i < span->end; i++) {
    634          wpos[i][0] = (GLfloat) span->array->x[i];
    635          wpos[i][1] = (GLfloat) span->array->y[i];
    636       }
    637    }
    638    else {
    639       for (i = 0; i < span->end; i++) {
    640          wpos[i][0] = (GLfloat) span->x + i;
    641          wpos[i][1] = (GLfloat) span->y;
    642       }
    643    }
    644 
    645    dw = span->attrStepX[VARYING_SLOT_POS][3];
    646    w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dw;
    647    for (i = 0; i < span->end; i++) {
    648       wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
    649       wpos[i][3] = w;
    650       w += dw;
    651    }
    652 }
    653 
    654 
    655 /**
    656  * Apply the current polygon stipple pattern to a span of pixels.
    657  */
    658 static inline void
    659 stipple_polygon_span(struct gl_context *ctx, SWspan *span)
    660 {
    661    GLubyte *mask = span->array->mask;
    662 
    663    assert(ctx->Polygon.StippleFlag);
    664 
    665    if (span->arrayMask & SPAN_XY) {
    666       /* arrays of x/y pixel coords */
    667       GLuint i;
    668       for (i = 0; i < span->end; i++) {
    669          const GLint col = span->array->x[i] % 32;
    670          const GLint row = span->array->y[i] % 32;
    671          const GLuint stipple = ctx->PolygonStipple[row];
    672          if (((1 << col) & stipple) == 0) {
    673             mask[i] = 0;
    674          }
    675       }
    676    }
    677    else {
    678       /* horizontal span of pixels */
    679       const GLuint highBit = 1 << 31;
    680       const GLuint stipple = ctx->PolygonStipple[span->y % 32];
    681       GLuint i, m = highBit >> (GLuint) (span->x % 32);
    682       for (i = 0; i < span->end; i++) {
    683          if ((m & stipple) == 0) {
    684             mask[i] = 0;
    685          }
    686          m = m >> 1;
    687          if (m == 0) {
    688             m = highBit;
    689          }
    690       }
    691    }
    692    span->writeAll = GL_FALSE;
    693 }
    694 
    695 
    696 /**
    697  * Clip a pixel span to the current buffer/window boundaries:
    698  * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
    699  * window clipping and scissoring.
    700  * Return:   GL_TRUE   some pixels still visible
    701  *           GL_FALSE  nothing visible
    702  */
    703 static inline GLuint
    704 clip_span( struct gl_context *ctx, SWspan *span )
    705 {
    706    const GLint xmin = ctx->DrawBuffer->_Xmin;
    707    const GLint xmax = ctx->DrawBuffer->_Xmax;
    708    const GLint ymin = ctx->DrawBuffer->_Ymin;
    709    const GLint ymax = ctx->DrawBuffer->_Ymax;
    710 
    711    span->leftClip = 0;
    712 
    713    if (span->arrayMask & SPAN_XY) {
    714       /* arrays of x/y pixel coords */
    715       const GLint *x = span->array->x;
    716       const GLint *y = span->array->y;
    717       const GLint n = span->end;
    718       GLubyte *mask = span->array->mask;
    719       GLint i;
    720       GLuint passed = 0;
    721       if (span->arrayMask & SPAN_MASK) {
    722          /* note: using & intead of && to reduce branches */
    723          for (i = 0; i < n; i++) {
    724             mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
    725                      & (y[i] >= ymin) & (y[i] < ymax);
    726             passed += mask[i];
    727          }
    728       }
    729       else {
    730          /* note: using & intead of && to reduce branches */
    731          for (i = 0; i < n; i++) {
    732             mask[i] = (x[i] >= xmin) & (x[i] < xmax)
    733                     & (y[i] >= ymin) & (y[i] < ymax);
    734             passed += mask[i];
    735          }
    736       }
    737       return passed > 0;
    738    }
    739    else {
    740       /* horizontal span of pixels */
    741       const GLint x = span->x;
    742       const GLint y = span->y;
    743       GLint n = span->end;
    744 
    745       /* Trivial rejection tests */
    746       if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
    747          span->end = 0;
    748          return GL_FALSE;  /* all pixels clipped */
    749       }
    750 
    751       /* Clip to right */
    752       if (x + n > xmax) {
    753          assert(x < xmax);
    754          n = span->end = xmax - x;
    755       }
    756 
    757       /* Clip to the left */
    758       if (x < xmin) {
    759          const GLint leftClip = xmin - x;
    760          GLuint i;
    761 
    762          assert(leftClip > 0);
    763          assert(x + n > xmin);
    764 
    765          /* Clip 'leftClip' pixels from the left side.
    766           * The span->leftClip field will be applied when we interpolate
    767           * fragment attributes.
    768           * For arrays of values, shift them left.
    769           */
    770          for (i = 0; i < VARYING_SLOT_MAX; i++) {
    771             if (span->interpMask & (1 << i)) {
    772                GLuint j;
    773                for (j = 0; j < 4; j++) {
    774                   span->attrStart[i][j] += leftClip * span->attrStepX[i][j];
    775                }
    776             }
    777          }
    778 
    779          span->red += leftClip * span->redStep;
    780          span->green += leftClip * span->greenStep;
    781          span->blue += leftClip * span->blueStep;
    782          span->alpha += leftClip * span->alphaStep;
    783          span->index += leftClip * span->indexStep;
    784          span->z += leftClip * span->zStep;
    785          span->intTex[0] += leftClip * span->intTexStep[0];
    786          span->intTex[1] += leftClip * span->intTexStep[1];
    787 
    788 #define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \
    789          memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
    790 
    791          for (i = 0; i < VARYING_SLOT_MAX; i++) {
    792             if (span->arrayAttribs & BITFIELD64_BIT(i)) {
    793                /* shift array elements left by 'leftClip' */
    794                SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip);
    795             }
    796          }
    797 
    798          SHIFT_ARRAY(span->array->mask, leftClip, n - leftClip);
    799          SHIFT_ARRAY(span->array->rgba8, leftClip, n - leftClip);
    800          SHIFT_ARRAY(span->array->rgba16, leftClip, n - leftClip);
    801          SHIFT_ARRAY(span->array->x, leftClip, n - leftClip);
    802          SHIFT_ARRAY(span->array->y, leftClip, n - leftClip);
    803          SHIFT_ARRAY(span->array->z, leftClip, n - leftClip);
    804          SHIFT_ARRAY(span->array->index, leftClip, n - leftClip);
    805          for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
    806             SHIFT_ARRAY(span->array->lambda[i], leftClip, n - leftClip);
    807          }
    808          SHIFT_ARRAY(span->array->coverage, leftClip, n - leftClip);
    809 
    810 #undef SHIFT_ARRAY
    811 
    812          span->leftClip = leftClip;
    813          span->x = xmin;
    814          span->end -= leftClip;
    815          span->writeAll = GL_FALSE;
    816       }
    817 
    818       assert(span->x >= xmin);
    819       assert(span->x + span->end <= xmax);
    820       assert(span->y >= ymin);
    821       assert(span->y < ymax);
    822 
    823       return GL_TRUE;  /* some pixels visible */
    824    }
    825 }
    826 
    827 
    828 /**
    829  * Add specular colors to primary colors.
    830  * Only called during fixed-function operation.
    831  * Result is float color array (VARYING_SLOT_COL0).
    832  */
    833 static inline void
    834 add_specular(struct gl_context *ctx, SWspan *span)
    835 {
    836    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
    837    const GLubyte *mask = span->array->mask;
    838    GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0];
    839    GLfloat (*col1)[4] = span->array->attribs[VARYING_SLOT_COL1];
    840    GLuint i;
    841 
    842    assert(!_swrast_use_fragment_program(ctx));
    843    assert(span->arrayMask & SPAN_RGBA);
    844    assert(swrast->_ActiveAttribMask & VARYING_BIT_COL1);
    845    (void) swrast; /* silence warning */
    846 
    847    if (span->array->ChanType == GL_FLOAT) {
    848       if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
    849          interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
    850       }
    851    }
    852    else {
    853       /* need float colors */
    854       if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
    855          interpolate_float_colors(span);
    856       }
    857    }
    858 
    859    if ((span->arrayAttribs & VARYING_BIT_COL1) == 0) {
    860       /* XXX could avoid this and interpolate COL1 in the loop below */
    861       interpolate_active_attribs(ctx, span, VARYING_BIT_COL1);
    862    }
    863 
    864    assert(span->arrayAttribs & VARYING_BIT_COL0);
    865    assert(span->arrayAttribs & VARYING_BIT_COL1);
    866 
    867    for (i = 0; i < span->end; i++) {
    868       if (mask[i]) {
    869          col0[i][0] += col1[i][0];
    870          col0[i][1] += col1[i][1];
    871          col0[i][2] += col1[i][2];
    872       }
    873    }
    874 
    875    span->array->ChanType = GL_FLOAT;
    876 }
    877 
    878 
    879 /**
    880  * Apply antialiasing coverage value to alpha values.
    881  */
    882 static inline void
    883 apply_aa_coverage(SWspan *span)
    884 {
    885    const GLfloat *coverage = span->array->coverage;
    886    GLuint i;
    887    if (span->array->ChanType == GL_UNSIGNED_BYTE) {
    888       GLubyte (*rgba)[4] = span->array->rgba8;
    889       for (i = 0; i < span->end; i++) {
    890          const GLfloat a = rgba[i][ACOMP] * coverage[i];
    891          rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0F, 255.0F);
    892          assert(coverage[i] >= 0.0F);
    893          assert(coverage[i] <= 1.0F);
    894       }
    895    }
    896    else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
    897       GLushort (*rgba)[4] = span->array->rgba16;
    898       for (i = 0; i < span->end; i++) {
    899          const GLfloat a = rgba[i][ACOMP] * coverage[i];
    900          rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0F, 65535.0F);
    901       }
    902    }
    903    else {
    904       GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
    905       for (i = 0; i < span->end; i++) {
    906          rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
    907          /* clamp later */
    908       }
    909    }
    910 }
    911 
    912 
    913 /**
    914  * Clamp span's float colors to [0,1]
    915  */
    916 static inline void
    917 clamp_colors(SWspan *span)
    918 {
    919    GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
    920    GLuint i;
    921    assert(span->array->ChanType == GL_FLOAT);
    922    for (i = 0; i < span->end; i++) {
    923       rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
    924       rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
    925       rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
    926       rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
    927    }
    928 }
    929 
    930 
    931 /**
    932  * Convert the span's color arrays to the given type.
    933  * The only way 'output' can be greater than zero is when we have a fragment
    934  * program that writes to gl_FragData[1] or higher.
    935  * \param output  which fragment program color output is being processed
    936  */
    937 static inline void
    938 convert_color_type(SWspan *span, GLenum srcType, GLenum newType, GLuint output)
    939 {
    940    GLvoid *src, *dst;
    941 
    942    if (output > 0 || srcType == GL_FLOAT) {
    943       src = span->array->attribs[VARYING_SLOT_COL0 + output];
    944       span->array->ChanType = GL_FLOAT;
    945    }
    946    else if (srcType == GL_UNSIGNED_BYTE) {
    947       src = span->array->rgba8;
    948    }
    949    else {
    950       assert(srcType == GL_UNSIGNED_SHORT);
    951       src = span->array->rgba16;
    952    }
    953 
    954    if (newType == GL_UNSIGNED_BYTE) {
    955       dst = span->array->rgba8;
    956    }
    957    else if (newType == GL_UNSIGNED_SHORT) {
    958       dst = span->array->rgba16;
    959    }
    960    else {
    961       dst = span->array->attribs[VARYING_SLOT_COL0];
    962    }
    963 
    964    _mesa_convert_colors(span->array->ChanType, src,
    965                         newType, dst,
    966                         span->end, span->array->mask);
    967 
    968    span->array->ChanType = newType;
    969    span->array->rgba = dst;
    970 }
    971 
    972 
    973 
    974 /**
    975  * Apply fragment shader, fragment program or normal texturing to span.
    976  */
    977 static inline void
    978 shade_texture_span(struct gl_context *ctx, SWspan *span)
    979 {
    980    if (_swrast_use_fragment_program(ctx) ||
    981        _mesa_ati_fragment_shader_enabled(ctx)) {
    982       /* programmable shading */
    983       if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
    984          convert_color_type(span, span->array->ChanType, GL_FLOAT, 0);
    985       }
    986       else {
    987          span->array->rgba = (void *) span->array->attribs[VARYING_SLOT_COL0];
    988       }
    989 
    990       if (span->primitive != GL_POINT ||
    991 	  (span->interpMask & SPAN_RGBA) ||
    992 	  ctx->Point.PointSprite) {
    993          /* for single-pixel points, we populated the arrays already */
    994          interpolate_active_attribs(ctx, span, ~0);
    995       }
    996       span->array->ChanType = GL_FLOAT;
    997 
    998       if (!(span->arrayMask & SPAN_Z))
    999          _swrast_span_interpolate_z (ctx, span);
   1000 
   1001 #if 0
   1002       if (inputsRead & VARYING_BIT_POS)
   1003 #else
   1004       /* XXX always interpolate wpos so that DDX/DDY work */
   1005 #endif
   1006          interpolate_wpos(ctx, span);
   1007 
   1008       /* Run fragment program/shader now */
   1009       if (_swrast_use_fragment_program(ctx)) {
   1010          _swrast_exec_fragment_program(ctx, span);
   1011       }
   1012       else {
   1013          assert(_mesa_ati_fragment_shader_enabled(ctx));
   1014          _swrast_exec_fragment_shader(ctx, span);
   1015       }
   1016    }
   1017    else if (ctx->Texture._EnabledCoordUnits) {
   1018       /* conventional texturing */
   1019 
   1020 #if CHAN_BITS == 32
   1021       if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
   1022          interpolate_int_colors(ctx, span);
   1023       }
   1024 #else
   1025       if (!(span->arrayMask & SPAN_RGBA))
   1026          interpolate_int_colors(ctx, span);
   1027 #endif
   1028       if ((span->arrayAttribs & VARYING_BITS_TEX_ANY) == 0x0)
   1029          interpolate_texcoords(ctx, span);
   1030 
   1031       _swrast_texture_span(ctx, span);
   1032    }
   1033 }
   1034 
   1035 
   1036 /** Put colors at x/y locations into a renderbuffer */
   1037 static void
   1038 put_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
   1039            GLenum datatype,
   1040            GLuint count, const GLint x[], const GLint y[],
   1041            const void *values, const GLubyte *mask)
   1042 {
   1043    gl_pack_ubyte_rgba_func pack_ubyte = NULL;
   1044    gl_pack_float_rgba_func pack_float = NULL;
   1045    GLuint i;
   1046 
   1047    if (datatype == GL_UNSIGNED_BYTE)
   1048       pack_ubyte = _mesa_get_pack_ubyte_rgba_function(rb->Format);
   1049    else
   1050       pack_float = _mesa_get_pack_float_rgba_function(rb->Format);
   1051 
   1052    for (i = 0; i < count; i++) {
   1053       if (mask[i]) {
   1054          GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
   1055 
   1056          if (datatype == GL_UNSIGNED_BYTE) {
   1057             pack_ubyte((const GLubyte *) values + 4 * i, dst);
   1058          }
   1059          else {
   1060             assert(datatype == GL_FLOAT);
   1061             pack_float((const GLfloat *) values + 4 * i, dst);
   1062          }
   1063       }
   1064    }
   1065 }
   1066 
   1067 
   1068 /** Put row of colors into renderbuffer */
   1069 void
   1070 _swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
   1071                 GLenum datatype,
   1072                 GLuint count, GLint x, GLint y,
   1073                 const void *values, const GLubyte *mask)
   1074 {
   1075    GLubyte *dst = _swrast_pixel_address(rb, x, y);
   1076 
   1077    if (!mask) {
   1078       if (datatype == GL_UNSIGNED_BYTE) {
   1079          _mesa_pack_ubyte_rgba_row(rb->Format, count,
   1080                                    (const GLubyte (*)[4]) values, dst);
   1081       }
   1082       else {
   1083          assert(datatype == GL_FLOAT);
   1084          _mesa_pack_float_rgba_row(rb->Format, count,
   1085                                    (const GLfloat (*)[4]) values, dst);
   1086       }
   1087    }
   1088    else {
   1089       const GLuint bpp = _mesa_get_format_bytes(rb->Format);
   1090       GLuint i, runLen, runStart;
   1091       /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions
   1092        * so look for runs where mask=1...
   1093        */
   1094       runLen = runStart = 0;
   1095       for (i = 0; i < count; i++) {
   1096          if (mask[i]) {
   1097             if (runLen == 0)
   1098                runStart = i;
   1099             runLen++;
   1100          }
   1101 
   1102          if (!mask[i] || i == count - 1) {
   1103             /* might be the end of a run of pixels */
   1104             if (runLen > 0) {
   1105                if (datatype == GL_UNSIGNED_BYTE) {
   1106                   _mesa_pack_ubyte_rgba_row(rb->Format, runLen,
   1107                                      (const GLubyte (*)[4]) values + runStart,
   1108                                      dst + runStart * bpp);
   1109                }
   1110                else {
   1111                   assert(datatype == GL_FLOAT);
   1112                   _mesa_pack_float_rgba_row(rb->Format, runLen,
   1113                                    (const GLfloat (*)[4]) values + runStart,
   1114                                    dst + runStart * bpp);
   1115                }
   1116                runLen = 0;
   1117             }
   1118          }
   1119       }
   1120    }
   1121 }
   1122 
   1123 
   1124 
   1125 /**
   1126  * Apply all the per-fragment operations to a span.
   1127  * This now includes texturing (_swrast_write_texture_span() is history).
   1128  * This function may modify any of the array values in the span.
   1129  * span->interpMask and span->arrayMask may be changed but will be restored
   1130  * to their original values before returning.
   1131  */
   1132 void
   1133 _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
   1134 {
   1135    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
   1136    const GLuint *colorMask = (GLuint *) ctx->Color.ColorMask;
   1137    const GLbitfield origInterpMask = span->interpMask;
   1138    const GLbitfield origArrayMask = span->arrayMask;
   1139    const GLbitfield64 origArrayAttribs = span->arrayAttribs;
   1140    const GLenum origChanType = span->array->ChanType;
   1141    void * const origRgba = span->array->rgba;
   1142    const GLboolean shader = (_swrast_use_fragment_program(ctx)
   1143                              || _mesa_ati_fragment_shader_enabled(ctx));
   1144    const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
   1145    struct gl_framebuffer *fb = ctx->DrawBuffer;
   1146 
   1147    /*
   1148    printf("%s()  interp 0x%x  array 0x%x\n", __func__,
   1149           span->interpMask, span->arrayMask);
   1150    */
   1151 
   1152    assert(span->primitive == GL_POINT ||
   1153           span->primitive == GL_LINE ||
   1154 	  span->primitive == GL_POLYGON ||
   1155           span->primitive == GL_BITMAP);
   1156 
   1157    /* Fragment write masks */
   1158    if (span->arrayMask & SPAN_MASK) {
   1159       /* mask was initialized by caller, probably glBitmap */
   1160       span->writeAll = GL_FALSE;
   1161    }
   1162    else {
   1163       memset(span->array->mask, 1, span->end);
   1164       span->writeAll = GL_TRUE;
   1165    }
   1166 
   1167    /* Clip to window/scissor box */
   1168    if (!clip_span(ctx, span)) {
   1169       return;
   1170    }
   1171 
   1172    assert(span->end <= SWRAST_MAX_WIDTH);
   1173 
   1174    /* Depth bounds test */
   1175    if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
   1176       if (!_swrast_depth_bounds_test(ctx, span)) {
   1177          return;
   1178       }
   1179    }
   1180 
   1181 #ifdef DEBUG
   1182    /* Make sure all fragments are within window bounds */
   1183    if (span->arrayMask & SPAN_XY) {
   1184       /* array of pixel locations */
   1185       GLuint i;
   1186       for (i = 0; i < span->end; i++) {
   1187          if (span->array->mask[i]) {
   1188             assert(span->array->x[i] >= fb->_Xmin);
   1189             assert(span->array->x[i] < fb->_Xmax);
   1190             assert(span->array->y[i] >= fb->_Ymin);
   1191             assert(span->array->y[i] < fb->_Ymax);
   1192          }
   1193       }
   1194    }
   1195 #endif
   1196 
   1197    /* Polygon Stippling */
   1198    if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
   1199       stipple_polygon_span(ctx, span);
   1200    }
   1201 
   1202    /* This is the normal place to compute the fragment color/Z
   1203     * from texturing or shading.
   1204     */
   1205    if (shaderOrTexture && !swrast->_DeferredTexture) {
   1206       shade_texture_span(ctx, span);
   1207    }
   1208 
   1209    /* Do the alpha test */
   1210    if (ctx->Color.AlphaEnabled) {
   1211       if (!_swrast_alpha_test(ctx, span)) {
   1212          /* all fragments failed test */
   1213          goto end;
   1214       }
   1215    }
   1216 
   1217    /* Stencil and Z testing */
   1218    if (_mesa_stencil_is_enabled(ctx) || ctx->Depth.Test) {
   1219       if (!(span->arrayMask & SPAN_Z))
   1220          _swrast_span_interpolate_z(ctx, span);
   1221 
   1222       if (ctx->Transform.DepthClamp)
   1223 	 _swrast_depth_clamp_span(ctx, span);
   1224 
   1225       if (_mesa_stencil_is_enabled(ctx)) {
   1226          /* Combined Z/stencil tests */
   1227          if (!_swrast_stencil_and_ztest_span(ctx, span)) {
   1228             /* all fragments failed test */
   1229             goto end;
   1230          }
   1231       }
   1232       else if (fb->Visual.depthBits > 0) {
   1233          /* Just regular depth testing */
   1234          assert(ctx->Depth.Test);
   1235          assert(span->arrayMask & SPAN_Z);
   1236          if (!_swrast_depth_test_span(ctx, span)) {
   1237             /* all fragments failed test */
   1238             goto end;
   1239          }
   1240       }
   1241    }
   1242 
   1243    if (ctx->Query.CurrentOcclusionObject) {
   1244       /* update count of 'passed' fragments */
   1245       struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
   1246       GLuint i;
   1247       for (i = 0; i < span->end; i++)
   1248          q->Result += span->array->mask[i];
   1249    }
   1250 
   1251    /* We had to wait until now to check for glColorMask(0,0,0,0) because of
   1252     * the occlusion test.
   1253     */
   1254    if (fb->_NumColorDrawBuffers == 1 && colorMask[0] == 0x0) {
   1255       /* no colors to write */
   1256       goto end;
   1257    }
   1258 
   1259    /* If we were able to defer fragment color computation to now, there's
   1260     * a good chance that many fragments will have already been killed by
   1261     * Z/stencil testing.
   1262     */
   1263    if (shaderOrTexture && swrast->_DeferredTexture) {
   1264       shade_texture_span(ctx, span);
   1265    }
   1266 
   1267 #if CHAN_BITS == 32
   1268    if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) {
   1269       interpolate_active_attribs(ctx, span, VARYING_BIT_COL0);
   1270    }
   1271 #else
   1272    if ((span->arrayMask & SPAN_RGBA) == 0) {
   1273       interpolate_int_colors(ctx, span);
   1274    }
   1275 #endif
   1276 
   1277    assert(span->arrayMask & SPAN_RGBA);
   1278 
   1279    if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) {
   1280       /* Add primary and specular (diffuse + specular) colors */
   1281       if (!shader) {
   1282          if (ctx->Fog.ColorSumEnabled ||
   1283              (ctx->Light.Enabled &&
   1284               ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
   1285             add_specular(ctx, span);
   1286          }
   1287       }
   1288    }
   1289 
   1290    /* Fog */
   1291    if (swrast->_FogEnabled) {
   1292       _swrast_fog_rgba_span(ctx, span);
   1293    }
   1294 
   1295    /* Antialias coverage application */
   1296    if (span->arrayMask & SPAN_COVERAGE) {
   1297       apply_aa_coverage(span);
   1298    }
   1299 
   1300    /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
   1301    if (ctx->Color.ClampFragmentColor == GL_TRUE &&
   1302        span->array->ChanType == GL_FLOAT) {
   1303       clamp_colors(span);
   1304    }
   1305 
   1306    /*
   1307     * Write to renderbuffers.
   1308     * Depending on glDrawBuffer() state and the which color outputs are
   1309     * written by the fragment shader, we may either replicate one color to
   1310     * all renderbuffers or write a different color to each renderbuffer.
   1311     * multiFragOutputs=TRUE for the later case.
   1312     */
   1313    {
   1314       const GLuint numBuffers = fb->_NumColorDrawBuffers;
   1315       const struct gl_program *fp = ctx->FragmentProgram._Current;
   1316       const GLboolean multiFragOutputs =
   1317          _swrast_use_fragment_program(ctx)
   1318          && fp->info.outputs_written >= (1 << FRAG_RESULT_DATA0);
   1319       /* Save srcColorType because convert_color_type() can change it */
   1320       const GLenum srcColorType = span->array->ChanType;
   1321       GLuint buf;
   1322 
   1323       for (buf = 0; buf < numBuffers; buf++) {
   1324          struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
   1325 
   1326          /* color[fragOutput] will be written to buffer[buf] */
   1327 
   1328          if (rb) {
   1329             /* re-use one of the attribute array buffers for rgbaSave */
   1330             GLchan (*rgbaSave)[4] = (GLchan (*)[4]) span->array->attribs[0];
   1331             struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   1332             const GLenum dstColorType = srb->ColorType;
   1333 
   1334             assert(dstColorType == GL_UNSIGNED_BYTE ||
   1335                    dstColorType == GL_FLOAT);
   1336 
   1337             /* set span->array->rgba to colors for renderbuffer's datatype */
   1338             if (srcColorType != dstColorType) {
   1339                convert_color_type(span, srcColorType, dstColorType,
   1340                                   multiFragOutputs ? buf : 0);
   1341             }
   1342             else {
   1343                if (srcColorType == GL_UNSIGNED_BYTE) {
   1344                   span->array->rgba = span->array->rgba8;
   1345                }
   1346                else {
   1347                   span->array->rgba = (void *)
   1348                      span->array->attribs[VARYING_SLOT_COL0];
   1349                }
   1350             }
   1351 
   1352             if (!multiFragOutputs && numBuffers > 1) {
   1353                /* save colors for second, third renderbuffer writes */
   1354                memcpy(rgbaSave, span->array->rgba,
   1355                       4 * span->end * sizeof(GLchan));
   1356             }
   1357 
   1358             assert(rb->_BaseFormat == GL_RGBA ||
   1359                    rb->_BaseFormat == GL_RGB ||
   1360                    rb->_BaseFormat == GL_RED ||
   1361                    rb->_BaseFormat == GL_RG ||
   1362 		   rb->_BaseFormat == GL_ALPHA);
   1363 
   1364             if (ctx->Color.ColorLogicOpEnabled) {
   1365                _swrast_logicop_rgba_span(ctx, rb, span);
   1366             }
   1367             else if ((ctx->Color.BlendEnabled >> buf) & 1) {
   1368                _swrast_blend_span(ctx, rb, span);
   1369             }
   1370 
   1371             if (colorMask[buf] != 0xffffffff) {
   1372                _swrast_mask_rgba_span(ctx, rb, span, buf);
   1373             }
   1374 
   1375             if (span->arrayMask & SPAN_XY) {
   1376                /* array of pixel coords */
   1377                put_values(ctx, rb,
   1378                           span->array->ChanType, span->end,
   1379                           span->array->x, span->array->y,
   1380                           span->array->rgba, span->array->mask);
   1381             }
   1382             else {
   1383                /* horizontal run of pixels */
   1384                _swrast_put_row(ctx, rb,
   1385                                span->array->ChanType,
   1386                                span->end, span->x, span->y,
   1387                                span->array->rgba,
   1388                                span->writeAll ? NULL: span->array->mask);
   1389             }
   1390 
   1391             if (!multiFragOutputs && numBuffers > 1) {
   1392                /* restore original span values */
   1393                memcpy(span->array->rgba, rgbaSave,
   1394                       4 * span->end * sizeof(GLchan));
   1395             }
   1396 
   1397          } /* if rb */
   1398       } /* for buf */
   1399    }
   1400 
   1401 end:
   1402    /* restore these values before returning */
   1403    span->interpMask = origInterpMask;
   1404    span->arrayMask = origArrayMask;
   1405    span->arrayAttribs = origArrayAttribs;
   1406    span->array->ChanType = origChanType;
   1407    span->array->rgba = origRgba;
   1408 }
   1409 
   1410 
   1411 /**
   1412  * Read float RGBA pixels from a renderbuffer.  Clipping will be done to
   1413  * prevent reading ouside the buffer's boundaries.
   1414  * \param rgba  the returned colors
   1415  */
   1416 void
   1417 _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
   1418                         GLuint n, GLint x, GLint y,
   1419                         GLvoid *rgba)
   1420 {
   1421    struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   1422    GLenum dstType = GL_FLOAT;
   1423    const GLint bufWidth = (GLint) rb->Width;
   1424    const GLint bufHeight = (GLint) rb->Height;
   1425 
   1426    if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
   1427       /* completely above, below, or right */
   1428       /* XXX maybe leave rgba values undefined? */
   1429       memset(rgba, 0, 4 * n * sizeof(GLchan));
   1430    }
   1431    else {
   1432       GLint skip, length;
   1433       GLubyte *src;
   1434 
   1435       if (x < 0) {
   1436          /* left edge clipping */
   1437          skip = -x;
   1438          length = (GLint) n - skip;
   1439          if (length < 0) {
   1440             /* completely left of window */
   1441             return;
   1442          }
   1443          if (length > bufWidth) {
   1444             length = bufWidth;
   1445          }
   1446       }
   1447       else if ((GLint) (x + n) > bufWidth) {
   1448          /* right edge clipping */
   1449          skip = 0;
   1450          length = bufWidth - x;
   1451          if (length < 0) {
   1452             /* completely to right of window */
   1453             return;
   1454          }
   1455       }
   1456       else {
   1457          /* no clipping */
   1458          skip = 0;
   1459          length = (GLint) n;
   1460       }
   1461 
   1462       assert(rb);
   1463       assert(rb->_BaseFormat == GL_RGBA ||
   1464 	     rb->_BaseFormat == GL_RGB ||
   1465 	     rb->_BaseFormat == GL_RG ||
   1466 	     rb->_BaseFormat == GL_RED ||
   1467 	     rb->_BaseFormat == GL_LUMINANCE ||
   1468 	     rb->_BaseFormat == GL_INTENSITY ||
   1469 	     rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
   1470 	     rb->_BaseFormat == GL_ALPHA);
   1471 
   1472       assert(srb->Map);
   1473       (void) srb; /* silence unused var warning */
   1474 
   1475       src = _swrast_pixel_address(rb, x + skip, y);
   1476 
   1477       if (dstType == GL_UNSIGNED_BYTE) {
   1478          _mesa_unpack_ubyte_rgba_row(rb->Format, length, src,
   1479                                      (GLubyte (*)[4]) rgba + skip);
   1480       }
   1481       else if (dstType == GL_FLOAT) {
   1482          _mesa_unpack_rgba_row(rb->Format, length, src,
   1483                                (GLfloat (*)[4]) rgba + skip);
   1484       }
   1485       else {
   1486          _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()");
   1487       }
   1488    }
   1489 }
   1490 
   1491 
   1492 /**
   1493  * Get colors at x/y positions with clipping.
   1494  * \param type  type of values to return
   1495  */
   1496 static void
   1497 get_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
   1498            GLuint count, const GLint x[], const GLint y[],
   1499            void *values, GLenum type)
   1500 {
   1501    GLuint i;
   1502 
   1503    for (i = 0; i < count; i++) {
   1504       if (x[i] >= 0 && y[i] >= 0 &&
   1505 	  x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
   1506          /* inside */
   1507          const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]);
   1508 
   1509          if (type == GL_UNSIGNED_BYTE) {
   1510             _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src,
   1511                                         (GLubyte (*)[4]) values + i);
   1512          }
   1513          else if (type == GL_FLOAT) {
   1514             _mesa_unpack_rgba_row(rb->Format, 1, src,
   1515                                   (GLfloat (*)[4]) values + i);
   1516          }
   1517          else {
   1518             _mesa_problem(ctx, "unexpected type in get_values()");
   1519          }
   1520       }
   1521    }
   1522 }
   1523 
   1524 
   1525 /**
   1526  * Get row of colors with clipping.
   1527  * \param type  type of values to return
   1528  */
   1529 static void
   1530 get_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
   1531         GLuint count, GLint x, GLint y,
   1532         GLvoid *values, GLenum type)
   1533 {
   1534    GLint skip = 0;
   1535    GLubyte *src;
   1536 
   1537    if (y < 0 || y >= (GLint) rb->Height)
   1538       return; /* above or below */
   1539 
   1540    if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
   1541       return; /* entirely left or right */
   1542 
   1543    if (x + count > rb->Width) {
   1544       /* right clip */
   1545       GLint clip = x + count - rb->Width;
   1546       count -= clip;
   1547    }
   1548 
   1549    if (x < 0) {
   1550       /* left clip */
   1551       skip = -x;
   1552       x = 0;
   1553       count -= skip;
   1554    }
   1555 
   1556    src = _swrast_pixel_address(rb, x, y);
   1557 
   1558    if (type == GL_UNSIGNED_BYTE) {
   1559       _mesa_unpack_ubyte_rgba_row(rb->Format, count, src,
   1560                                   (GLubyte (*)[4]) values + skip);
   1561    }
   1562    else if (type == GL_FLOAT) {
   1563       _mesa_unpack_rgba_row(rb->Format, count, src,
   1564                             (GLfloat (*)[4]) values + skip);
   1565    }
   1566    else {
   1567       _mesa_problem(ctx, "unexpected type in get_row()");
   1568    }
   1569 }
   1570 
   1571 
   1572 /**
   1573  * Get RGBA pixels from the given renderbuffer.
   1574  * Used by blending, logicop and masking functions.
   1575  * \return pointer to the colors we read.
   1576  */
   1577 void *
   1578 _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
   1579                       SWspan *span)
   1580 {
   1581    void *rbPixels;
   1582 
   1583    /* Point rbPixels to a temporary space */
   1584    rbPixels = span->array->attribs[VARYING_SLOT_MAX - 1];
   1585 
   1586    /* Get destination values from renderbuffer */
   1587    if (span->arrayMask & SPAN_XY) {
   1588       get_values(ctx, rb, span->end, span->array->x, span->array->y,
   1589                  rbPixels, span->array->ChanType);
   1590    }
   1591    else {
   1592       get_row(ctx, rb, span->end, span->x, span->y,
   1593               rbPixels, span->array->ChanType);
   1594    }
   1595 
   1596    return rbPixels;
   1597 }
   1598