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