home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / swrast / s_span.cpp < prev    next >
C/C++ Source or Header  |  2002-12-29  |  47KB  |  1,413 lines

  1. /* $Id: s_span.c,v 1.53 2002/11/26 03:00:04 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.0.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. /**
  29.  * \file swrast/s_span.c
  30.  * \brief Span processing functions used by all rasterization functions.
  31.  * This is where all the per-fragment tests are performed
  32.  * \author Brian Paul
  33.  */
  34.  
  35. #include "glheader.h"
  36. #include "colormac.h"
  37. #include "context.h"
  38. #include "macros.h"
  39. #include "mmath.h"
  40. #include "imports.h"
  41.  
  42. #include "s_alpha.h"
  43. #include "s_alphabuf.h"
  44. #include "s_blend.h"
  45. #include "s_context.h"
  46. #include "s_depth.h"
  47. #include "s_fog.h"
  48. #include "s_logic.h"
  49. #include "s_masking.h"
  50. #include "s_span.h"
  51. #include "s_stencil.h"
  52. #include "s_texture.h"
  53.  
  54.  
  55. /**
  56.  * Init span's Z interpolation values to the RasterPos Z.
  57.  * Used during setup for glDraw/CopyPixels.
  58.  */
  59. void
  60. _mesa_span_default_z( GLcontext *ctx, struct sw_span *span )
  61. {
  62.    if (ctx->Visual.depthBits <= 16)
  63.       span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F);
  64.    else
  65.       span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F);
  66.    span->zStep = 0;
  67.    span->interpMask |= SPAN_Z;
  68. }
  69.  
  70.  
  71. /**
  72.  * Init span's fog interpolation values to the RasterPos fog.
  73.  * Used during setup for glDraw/CopyPixels.
  74.  */
  75. void
  76. _mesa_span_default_fog( GLcontext *ctx, struct sw_span *span )
  77. {
  78.    span->fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
  79.    span->fogStep = 0;
  80.    span->interpMask |= SPAN_FOG;
  81. }
  82.  
  83.  
  84. /**
  85.  * Init span's color or index interpolation values to the RasterPos color.
  86.  * Used during setup for glDraw/CopyPixels.
  87.  */
  88. void
  89. _mesa_span_default_color( GLcontext *ctx, struct sw_span *span )
  90. {
  91.    if (ctx->Visual.rgbMode) {
  92.       GLchan r, g, b, a;
  93.       UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
  94.       UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
  95.       UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
  96.       UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
  97. #if CHAN_TYPE == GL_FLOAT
  98.       span->red = r;
  99.       span->green = g;
  100.       span->blue = b;
  101.       span->alpha = a;
  102. #else
  103.       span->red   = IntToFixed(r);
  104.       span->green = IntToFixed(g);
  105.       span->blue  = IntToFixed(b);
  106.       span->alpha = IntToFixed(a);
  107. #endif
  108.       span->redStep = 0;
  109.       span->greenStep = 0;
  110.       span->blueStep = 0;
  111.       span->alphaStep = 0;
  112.       span->interpMask |= SPAN_RGBA;
  113.    }
  114.    else {
  115.       span->index = IntToFixed(ctx->Current.RasterIndex);
  116.       span->indexStep = 0;
  117.       span->interpMask |= SPAN_INDEX;
  118.    }
  119. }
  120.  
  121.  
  122. /**
  123.  * Init span's texcoord interpolation values to the RasterPos texcoords.
  124.  * Used during setup for glDraw/CopyPixels.
  125.  */
  126. void
  127. _mesa_span_default_texcoords( GLcontext *ctx, struct sw_span *span )
  128. {
  129.    GLuint i;
  130.    for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
  131.       COPY_4V(span->tex[i], ctx->Current.RasterTexCoords[i]);
  132.       ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
  133.       ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
  134.    }
  135.    span->interpMask |= SPAN_TEXTURE;
  136. }
  137.  
  138.  
  139. /* Fill in the span.color.rgba array from the interpolation values */
  140. static void
  141. interpolate_colors(GLcontext *ctx, struct sw_span *span)
  142. {
  143.    GLfixed r = span->red;
  144.    GLfixed g = span->green;
  145.    GLfixed b = span->blue;
  146.    GLfixed a = span->alpha;
  147.    const GLuint n = span->end;
  148.    GLchan (*rgba)[4] = span->array->rgba;
  149.    GLuint i;
  150.  
  151.    ASSERT((span->interpMask & SPAN_RGBA)  &&
  152.          !(span->arrayMask & SPAN_RGBA));
  153.  
  154.    if (span->interpMask & SPAN_FLAT) {
  155.       /* constant color */
  156.       GLchan color[4];
  157.       color[RCOMP] = FixedToChan(r);
  158.       color[GCOMP] = FixedToChan(g);
  159.       color[BCOMP] = FixedToChan(b);
  160.       color[ACOMP] = FixedToChan(a);
  161.       for (i = 0; i < n; i++) {
  162.          COPY_CHAN4(span->array->rgba[i], color);
  163.       }
  164.    } else {
  165.    const GLint dr = span->redStep;
  166.    const GLint dg = span->greenStep;
  167.    const GLint db = span->blueStep;
  168.    const GLint da = span->alphaStep;
  169.       /* interpolate */
  170.       for (i = 0; i < n; i++) {
  171.          rgba[i][RCOMP] = FixedToChan(r);
  172.          rgba[i][GCOMP] = FixedToChan(g);
  173.          rgba[i][BCOMP] = FixedToChan(b);
  174.          rgba[i][ACOMP] = FixedToChan(a);
  175.          r += dr;
  176.          g += dg;
  177.          b += db;
  178.          a += da;
  179.       }
  180.    }
  181.    span->arrayMask |= SPAN_RGBA;
  182. }
  183.  
  184.  
  185. /* Fill in the span.color.index array from the interpolation values */
  186. static void
  187. interpolate_indexes(GLcontext *ctx, struct sw_span *span)
  188. {
  189.    GLfixed index = span->index;
  190.    const GLint indexStep = span->indexStep;
  191.    const GLuint n = span->end;
  192.    GLuint *indexes = span->array->index;
  193.    GLuint i;
  194.    ASSERT((span->interpMask & SPAN_INDEX)  &&
  195.          !(span->arrayMask & SPAN_INDEX));
  196.  
  197.    if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
  198.       /* constant color */
  199.       index = FixedToInt(index);
  200.       for (i = 0; i < n; i++) {
  201.          indexes[i] = index;
  202.       }
  203.    }
  204.    else {
  205.       /* interpolate */
  206.       for (i = 0; i < n; i++) {
  207.          indexes[i] = FixedToInt(index);
  208.          index += indexStep;
  209.       }
  210.    }
  211.    span->arrayMask |= SPAN_INDEX;
  212. }
  213.  
  214.  
  215. /* Fill in the span.->array->spec array from the interpolation values */
  216. static void
  217. interpolate_specular(GLcontext *ctx, struct sw_span *span)
  218. {
  219.    if (span->interpMask & SPAN_FLAT) {
  220.       /* constant color */
  221.       const GLchan r = FixedToChan(span->specRed);
  222.       const GLchan g = FixedToChan(span->specGreen);
  223.       const GLchan b = FixedToChan(span->specBlue);
  224.       GLuint i;
  225.       for (i = 0; i < span->end; i++) {
  226.          span->array->spec[i][RCOMP] = r;
  227.          span->array->spec[i][GCOMP] = g;
  228.          span->array->spec[i][BCOMP] = b;
  229.       }
  230.    }
  231.    else {
  232.       /* interpolate */
  233. #if CHAN_TYPE == GL_FLOAT
  234.       GLfloat r = span->specRed;
  235.       GLfloat g = span->specGreen;
  236.       GLfloat b = span->specBlue;
  237. #else
  238.       GLfixed r = span->specRed;
  239.       GLfixed g = span->specGreen;
  240.       GLfixed b = span->specBlue;
  241. #endif
  242.       GLuint i;
  243.       for (i = 0; i < span->end; i++) {
  244.          span->array->spec[i][RCOMP] = FixedToChan(r);
  245.          span->array->spec[i][GCOMP] = FixedToChan(g);
  246.          span->array->spec[i][BCOMP] = FixedToChan(b);
  247.          r += span->specRedStep;
  248.          g += span->specGreenStep;
  249.          b += span->specBlueStep;
  250.       }
  251.    }
  252.    span->arrayMask |= SPAN_SPEC;
  253. }
  254.  
  255.  
  256. /* Fill in the span.zArray array from the interpolation values */
  257. void
  258. _mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
  259. {
  260.    const GLuint n = span->end;
  261.    GLuint i;
  262.  
  263.    ASSERT((span->interpMask & SPAN_Z)  &&
  264.          !(span->arrayMask & SPAN_Z));
  265.  
  266.    if (ctx->Visual.depthBits <= 16) {
  267.       GLfixed zval = span->z;
  268.       GLdepth *z = span->array->z;
  269.       for (i = 0; i < n; i++) {
  270.          z[i] = FixedToInt(zval);
  271.          zval += span->zStep;
  272.       }
  273.    }
  274.    else {
  275.       /* Deep Z buffer, no fixed->int shift */
  276.       GLfixed zval = span->z;
  277.       GLdepth *z = span->array->z;
  278.       for (i = 0; i < n; i++) {
  279.          z[i] = zval;
  280.          zval += span->zStep;
  281.       }
  282.    }
  283.    span->arrayMask |= SPAN_Z;
  284. }
  285.  
  286.  
  287. /*
  288.  * This the ideal solution, as given in the OpenGL spec.
  289.  */
  290. #if 0
  291. static GLfloat
  292. compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
  293.                GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
  294.                GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
  295. {
  296.    GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
  297.    GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
  298.    GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
  299.    GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
  300.    GLfloat x = sqrt(dudx * dudx + dvdx * dvdx);
  301.    GLfloat y = sqrt(dudy * dudy + dvdy * dvdy);
  302.    GLfloat rho = MAX2(x, y);
  303.    GLfloat lambda = LOG2(rho);
  304.    return lambda;
  305. }
  306. #endif
  307.  
  308.  
  309. /*
  310.  * This is a faster approximation
  311.  */
  312. static GLfloat
  313. compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
  314.                GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
  315.                GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
  316. {
  317.    GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
  318.    GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
  319.    GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
  320.    GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
  321.    GLfloat maxU, maxV, rho, lambda;
  322.    dsdx2 = FABSF(dsdx2);
  323.    dsdy2 = FABSF(dsdy2);
  324.    dtdx2 = FABSF(dtdx2);
  325.    dtdy2 = FABSF(dtdy2);
  326.    maxU = MAX2(dsdx2, dsdy2) * texW;
  327.    maxV = MAX2(dtdx2, dtdy2) * texH;
  328.    rho = MAX2(maxU, maxV);
  329.    lambda = LOG2(rho);
  330.    return lambda;
  331. }
  332.  
  333. /*
  334.  * Fill in the span.texcoords array from the interpolation values.
  335.  * XXX We could optimize here for the case when dq = 0.  That would
  336.  * usually be the case when using an orthographic projection.
  337.  */
  338. static void
  339. interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
  340. {
  341.    ASSERT(span->interpMask & SPAN_TEXTURE);
  342.    ASSERT(!(span->arrayMask & SPAN_TEXTURE));
  343.  
  344.    if (ctx->Texture._EnabledUnits > 1) {
  345.       /* multitexture */
  346.       GLuint u;
  347.       span->arrayMask |= SPAN_TEXTURE;
  348.       for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
  349.          if (ctx->Texture.Unit[u]._ReallyEnabled) {
  350.             const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
  351.             const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
  352.             GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
  353.             if (needLambda) {
  354.                GLfloat (*texcoord)[4] = span->array->texcoords[u];
  355.                GLfloat *lambda = span->array->lambda[u];
  356.                const GLfloat texW = (GLfloat) img->WidthScale;
  357.                const GLfloat texH = (GLfloat) img->HeightScale;
  358.                const GLfloat dsdx = span->texStepX[u][0];
  359.                const GLfloat dsdy = span->texStepY[u][0];
  360.                const GLfloat dtdx = span->texStepX[u][1];
  361.                const GLfloat dtdy = span->texStepY[u][1];
  362.                const GLfloat drdx = span->texStepX[u][2];
  363.                const GLfloat dqdx = span->texStepX[u][3];
  364.                const GLfloat dqdy = span->texStepY[u][3];
  365.                GLfloat s = span->tex[u][0];
  366.                GLfloat t = span->tex[u][1];
  367.                GLfloat r = span->tex[u][2];
  368.                GLfloat q = span->tex[u][3];
  369.                GLuint i;
  370.                for (i = 0; i < span->end; i++) {
  371.                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
  372.                   texcoord[i][0] = s * invQ;
  373.                   texcoord[i][1] = t * invQ;
  374.                   texcoord[i][2] = r * invQ;
  375.                   lambda[i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
  376.                                              dqdx, dqdy, texW, texH,
  377.                                              s, t, q, invQ);
  378.                   s += dsdx;
  379.                   t += dtdx;
  380.                   r += drdx;
  381.                   q += dqdx;
  382.                }
  383.                span->arrayMask |= SPAN_LAMBDA;
  384.             }
  385.             else {
  386.                GLfloat (*texcoord)[4] = span->array->texcoords[u];
  387.                GLfloat *lambda = span->array->lambda[u];
  388.                const GLfloat dsdx = span->texStepX[u][0];
  389.                const GLfloat dtdx = span->texStepX[u][1];
  390.                const GLfloat drdx = span->texStepX[u][2];
  391.                const GLfloat dqdx = span->texStepX[u][3];
  392.                GLfloat s = span->tex[u][0];
  393.                GLfloat t = span->tex[u][1];
  394.                GLfloat r = span->tex[u][2];
  395.                GLfloat q = span->tex[u][3];
  396.                GLuint i;
  397.                if (dqdx == 0.0) {
  398.                   /* Ortho projection or polygon's parallel to window X axis */
  399.                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
  400.                   for (i = 0; i < span->end; i++) {
  401.                      texcoord[i][0] = s * invQ;
  402.                      texcoord[i][1] = t * invQ;
  403.                      texcoord[i][2] = r * invQ;
  404.                      lambda[i] = 0.0;
  405.                      s += dsdx;
  406.                      t += dtdx;
  407.                      r += drdx;
  408.                   }
  409.                }
  410.                else {
  411.                   for (i = 0; i < span->end; i++) {
  412.                      const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
  413.                      texcoord[i][0] = s * invQ;
  414.                      texcoord[i][1] = t * invQ;
  415.                      texcoord[i][2] = r * invQ;
  416.                      lambda[i] = 0.0;
  417.                      s += dsdx;
  418.                      t += dtdx;
  419.                      r += drdx;
  420.                      q += dqdx;
  421.                   }
  422.                }
  423.             } /* lambda */
  424.          } /* if */
  425.       } /* for */
  426.    }
  427.    else {
  428.       /* single texture */
  429.       const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
  430.       const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
  431.       GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
  432.       span->arrayMask |= SPAN_TEXTURE;
  433.       if (needLambda) {
  434.          /* just texture unit 0, with lambda */
  435.          GLfloat (*texcoord)[4] = span->array->texcoords[0];
  436.          GLfloat *lambda = span->array->lambda[0];
  437.          const GLfloat texW = (GLfloat) img->WidthScale;
  438.          const GLfloat texH = (GLfloat) img->HeightScale;
  439.          const GLfloat dsdx = span->texStepX[0][0];
  440.          const GLfloat dsdy = span->texStepY[0][0];
  441.          const GLfloat dtdx = span->texStepX[0][1];
  442.          const GLfloat dtdy = span->texStepY[0][1];
  443.          const GLfloat drdx = span->texStepX[0][2];
  444.          const GLfloat dqdx = span->texStepX[0][3];
  445.          const GLfloat dqdy = span->texStepY[0][3];
  446.          GLfloat s = span->tex[0][0];
  447.          GLfloat t = span->tex[0][1];
  448.          GLfloat r = span->tex[0][2];
  449.          GLfloat q = span->tex[0][3];
  450.          GLuint i;
  451.          for (i = 0; i < span->end; i++) {
  452.             const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
  453.             lambda[i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
  454.                                        dqdx, dqdy, texW, texH,
  455.                                        s, t, q, invQ);
  456.             texcoord[i][0] = s * invQ;
  457.             texcoord[i][1] = t * invQ;
  458.             texcoord[i][2] = r * invQ;
  459.             s += dsdx;
  460.             t += dtdx;
  461.             r += drdx;
  462.             q += dqdx;
  463.          }
  464.          span->arrayMask |= SPAN_LAMBDA;
  465.       }
  466.       else {
  467.          /* just texture 0, without lambda */
  468.          GLfloat (*texcoord)[4] = span->array->texcoords[0];
  469.          const GLfloat dsdx = span->texStepX[0][0];
  470.          const GLfloat dtdx = span->texStepX[0][1];
  471.          const GLfloat drdx = span->texStepX[0][2];
  472.          const GLfloat dqdx = span->texStepX[0][3];
  473.          GLfloat s = span->tex[0][0];
  474.          GLfloat t = span->tex[0][1];
  475.          GLfloat r = span->tex[0][2];
  476.          GLfloat q = span->tex[0][3];
  477.          GLuint i;
  478.          if (dqdx == 0.0) {
  479.             /* Ortho projection or polygon's parallel to window X axis */
  480.             const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
  481.             for (i = 0; i < span->end; i++) {
  482.                texcoord[i][0] = s * invQ;
  483.                texcoord[i][1] = t * invQ;
  484.                texcoord[i][2] = r * invQ;
  485.                s += dsdx;
  486.                t += dtdx;
  487.                r += drdx;
  488.             }
  489.          }
  490.          else {
  491.             for (i = 0; i < span->end; i++) {
  492.                const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
  493.                texcoord[i][0] = s * invQ;
  494.                texcoord[i][1] = t * invQ;
  495.                texcoord[i][2] = r * invQ;
  496.                s += dsdx;
  497.                t += dtdx;
  498.                r += drdx;
  499.                q += dqdx;
  500.             }
  501.          }
  502.       }
  503.    }
  504. }
  505.  
  506.  
  507. /**
  508.  * Apply the current polygon stipple pattern to a span of pixels.
  509.  */
  510. static void
  511. stipple_polygon_span( GLcontext *ctx, struct sw_span *span )
  512. {
  513.    const GLuint highbit = 0x80000000;
  514.    const GLuint stipple = ctx->PolygonStipple[span->y % 32];
  515.    GLubyte *mask = span->array->mask;
  516.    GLuint i, m;
  517.  
  518.    ASSERT(ctx->Polygon.StippleFlag);
  519.    ASSERT((span->arrayMask & SPAN_XY) == 0);
  520.  
  521.    m = highbit >> (GLuint) (span->x % 32);
  522.  
  523.    for (i = 0; i < span->end; i++) {
  524.       if ((m & stipple) == 0) {
  525.         mask[i] = 0;
  526.       }
  527.       m = m >> 1;
  528.       if (m == 0) {
  529.          m = highbit;
  530.       }
  531.    }
  532.    span->writeAll = GL_FALSE;
  533. }
  534.  
  535.  
  536. /**
  537.  * Clip a pixel span to the current buffer/window boundaries:
  538.  * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
  539.  * window clipping and scissoring.
  540.  * Return:   GL_TRUE   some pixels still visible
  541.  *           GL_FALSE  nothing visible
  542.  */
  543. static GLuint
  544. clip_span( GLcontext *ctx, struct sw_span *span )
  545. {
  546.    const GLint xmin = ctx->DrawBuffer->_Xmin;
  547.    const GLint xmax = ctx->DrawBuffer->_Xmax;
  548.    const GLint ymin = ctx->DrawBuffer->_Ymin;
  549.    const GLint ymax = ctx->DrawBuffer->_Ymax;
  550.  
  551.    if (span->arrayMask & SPAN_XY) {
  552.       /* arrays of x/y pixel coords */
  553.       const GLint *x = span->array->x;
  554.       const GLint *y = span->array->y;
  555.       const GLint n = span->end;
  556.       GLubyte *mask = span->array->mask;
  557.       GLint i;
  558.       if (span->arrayMask & SPAN_MASK) {
  559.          /* note: using & intead of && to reduce branches */
  560.          for (i = 0; i < n; i++) {
  561.             mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
  562.                      & (y[i] >= ymin) & (y[i] < ymax);
  563.          }
  564.       }
  565.       else {
  566.          /* note: using & intead of && to reduce branches */
  567.          for (i = 0; i < n; i++) {
  568.             mask[i] = (x[i] >= xmin) & (x[i] < xmax)
  569.                     & (y[i] >= ymin) & (y[i] < ymax);
  570.          }
  571.       }
  572.       return GL_TRUE;  /* some pixels visible */
  573.    }
  574.    else {
  575.       /* horizontal span of pixels */
  576.       const GLint x = span->x;
  577.       const GLint y = span->y;
  578.       const GLint n = span->end;
  579.  
  580.       /* Trivial rejection tests */
  581.       if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
  582.          span->end = 0;
  583.          return GL_FALSE;  /* all pixels clipped */
  584.       }
  585.  
  586.       /* Clip to the left */
  587.       if (x < xmin) {
  588.          ASSERT(x + n > xmin);
  589.          span->writeAll = GL_FALSE;
  590.          _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
  591.       }
  592.  
  593.       /* Clip to right */
  594.       if (x + n > xmax) {
  595.          ASSERT(x < xmax);
  596.          span->end = xmax - x;
  597.       }
  598.  
  599.       return GL_TRUE;  /* some pixels visible */
  600.    }
  601. }
  602.  
  603.  
  604.  
  605. /**
  606.  * Draw to more than one color buffer (or none).
  607.  */
  608. static void
  609. multi_write_index_span( GLcontext *ctx, struct sw_span *span )
  610. {
  611.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  612.    GLuint bufferBit;
  613.  
  614.    /* loop over four possible dest color buffers */
  615.    for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
  616.       if (bufferBit & ctx->Color._DrawDestMask) {
  617.          GLuint indexTmp[MAX_WIDTH];
  618.          ASSERT(span->end < MAX_WIDTH);
  619.  
  620.          /* Set the current read/draw buffer */
  621.          swrast->CurrentBuffer = bufferBit;
  622.          (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
  623.  
  624.          /* make copy of incoming indexes */
  625.          MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) );
  626.  
  627.          if (ctx->Color.IndexLogicOpEnabled) {
  628.             _mesa_logicop_ci_span(ctx, span, indexTmp);
  629.          }
  630.  
  631.          if (ctx->Color.IndexMask != 0xffffffff) {
  632.             _mesa_mask_index_span(ctx, span, indexTmp);
  633.          }
  634.  
  635.          if (span->arrayMask & SPAN_XY) {
  636.             /* array of pixel coords */
  637.             (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
  638.                                               span->array->x, span->array->y,
  639.                                               indexTmp, span->array->mask);
  640.          }
  641.          else {
  642.             /* horizontal run of pixels */
  643.             (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
  644.                                             indexTmp, span->array->mask);
  645.          }
  646.       }
  647.    }
  648.  
  649.    /* restore default dest buffer */
  650.    _swrast_use_draw_buffer(ctx);
  651. }
  652.  
  653.  
  654. /**
  655.  * Draw to more than one RGBA color buffer (or none).
  656.  * All fragment operations, up to (but not) blending/logicop should
  657.  * have been done first.
  658.  */
  659. static void
  660. multi_write_rgba_span( GLcontext *ctx, struct sw_span *span )
  661. {
  662.    const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
  663.    GLuint bufferBit;
  664.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  665.  
  666.    ASSERT(colorMask != 0x0);
  667.  
  668.    if (ctx->Color.DrawBuffer == GL_NONE)
  669.       return;
  670.  
  671.    /* loop over four possible dest color buffers */
  672.    for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
  673.       if (bufferBit & ctx->Color._DrawDestMask) {
  674.          GLchan rgbaTmp[MAX_WIDTH][4];
  675.          ASSERT(span->end < MAX_WIDTH);
  676.  
  677.          /* Set the current read/draw buffer */
  678.          swrast->CurrentBuffer = bufferBit;
  679.          (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
  680.  
  681.          /* make copy of incoming colors */
  682.          MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) );
  683.  
  684.          if (ctx->Color.ColorLogicOpEnabled) {
  685.             _mesa_logicop_rgba_span(ctx, span, rgbaTmp);
  686.          }
  687.          else if (ctx->Color.BlendEnabled) {
  688.             _mesa_blend_span(ctx, span, rgbaTmp);
  689.          }
  690.  
  691.          if (colorMask != 0xffffffff) {
  692.             _mesa_mask_rgba_span(ctx, span, rgbaTmp);
  693.          }
  694.  
  695.          if (span->arrayMask & SPAN_XY) {
  696.             /* array of pixel coords */
  697.             (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
  698.                                               span->array->x, span->array->y,
  699.                                               (const GLchan (*)[4]) rgbaTmp,
  700.                                               span->array->mask);
  701.             if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
  702.                _mesa_write_alpha_pixels(ctx, span->end,
  703.                                         span->array->x, span->array->y,
  704.                                         (const GLchan (*)[4]) rgbaTmp,
  705.                                         span->array->mask);
  706.             }
  707.          }
  708.          else {
  709.             /* horizontal run of pixels */
  710.             (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
  711.                                             (const GLchan (*)[4]) rgbaTmp,
  712.                                             span->array->mask);
  713.             if (swrast->_RasterMask & ALPHABUF_BIT) {
  714.                _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
  715.                                       (const GLchan (*)[4]) rgbaTmp,
  716.                                       span->array->mask);
  717.             }
  718.          }
  719.       }
  720.    }
  721.  
  722.    /* restore default dest buffer */
  723.    _swrast_use_draw_buffer(ctx);
  724. }
  725.  
  726.  
  727.  
  728. /**
  729.  * This function may modify any of the array values in the span.
  730.  * span->interpMask and span->arrayMask may be changed but will be restored
  731.  * to their original values before returning.
  732.  */
  733. void
  734. _mesa_write_index_span( GLcontext *ctx, struct sw_span *span)
  735. {
  736.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  737.    const GLuint origInterpMask = span->interpMask;
  738.    const GLuint origArrayMask = span->arrayMask;
  739.  
  740.    ASSERT(span->end <= MAX_WIDTH);
  741.    ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
  742.          span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
  743.    ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
  744.    ASSERT((span->interpMask & span->arrayMask) == 0);
  745.  
  746.    if (span->arrayMask & SPAN_MASK) {
  747.       /* mask was initialized by caller, probably glBitmap */
  748.       span->writeAll = GL_FALSE;
  749.    }
  750.    else {
  751.       MEMSET(span->array->mask, 1, span->end);
  752.       span->writeAll = GL_TRUE;
  753.    }
  754.  
  755.    /* Clipping */
  756.    if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
  757.       if (!clip_span(ctx, span)) {
  758.          return;
  759.       }
  760.    }
  761.  
  762. #ifdef DEBUG
  763.    if (span->arrayMask & SPAN_XY) {
  764.       GLuint i;
  765.       for (i = 0; i < span->end; i++) {
  766.          if (span->array->mask[i]) {
  767.             assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
  768.             assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
  769.             assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
  770.             assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
  771.          }
  772.       }
  773.    }
  774. #endif
  775.  
  776.    /* Polygon Stippling */
  777.    if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
  778.       stipple_polygon_span(ctx, span);
  779.    }
  780.  
  781.    /* Depth test and stencil */
  782.    if (ctx->Depth.Test || ctx->Stencil.Enabled) {
  783.       if (span->interpMask & SPAN_Z)
  784.          _mesa_span_interpolate_z(ctx, span);
  785.  
  786.       if (ctx->Stencil.Enabled) {
  787.          if (!_mesa_stencil_and_ztest_span(ctx, span)) {
  788.             span->arrayMask = origArrayMask;
  789.             return;
  790.          }
  791.       }
  792.       else {
  793.          ASSERT(ctx->Depth.Test);
  794.          if (!_mesa_depth_test_span(ctx, span)) {
  795.             span->arrayMask = origArrayMask;
  796.             return;
  797.          }
  798.       }
  799.    }
  800.  
  801.    /* if we get here, something passed the depth test */
  802.    ctx->OcclusionResult = GL_TRUE;
  803.  
  804.    /* we have to wait until after occlusion to do this test */
  805.    if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
  806.       /* write no pixels */
  807.       span->arrayMask = origArrayMask;
  808.       return;
  809.    }
  810.  
  811.    /* Interpolate the color indexes if needed */
  812.    if (span->interpMask & SPAN_INDEX) {
  813.       interpolate_indexes(ctx, span);
  814.       /* clear the bit - this allows the WriteMonoCISpan optimization below */
  815.       span->interpMask &= ~SPAN_INDEX;
  816.    }
  817.  
  818.    /* Fog */
  819.    if (ctx->Fog.Enabled) {
  820.       _mesa_fog_ci_span(ctx, span);
  821.    }
  822.  
  823.    /* Antialias coverage application */
  824.    if (span->arrayMask & SPAN_COVERAGE) {
  825.       GLuint i;
  826.       GLuint *index = span->array->index;
  827.       GLfloat *coverage = span->array->coverage;
  828.       for (i = 0; i < span->end; i++) {
  829.          ASSERT(coverage[i] < 16);
  830.          index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
  831.       }
  832.    }
  833.  
  834.    if (swrast->_RasterMask & MULTI_DRAW_BIT) {
  835.       /* draw to zero or two or more buffers */
  836.       multi_write_index_span(ctx, span);
  837.    }
  838.    else {
  839.       /* normal situation: draw to exactly one buffer */
  840.       if (ctx->Color.IndexLogicOpEnabled) {
  841.          _mesa_logicop_ci_span(ctx, span, span->array->index);
  842.       }
  843.  
  844.       if (ctx->Color.IndexMask != 0xffffffff) {
  845.          _mesa_mask_index_span(ctx, span, span->array->index);
  846.       }
  847.  
  848.       /* write pixels */
  849.       if (span->arrayMask & SPAN_XY) {
  850.          /* array of pixel coords */
  851.          if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
  852.             /* all pixels have same color index */
  853.             (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
  854.                                                 span->array->x, span->array->y,
  855.                                                 FixedToInt(span->index),
  856.                                                 span->array->mask);
  857.          }
  858.          else {
  859.             (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x,
  860.                                               span->array->y, span->array->index,
  861.                                               span->array->mask );
  862.          }
  863.       }
  864.       else {
  865.          /* horizontal run of pixels */
  866.          if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
  867.             /* all pixels have same color index */
  868.             (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
  869.                                               FixedToInt(span->index),
  870.                                               span->array->mask);
  871.          }
  872.          else {
  873.             (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
  874.                                             span->array->index,
  875.                                             span->array->mask);
  876.          }
  877.       }
  878.    }
  879.  
  880.    span->interpMask = origInterpMask;
  881.    span->arrayMask = origArrayMask;
  882. }
  883.  
  884.  
  885. /**
  886.  * This function may modify any of the array values in the span.
  887.  * span->interpMask and span->arrayMask may be changed but will be restored
  888.  * to their original values before returning.
  889.  */
  890. void
  891. _mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span)
  892. {
  893.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  894.    const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
  895.    const GLuint origInterpMask = span->interpMask;
  896.    const GLuint origArrayMask = span->arrayMask;
  897.    GLboolean monoColor;
  898.  
  899.    ASSERT(span->end <= MAX_WIDTH);
  900.    ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
  901.          span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
  902.    ASSERT((span->interpMask & span->arrayMask) == 0);
  903.    ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
  904. #ifdef DEBUG
  905.    if (ctx->Fog.Enabled)
  906.       ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
  907.    if (ctx->Depth.Test)
  908.       ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
  909. #endif
  910.  
  911.    if (span->arrayMask & SPAN_MASK) {
  912.       /* mask was initialized by caller, probably glBitmap */
  913.       span->writeAll = GL_FALSE;
  914.    }
  915.    else {
  916.       MEMSET(span->array->mask, 1, span->end);
  917.       span->writeAll = GL_TRUE;
  918.    }
  919.  
  920.    /* Determine if we have mono-chromatic colors */
  921.    monoColor = (span->interpMask & SPAN_RGBA) &&
  922.       span->redStep == 0 && span->greenStep == 0 &&
  923.       span->blueStep == 0 && span->alphaStep == 0;
  924.  
  925.    /* Clipping */
  926.    if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
  927.       if (!clip_span(ctx, span)) {
  928.          return;
  929.       }
  930.    }
  931.  
  932. #ifdef DEBUG
  933.    if (span->arrayMask & SPAN_XY) {
  934.       GLuint i;
  935.       for (i = 0; i < span->end; i++) {
  936.          if (span->array->mask[i]) {
  937.             assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
  938.             assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
  939.             assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
  940.             assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
  941.          }
  942.       }
  943.    }
  944. #endif
  945.  
  946.    /* Polygon Stippling */
  947.    if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
  948.       stipple_polygon_span(ctx, span);
  949.    }
  950.  
  951.    /* Do the alpha test */
  952.    if (ctx->Color.AlphaEnabled) {
  953.       if (!_mesa_alpha_test(ctx, span)) {
  954.          span->interpMask = origInterpMask;
  955.          span->arrayMask = origArrayMask;
  956.         return;
  957.       }
  958.    }
  959.  
  960.    /* Stencil and Z testing */
  961.    if (ctx->Stencil.Enabled || ctx->Depth.Test) {
  962.       if (span->interpMask & SPAN_Z)
  963.          _mesa_span_interpolate_z(ctx, span);
  964.  
  965.       if (ctx->Stencil.Enabled) {
  966.          if (!_mesa_stencil_and_ztest_span(ctx, span)) {
  967.             span->interpMask = origInterpMask;
  968.             span->arrayMask = origArrayMask;
  969.             return;
  970.          }
  971.       }
  972.       else {
  973.          ASSERT(ctx->Depth.Test);
  974.          ASSERT(span->arrayMask & SPAN_Z);
  975.          /* regular depth testing */
  976.          if (!_mesa_depth_test_span(ctx, span)) {
  977.             span->interpMask = origInterpMask;
  978.             span->arrayMask = origArrayMask;
  979.             return;
  980.          }
  981.       }
  982.    }
  983.  
  984.    /* if we get here, something passed the depth test */
  985.    ctx->OcclusionResult = GL_TRUE;
  986.  
  987.    /* can't abort span-writing until after occlusion testing */
  988.    if (colorMask == 0x0) {
  989.       span->interpMask = origInterpMask;
  990.       span->arrayMask = origArrayMask;
  991.       return;
  992.    }
  993.  
  994.    /* Now we may need to interpolate the colors */
  995.    if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
  996.       interpolate_colors(ctx, span);
  997.       /* clear the bit - this allows the WriteMonoCISpan optimization below */
  998.       span->interpMask &= ~SPAN_RGBA;
  999.    }
  1000.  
  1001.    /* Fog */
  1002.    if (ctx->Fog.Enabled) {
  1003.       _mesa_fog_rgba_span(ctx, span);
  1004.       monoColor = GL_FALSE;
  1005.    }
  1006.  
  1007.    /* Antialias coverage application */
  1008.    if (span->arrayMask & SPAN_COVERAGE) {
  1009.       GLchan (*rgba)[4] = span->array->rgba;
  1010.       GLfloat *coverage = span->array->coverage;
  1011.       GLuint i;
  1012.       for (i = 0; i < span->end; i++) {
  1013.          rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
  1014.       }
  1015.       monoColor = GL_FALSE;
  1016.    }
  1017.  
  1018.    if (swrast->_RasterMask & MULTI_DRAW_BIT) {
  1019.       multi_write_rgba_span(ctx, span);
  1020.    }
  1021.    else {
  1022.       /* normal: write to exactly one buffer */
  1023.       if (ctx->Color.ColorLogicOpEnabled) {
  1024.          _mesa_logicop_rgba_span(ctx, span, span->array->rgba);
  1025.          monoColor = GL_FALSE;
  1026.       }
  1027.       else if (ctx->Color.BlendEnabled) {
  1028.          _mesa_blend_span(ctx, span, span->array->rgba);
  1029.          monoColor = GL_FALSE;
  1030.       }
  1031.  
  1032.       /* Color component masking */
  1033.       if (colorMask != 0xffffffff) {
  1034.          _mesa_mask_rgba_span(ctx, span, span->array->rgba);
  1035.          monoColor = GL_FALSE;
  1036.       }
  1037.  
  1038.       /* write pixels */
  1039.       if (span->arrayMask & SPAN_XY) {
  1040.          /* array of pixel coords */
  1041.          /* XXX test for mono color */
  1042.          (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
  1043.              span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
  1044.          if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
  1045.             _mesa_write_alpha_pixels(ctx, span->end,
  1046.                                      span->array->x, span->array->y,
  1047.                                      (const GLchan (*)[4]) span->array->rgba,
  1048.                                      span->array->mask);
  1049.          }
  1050.       }
  1051.       else {
  1052.          /* horizontal run of pixels */
  1053.          if (monoColor) {
  1054.             /* all pixels have same color */
  1055.             GLchan color[4];
  1056.             color[RCOMP] = FixedToChan(span->red);
  1057.             color[GCOMP] = FixedToChan(span->green);
  1058.             color[BCOMP] = FixedToChan(span->blue);
  1059.             color[ACOMP] = FixedToChan(span->alpha);
  1060.             (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
  1061.                                                 span->y, color, span->array->mask);
  1062.             if (swrast->_RasterMask & ALPHABUF_BIT) {
  1063.                _mesa_write_mono_alpha_span(ctx, span->end, span->x, span->y,
  1064.                       color[ACOMP],
  1065.                       span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
  1066.             }
  1067.          }
  1068.          else {
  1069.             /* each pixel is a different color */
  1070.             (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
  1071.                       (const GLchan (*)[4]) span->array->rgba,
  1072.                       span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
  1073.             if (swrast->_RasterMask & ALPHABUF_BIT) {
  1074.                _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
  1075.                       (const GLchan (*)[4]) span->array->rgba,
  1076.                       span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
  1077.             }
  1078.          }
  1079.       }
  1080.    }
  1081.  
  1082.    span->interpMask = origInterpMask;
  1083.    span->arrayMask = origArrayMask;
  1084. }
  1085.  
  1086.  
  1087. /**
  1088.  * Add specular color to base color.  This is used only when
  1089.  * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
  1090.  */
  1091. static void
  1092. add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
  1093. {
  1094.    GLuint i;
  1095.    for (i = 0; i < n; i++) {
  1096. #if CHAN_TYPE == GL_FLOAT
  1097.       /* no clamping */
  1098.       rgba[i][RCOMP] += specular[i][RCOMP];
  1099.       rgba[i][GCOMP] += specular[i][GCOMP];
  1100.       rgba[i][BCOMP] += specular[i][BCOMP];
  1101. #else
  1102.       GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
  1103.       GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
  1104.       GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
  1105.       rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
  1106.       rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
  1107.       rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
  1108. #endif
  1109.    }
  1110. }
  1111.  
  1112.  
  1113. /**
  1114.  * This function may modify any of the array values in the span.
  1115.  * span->interpMask and span->arrayMask may be changed but will be restored
  1116.  * to their original values before returning.
  1117.  */
  1118. void
  1119. _mesa_write_texture_span( GLcontext *ctx, struct sw_span *span)
  1120. {
  1121.    const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
  1122.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1123.    const GLuint origArrayMask = span->arrayMask;
  1124.  
  1125.    ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
  1126.          span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
  1127.    ASSERT(span->end <= MAX_WIDTH);
  1128.    ASSERT((span->interpMask & span->arrayMask) == 0);
  1129.    ASSERT(ctx->Texture._EnabledUnits);
  1130.  
  1131.    /*
  1132.    printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
  1133.    */
  1134.  
  1135.    if (span->arrayMask & SPAN_MASK) {
  1136.       /* mask was initialized by caller, probably glBitmap */
  1137.       span->writeAll = GL_FALSE;
  1138.    }
  1139.    else {
  1140.       MEMSET(span->array->mask, 1, span->end);
  1141.       span->writeAll = GL_TRUE;
  1142.    }
  1143.  
  1144.    /* Clipping */
  1145.    if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
  1146.       if (!clip_span(ctx, span)) {
  1147.         return;
  1148.       }
  1149.    }
  1150.  
  1151. #ifdef DEBUG
  1152.    if (span->arrayMask & SPAN_XY) {
  1153.       GLuint i;
  1154.       for (i = 0; i < span->end; i++) {
  1155.          if (span->array->mask[i]) {
  1156.             assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
  1157.             assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
  1158.             assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
  1159.             assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
  1160.          }
  1161.       }
  1162.    }
  1163. #endif
  1164.  
  1165.    /* Polygon Stippling */
  1166.    if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
  1167.       stipple_polygon_span(ctx, span);
  1168.    }
  1169.  
  1170.    /* Need texture coordinates now */
  1171.    if ((span->interpMask & SPAN_TEXTURE)
  1172.        && (span->arrayMask & SPAN_TEXTURE) == 0)
  1173.       interpolate_texcoords(ctx, span);
  1174.  
  1175.    /* Texture with alpha test */
  1176.    if (ctx->Color.AlphaEnabled) {
  1177.  
  1178.       /* Now we need the rgba array, fill it in if needed */
  1179.       if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
  1180.          interpolate_colors(ctx, span);
  1181.  
  1182.       /* Texturing without alpha is done after depth-testing which
  1183.        * gives a potential speed-up.
  1184.        */
  1185.       _swrast_texture_span( ctx, span );
  1186.  
  1187.       /* Do the alpha test */
  1188.       if (!_mesa_alpha_test(ctx, span)) {
  1189.          span->arrayMask = origArrayMask;
  1190.         return;
  1191.       }
  1192.    }
  1193.  
  1194.    /* Stencil and Z testing */
  1195.    if (ctx->Stencil.Enabled || ctx->Depth.Test) {
  1196.       if (span->interpMask & SPAN_Z)
  1197.          _mesa_span_interpolate_z(ctx, span);
  1198.  
  1199.       if (ctx->Stencil.Enabled) {
  1200.          if (!_mesa_stencil_and_ztest_span(ctx, span)) {
  1201.             span->arrayMask = origArrayMask;
  1202.             return;
  1203.          }
  1204.       }
  1205.       else {
  1206.          ASSERT(ctx->Depth.Test);
  1207.          ASSERT(span->arrayMask & SPAN_Z);
  1208.          /* regular depth testing */
  1209.          if (!_mesa_depth_test_span(ctx, span)) {
  1210.             span->arrayMask = origArrayMask;
  1211.             return;
  1212.          }
  1213.       }
  1214.    }
  1215.  
  1216.    /* if we get here, some fragments passed the depth test */
  1217.    ctx->OcclusionResult = GL_TRUE;
  1218.  
  1219.    /* We had to wait until now to check for glColorMask(F,F,F,F) because of
  1220.     * the occlusion test.
  1221.     */
  1222.    if (colorMask == 0x0) {
  1223.       span->arrayMask = origArrayMask;
  1224.       return;
  1225.    }
  1226.  
  1227.    /* Texture without alpha test */
  1228.    if (!ctx->Color.AlphaEnabled) {
  1229.  
  1230.       /* Now we need the rgba array, fill it in if needed */
  1231.       if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
  1232.          interpolate_colors(ctx, span);
  1233.  
  1234.       _swrast_texture_span( ctx, span );
  1235.    }
  1236.  
  1237.    ASSERT(span->arrayMask & SPAN_RGBA);
  1238.  
  1239.    /* Add base and specular colors */
  1240.    if (ctx->Fog.ColorSumEnabled ||
  1241.        (ctx->Light.Enabled &&
  1242.         ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
  1243.       if (span->interpMask & SPAN_SPEC) {
  1244.          interpolate_specular(ctx, span);
  1245.       }
  1246.       ASSERT(span->arrayMask & SPAN_SPEC);
  1247.       add_colors( span->end, span->array->rgba, span->array->spec );
  1248.    }
  1249.  
  1250.    /* Fog */
  1251.    if (ctx->Fog.Enabled) {
  1252.       _mesa_fog_rgba_span(ctx, span);
  1253.    }
  1254.  
  1255.    /* Antialias coverage application */
  1256.    if (span->arrayMask & SPAN_COVERAGE) {
  1257.       GLchan (*rgba)[4] = span->array->rgba;
  1258.       GLfloat *coverage = span->array->coverage;
  1259.       GLuint i;
  1260.       for (i = 0; i < span->end; i++) {
  1261.          rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
  1262.       }
  1263.    }
  1264.  
  1265.    if (swrast->_RasterMask & MULTI_DRAW_BIT) {
  1266.       multi_write_rgba_span(ctx, span);
  1267.    }
  1268.    else {
  1269.       /* normal: write to exactly one buffer */
  1270.       if (ctx->Color.ColorLogicOpEnabled) {
  1271.          _mesa_logicop_rgba_span(ctx, span, span->array->rgba);
  1272.       }
  1273.       else if (ctx->Color.BlendEnabled) {
  1274.          _mesa_blend_span(ctx, span, span->array->rgba);
  1275.       }
  1276.  
  1277.       if (colorMask != 0xffffffff) {
  1278.          _mesa_mask_rgba_span(ctx, span, span->array->rgba);
  1279.       }
  1280.  
  1281.  
  1282.       if (span->arrayMask & SPAN_XY) {
  1283.          /* array of pixel coords */
  1284.          (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
  1285.              span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
  1286.          if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
  1287.             _mesa_write_alpha_pixels(ctx, span->end,
  1288.                                      span->array->x, span->array->y,
  1289.                                      (const GLchan (*)[4]) span->array->rgba,
  1290.                                      span->array->mask);
  1291.          }
  1292.       }
  1293.       else {
  1294.          /* horizontal run of pixels */
  1295.          (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
  1296.                                        (const GLchan (*)[4]) span->array->rgba,
  1297.                                        span->writeAll ? NULL : span->array->mask);
  1298.          if (swrast->_RasterMask & ALPHABUF_BIT) {
  1299.             _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
  1300.                                    (const GLchan (*)[4]) span->array->rgba,
  1301.                                    span->writeAll ? NULL : span->array->mask);
  1302.          }
  1303.       }
  1304.    }
  1305.  
  1306.    span->arrayMask = origArrayMask;
  1307. }
  1308.  
  1309.  
  1310.  
  1311. /**
  1312.  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
  1313.  * reading ouside the buffer's boundaries.
  1314.  */
  1315. void
  1316. _mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
  1317.                       GLuint n, GLint x, GLint y, GLchan rgba[][4] )
  1318. {
  1319.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1320.    const GLint bufWidth = (GLint) buffer->Width;
  1321.    const GLint bufHeight = (GLint) buffer->Height;
  1322.  
  1323.    if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
  1324.       /* completely above, below, or right */
  1325.       /* XXX maybe leave undefined? */
  1326.       _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
  1327.    }
  1328.    else {
  1329.       GLint skip, length;
  1330.       if (x < 0) {
  1331.          /* left edge clippping */
  1332.          skip = -x;
  1333.          length = (GLint) n - skip;
  1334.          if (length < 0) {
  1335.             /* completely left of window */
  1336.             return;
  1337.          }
  1338.          if (length > bufWidth) {
  1339.             length = bufWidth;
  1340.          }
  1341.       }
  1342.       else if ((GLint) (x + n) > bufWidth) {
  1343.          /* right edge clipping */
  1344.          skip = 0;
  1345.          length = bufWidth - x;
  1346.          if (length < 0) {
  1347.             /* completely to right of window */
  1348.             return;
  1349.          }
  1350.       }
  1351.       else {
  1352.          /* no clipping */
  1353.          skip = 0;
  1354.          length = (GLint) n;
  1355.       }
  1356.  
  1357.       (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
  1358.       if (buffer->UseSoftwareAlphaBuffers) {
  1359.          _mesa_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
  1360.       }
  1361.    }
  1362. }
  1363.  
  1364.  
  1365. /**
  1366.  * Read CI pixels from frame buffer.  Clipping will be done to prevent
  1367.  * reading ouside the buffer's boundaries.
  1368.  */
  1369. void
  1370. _mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
  1371.                        GLuint n, GLint x, GLint y, GLuint indx[] )
  1372. {
  1373.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  1374.    const GLint bufWidth = (GLint) buffer->Width;
  1375.    const GLint bufHeight = (GLint) buffer->Height;
  1376.  
  1377.    if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
  1378.       /* completely above, below, or right */
  1379.       _mesa_bzero(indx, n * sizeof(GLuint));
  1380.    }
  1381.    else {
  1382.       GLint skip, length;
  1383.       if (x < 0) {
  1384.          /* left edge clippping */
  1385.          skip = -x;
  1386.          length = (GLint) n - skip;
  1387.          if (length < 0) {
  1388.             /* completely left of window */
  1389.             return;
  1390.          }
  1391.          if (length > bufWidth) {
  1392.             length = bufWidth;
  1393.          }
  1394.       }
  1395.       else if ((GLint) (x + n) > bufWidth) {
  1396.          /* right edge clipping */
  1397.          skip = 0;
  1398.          length = bufWidth - x;
  1399.          if (length < 0) {
  1400.             /* completely to right of window */
  1401.             return;
  1402.          }
  1403.       }
  1404.       else {
  1405.          /* no clipping */
  1406.          skip = 0;
  1407.          length = (GLint) n;
  1408.       }
  1409.  
  1410.       (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
  1411.    }
  1412. }
  1413.