s_span.c revision 31f12f504e61cb2ad65b8890a68eb7154edcb64b
131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/* $Id: s_span.c,v 1.37 2002/03/16 18:02:08 brianp Exp $ */
2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
3e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
4e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library
59927f1978da8530416f699d084dda099720e43e6Brian Paul * Version:  4.1
622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
79927f1978da8530416f699d084dda099720e43e6Brian Paul * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
822144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * copy of this software and associated documentation files (the "Software"),
11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to deal in the Software without restriction, including without limitation
12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
14e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Software is furnished to do so, subject to the following conditions:
1522144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
16e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice shall be included
17e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in all copies or substantial portions of the Software.
1822144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
26e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
27e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
2879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
29bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul * \file swrast/s_span.c
3079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \brief Span processing functions used by all rasterization functions.
3179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * This is where all the per-fragment tests are performed
3279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \author Brian Paul
33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
34e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
35e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "glheader.h"
36e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "colormac.h"
3771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul#include "context.h"
38e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "macros.h"
3931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul#include "mmath.h"
40e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "mem.h"
41e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alpha.h"
43e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alphabuf.h"
44e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
45cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
48e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
51e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
52e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_texture.h"
53e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
5579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's Z interpolation values to the RasterPos Z.
572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_z( GLcontext *ctx, struct sw_span *span )
612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.depthBits <= 16)
632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax);
642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else
652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax);
662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->zStep = 0;
672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_Z;
682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
7179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's fog interpolation values to the RasterPos fog.
732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_fog( GLcontext *ctx, struct sw_span *span )
772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
78c9ceef41fe89f5ba6e16ec51c1f9b7bfd8119c64Brian Paul   span->fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->fogStep = 0;
802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_FOG;
812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's color or index interpolation values to the RasterPos color.
862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_color( GLcontext *ctx, struct sw_span *span )
902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.rgbMode) {
922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan r, g, b, a;
932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red = r;
992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = g;
1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue = b;
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = a;
1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red   = IntToFixed(r);
1042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = IntToFixed(g);
1052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue  = IntToFixed(b);
1062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = IntToFixed(a);
1072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->redStep = 0;
1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->greenStep = 0;
1102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blueStep = 0;
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alphaStep = 0;
1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_RGBA;
1132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->index = IntToFixed(ctx->Current.RasterIndex);
1162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->indexStep = 0;
1172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_INDEX;
1182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.rgba array from the interpolation values */
1232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_colors(GLcontext *ctx, struct sw_span *span)
1252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed r = span->red;
1272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed g = span->green;
1282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed b = span->blue;
1292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed a = span->alpha;
1302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint dr = span->redStep;
1312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint dg = span->greenStep;
1322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint db = span->blueStep;
1332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint da = span->alphaStep;
1342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
1352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLchan (*rgba)[4] = span->color.rgba;
1362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
1372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_RGBA);
1392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
1412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
1422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan color[4];
1432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[RCOMP] = FixedToChan(r);
1442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[GCOMP] = FixedToChan(g);
1452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[BCOMP] = FixedToChan(b);
1462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[ACOMP] = FixedToChan(a);
1472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         COPY_CHAN4(span->color.rgba[i], color);
1492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
1532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][RCOMP] = FixedToChan(r);
1552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][GCOMP] = FixedToChan(g);
1562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][BCOMP] = FixedToChan(b);
1572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][ACOMP] = FixedToChan(a);
1582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += dr;
1592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += dg;
1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += db;
1612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         a += da;
1622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_RGBA;
1652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
1692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_indexes(GLcontext *ctx, struct sw_span *span)
1712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
1732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
1742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
1752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint *indexes = span->color.index;
1762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
1772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_INDEX);
1782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
1802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
1812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
1822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
1842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
1882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
1902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
1912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
1942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.specArray array from the interpolation values */
1982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_specular(GLcontext *ctx, struct sw_span *span)
2002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
2022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
2032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan r = FixedToChan(span->specRed);
2042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan g = FixedToChan(span->specGreen);
2052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan b = FixedToChan(span->specBlue);
2062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
2082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][RCOMP] = r;
2092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][GCOMP] = g;
2102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][BCOMP] = b;
2112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
2152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
2162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat r = span->specRed;
2172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat g = span->specGreen;
2182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat b = span->specBlue;
2192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
2202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed r = span->specRed;
2212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed g = span->specGreen;
2222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed b = span->specBlue;
2232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
2242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
2262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][RCOMP] = FixedToChan(r);
2272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][GCOMP] = FixedToChan(g);
2282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][BCOMP] = FixedToChan(b);
2292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += span->specRedStep;
2302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += span->specGreenStep;
2312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += span->specBlueStep;
2322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_SPEC;
2352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */
239711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
240711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul_mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
2412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
2432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
2442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_Z);
2462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.depthBits <= 16) {
2482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
2492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->zArray[i] = FixedToInt(zval);
2512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
2522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
2562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
2572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->zArray[i] = zval;
2592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
2602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
2632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
266c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
26731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
268c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
269c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
27031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
27131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
27231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
27331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
274c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
27531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
27631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
27731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
27831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
27931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat x = sqrt(dudx * dudx + dvdx * dvdx);
28031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat y = sqrt(dudy * dudy + dvdy * dvdy);
28131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
28231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
28331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
284c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
285c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
286c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
28731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
28831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/*
28931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This is a faster approximation
290c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
29131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
29231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
29331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
29431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
295c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
29631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
29731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
29831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
29931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
30031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
30131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
30231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
30331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
30431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
30531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
30631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
30731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
30831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
30931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
310c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
311c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
312c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
313c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Fill in the span.texcoords array from the interpolation values.
314c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * XXX We could optimize here for the case when dq = 0.  That would
315c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * usually be the case when using an orthographic projection.
316c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
3172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
3182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_texcoords(GLcontext *ctx, struct sw_span *span)
3192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_TEXTURE);
3212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Texture._ReallyEnabled & ~TEXTURE0_ANY) {
32331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* multitexture */
32431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      GLuint u;
32531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
32631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         if (ctx->Texture.Unit[u]._ReallyEnabled) {
32731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
32831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
32931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
33031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            if (needLambda) {
33131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat texW = (GLfloat) img->Width;
33231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat texH = (GLfloat) img->Height;
33331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
33431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdy = span->texStepY[u][0];
33531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
33631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdy = span->texStepY[u][1];
33731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
33831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
33931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdy = span->texStepY[u][3];
3402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
3412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
3422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
3432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
3442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
34531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               for (i = 0; i < span->end; i++) {
3462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
34731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  span->texcoords[u][i][0] = s * invQ;
34831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  span->texcoords[u][i][1] = t * invQ;
34931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  span->texcoords[u][i][2] = r * invQ;
35031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  span->lambda[u][i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
35131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                                                      dqdx, dqdy, texW, texH,
35231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                                                      s, t, q, invQ);
35331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  s += dsdx;
35431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  t += dtdx;
35531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  r += drdx;
35631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  q += dqdx;
3572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
35831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               span->arrayMask |= SPAN_LAMBDA;
3592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
36031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
36131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
36231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
36331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
36431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
3652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
3662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
3672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
3682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
3692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
37031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               if (dqdx == 0.0) {
371c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  /* Ortho projection or polygon's parallel to window X axis */
3722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
373c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
374c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][0] = s * invQ;
375c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][1] = t * invQ;
376c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][2] = r * invQ;
37731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     span->lambda[u][i] = 0.0;
37831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
37931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
38031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
381c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
382c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               }
383c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               else {
384c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
385c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
386c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][0] = s * invQ;
387c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][1] = t * invQ;
388c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][2] = r * invQ;
38931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     span->lambda[u][i] = 0.0;
39031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
39131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
39231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
39331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     q += dqdx;
394c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
39631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            } /* lambda */
39731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         } /* if */
39831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      } /* for */
3992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
40131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* single texture */
40231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
40331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
40431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
40531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      if (needLambda) {
4062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* just texture unit 0, with lambda */
40731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat texW = (GLfloat) img->Width;
40831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat texH = (GLfloat) img->Height;
40931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
41031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdy = span->texStepY[0][0];
41131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
41231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdy = span->texStepY[0][1];
41331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
41431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
41531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdy = span->texStepY[0][3];
4162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
4172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
4182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
4192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
4202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
42131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         for (i = 0; i < span->end; i++) {
4222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
42331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            span->lambda[0][i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
42431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                                                dqdx, dqdy, texW, texH,
42531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                                                s, t, q, invQ);
42631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            span->texcoords[0][i][0] = s * invQ;
42731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            span->texcoords[0][i][1] = t * invQ;
42831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            span->texcoords[0][i][2] = r * invQ;
42931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            s += dsdx;
43031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            t += dtdx;
43131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            r += drdx;
43231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            q += dqdx;
4332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
4342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask |= SPAN_LAMBDA;
4352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      else {
437733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* just texture 0, without lambda */
43831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
43931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
44031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
44131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
4422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
4432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
4442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
4452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
4462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
44731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         if (dqdx == 0.0) {
448c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            /* Ortho projection or polygon's parallel to window X axis */
4492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
450c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
451c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][0] = s * invQ;
452c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][1] = t * invQ;
453c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][2] = r * invQ;
45431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
45531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
45631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
457c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
458c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         }
459c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         else {
460c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
461c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
462c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][0] = s * invQ;
463c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][1] = t * invQ;
464c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][2] = r * invQ;
46531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
46631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
46731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
46831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               q += dqdx;
469c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
4702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
4712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
47310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
474e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
475e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
47679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
477e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
478e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
4795071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
480733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulstipple_polygon_span( GLcontext *ctx, struct sw_span *span )
48110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
48210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint highbit = 0x80000000;
483733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLuint stipple = ctx->PolygonStipple[span->y % 32];
484733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   GLuint i, m;
485733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
486733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
487733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->arrayMask & SPAN_XY) == 0);
48810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
48910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   m = highbit >> (GLuint) (span->x % 32);
49010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
49110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (i = 0; i < span->end; i++) {
49210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if ((m & stipple) == 0) {
49310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul	 span->mask[i] = 0;
49410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
49510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      m = m >> 1;
49610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (m == 0) {
49710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         m = highbit;
49810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
49910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
5002ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
50110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
50210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
503e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
50479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
505733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
506733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
507733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
508733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
50910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
51010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
51110f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic GLuint
512733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulclip_span( GLcontext *ctx, struct sw_span *span )
51310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
514733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
515733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
516733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
517733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
518733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
519733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
520733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
521733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint *x = span->xArray;
522733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint *y = span->yArray;
523733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
524733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLubyte *mask = span->mask;
525733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
526b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
527b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
528b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
529b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
530b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
531b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
532b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
533b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
534b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
535b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
536b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
537b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
538b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
53910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
540733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
54110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
542733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
543733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
544733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
545733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
546733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
547733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
548733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
549733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
550733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
551733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
552733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
55310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
554733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
555733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
556733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
557733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
558733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         BZERO(span->mask, (xmin - x) * sizeof(GLubyte));
55910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
560733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
561733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
562733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
563733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
564733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
56510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
56610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
567733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
568733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
56910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
57010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
57110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
572e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
57379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
574e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Draw to more than one color buffer (or none).
575e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
5765071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
577733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_index_span( GLcontext *ctx, struct sw_span *span )
578e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
579709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
580e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   GLuint bufferBit;
581e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
582e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* loop over four possible dest color buffers */
583e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
584e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (bufferBit & ctx->Color.DrawDestMask) {
585e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         GLuint indexTmp[MAX_WIDTH];
586733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(span->end < MAX_WIDTH);
587e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
588e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (bufferBit == FRONT_LEFT_BIT)
589e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
590e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         else if (bufferBit == FRONT_RIGHT_BIT)
591e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
592e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         else if (bufferBit == BACK_LEFT_BIT)
593e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
594e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         else
595e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
596e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
597e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* make copy of incoming indexes */
598733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         MEMCPY( indexTmp, span->color.index, span->end * sizeof(GLuint) );
599733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
600e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (ctx->Color.IndexLogicOpEnabled) {
601733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_logicop_ci_span(ctx, span, indexTmp);
602e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
603733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
6047956292a765910077f50352d7cd0174e1e66d26cBrian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
605733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_mask_index_span(ctx, span, indexTmp);
606733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
607733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
608733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (span->arrayMask & SPAN_XY) {
609733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* array of pixel coords */
610733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
611733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->xArray, span->yArray,
612733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              indexTmp, span->mask);
613733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
614733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
615733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* horizontal run of pixels */
616733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
617733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            indexTmp, span->mask);
618e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
619e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
620e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
621e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
622e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* restore default dest buffer */
623e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer);
624e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
625e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
626e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
62779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
62810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul * Draw to more than one RGBA color buffer (or none).
629f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * All fragment operations, up to (but not) blending/logicop should
630f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * have been done first.
63110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
63210f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic void
633733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_rgba_span( GLcontext *ctx, struct sw_span *span )
63410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
63510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
63610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   GLuint bufferBit;
63710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
63810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
639733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(colorMask != 0x0);
640733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
64110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   if (ctx->Color.DrawBuffer == GL_NONE)
64210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
64310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
64410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* loop over four possible dest color buffers */
64510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
64610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (bufferBit & ctx->Color.DrawDestMask) {
64710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         GLchan rgbaTmp[MAX_WIDTH][4];
648733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(span->end < MAX_WIDTH);
64910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
65010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         if (bufferBit == FRONT_LEFT_BIT) {
65110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
65210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
65310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
65410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else if (bufferBit == FRONT_RIGHT_BIT) {
65510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
65610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
65710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
65810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else if (bufferBit == BACK_LEFT_BIT) {
65910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
66010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
66110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
66210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else {
66310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
66410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
66510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
66610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
66710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         /* make copy of incoming colors */
668733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         MEMCPY( rgbaTmp, span->color.rgba, 4 * span->end * sizeof(GLchan) );
66910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
67010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         if (ctx->Color.ColorLogicOpEnabled) {
671733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_logicop_rgba_span(ctx, span, rgbaTmp);
67210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
67310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else if (ctx->Color.BlendEnabled) {
674733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_blend_span(ctx, span, rgbaTmp);
67510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
676733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
677733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (colorMask != 0xffffffff) {
678733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_mask_rgba_span(ctx, span, rgbaTmp);
67910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
68010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
681733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (span->arrayMask & SPAN_XY) {
682733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* array of pixel coords */
683733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
684733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->xArray, span->yArray,
685733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              (const GLchan (*)[4]) rgbaTmp,
686733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->mask);
687733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
688733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_pixels(ctx, span->end,
689733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                        span->xArray, span->yArray,
690733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                        (const GLchan (*)[4]) rgbaTmp,
691733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                        span->mask);
692733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
693733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
694733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
695733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* horizontal run of pixels */
696733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
697733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            (const GLchan (*)[4]) rgbaTmp,
698733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            span->mask);
699733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (swrast->_RasterMask & ALPHABUF_BIT) {
700733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
701733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                      (const GLchan (*)[4]) rgbaTmp,
702733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                      span->mask);
703733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
70410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
70510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
70610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
70710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
70810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* restore default dest buffer */
70910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
71010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
71110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
71210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
713e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
71479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
7157956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span.
7167956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
7177956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
71810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
71910f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
7202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_write_index_span( GLcontext *ctx, struct sw_span *span,
7212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul			GLenum primitive)
72210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
72310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
7247956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint origInterpMask = span->interpMask;
7252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint origArrayMask = span->arrayMask;
72610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
727733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
728733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
7297956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
7307956292a765910077f50352d7cd0174e1e66d26cBrian Paul
731733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
732733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
733733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
734733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
735733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
736733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      MEMSET(span->mask, 1, span->end);
737733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
73810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
73910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
740733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
741733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
742b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul       || (primitive == GL_POINT) || (primitive == GL_LINE)) {
743733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
74486ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
745e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
746e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
747e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
748b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
749b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
750b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      int i;
751b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
752b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         if (span->mask[i]) {
753b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
754b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
755b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
756b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
757b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
758b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
759b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
760b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
761b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
762e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
763733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
76410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
765e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
766e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
7677956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Depth test and stencil */
7687956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
7697956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (span->interpMask & SPAN_Z)
770711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
77110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
7727956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
77379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
7747956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
7757956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
7767956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
7772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
7787956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
7797956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
78079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul         if (!_mesa_depth_test_span(ctx, span)) {
7817956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
7827956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
7837956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
7842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
78510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
78610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
78710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* if we get here, something passed the depth test */
78810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   ctx->OcclusionResult = GL_TRUE;
78910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
7907956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
7917956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
79210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
7932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
79410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
79510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
79610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
7977956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
7987956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (span->interpMask & SPAN_INDEX) {
7992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      interpolate_indexes(ctx, span);
8007956292a765910077f50352d7cd0174e1e66d26cBrian Paul      /* clear the bit - this allows the WriteMonoCISpan optimization below */
8017956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->interpMask &= ~SPAN_INDEX;
8027956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
80310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8047956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
8052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Fog.Enabled) {
806711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_ci_span(ctx, span);
807e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
808e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
8092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
8102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
8112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
8127956292a765910077f50352d7cd0174e1e66d26cBrian Paul      GLuint *index = span->color.index;
81310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
8142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         ASSERT(span->coverage[i] < 16);
8152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) (span->coverage[i]));
8165071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
8172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
8185071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
8192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
8202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* draw to zero or two or more buffers */
821733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_index_span(ctx, span);
822e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
823e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
8242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* normal situation: draw to exactly one buffer */
8252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      if (ctx->Color.IndexLogicOpEnabled) {
826733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_logicop_ci_span(ctx, span, span->color.index);
82710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
8282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8297956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Color.IndexMask != 0xffffffff) {
830733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_mask_index_span(ctx, span, span->color.index);
831e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
8322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* write pixels */
834733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
835733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
836733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
837733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color index */
838733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
839733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                span->xArray, span->yArray,
840733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                FixedToInt(span->index),
841733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                span->mask);
842733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
843733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
844733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->xArray,
845733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->yArray, span->color.index,
846733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->mask );
847733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
8487956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
8497956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
850733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
851733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
852733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color index */
853733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
854733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              FixedToInt(span->index),
855733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->mask);
856733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
857733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
858733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
859733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            span->color.index, span->mask);
860733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
8617956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
862e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
8632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8647956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
8652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
866e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
867e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
868e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
86979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
8707956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span.
8717956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
8727956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
8735d2621928823a06006c1586efe78fe8bf65a7e1fBrian Paul */
8745071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
87510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul_mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span,
8762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul		       GLenum primitive)
877e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
878cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8797956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
8807956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint origInterpMask = span->interpMask;
8812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint origArrayMask = span->arrayMask;
8827956292a765910077f50352d7cd0174e1e66d26cBrian Paul   GLboolean monoColor;
8837956292a765910077f50352d7cd0174e1e66d26cBrian Paul
884733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
8857956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
886ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
887bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#ifdef DEBUG
888733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (ctx->Fog.Enabled)
889733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
890bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul   if (ctx->Depth.Test)
891bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul      ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
892bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#endif
893733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
894733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /*
895bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul   printf("%s()  interp 0x%x  array 0x%x  p=0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask, primitive);
896733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   */
897e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
898733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
899733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
900733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
901733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
902733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
903733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      MEMSET(span->mask, 1, span->end);
904733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
905733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
906e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9077956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Determine if we have mono-chromatic colors */
9087956292a765910077f50352d7cd0174e1e66d26cBrian Paul   monoColor = (span->interpMask & SPAN_RGBA) &&
9097956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->redStep == 0 && span->greenStep == 0 &&
9107956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->blueStep == 0 && span->alphaStep == 0;
9117956292a765910077f50352d7cd0174e1e66d26cBrian Paul
912733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
913733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
914b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul       || (primitive == GL_POINT) || (primitive == GL_LINE)) {
915733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
91686ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
917e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
918e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
919e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
920b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
921b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
922b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      int i;
923b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
924b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         if (span->mask[i]) {
925b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
926b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
927b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
928b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
929b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
930b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
931b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
932b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
933b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
934e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
9357956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
9367956292a765910077f50352d7cd0174e1e66d26cBrian Paul      stipple_polygon_span(ctx, span);
93710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
93810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
939e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Do the alpha test */
940e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (ctx->Color.AlphaEnabled) {
941ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      if (!_mesa_alpha_test(ctx, span)) {
9427956292a765910077f50352d7cd0174e1e66d26cBrian Paul         span->interpMask = origInterpMask;
9432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask = origArrayMask;
944e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 return;
945e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
94610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
94710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
948f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
949f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
950f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
951711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
952f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
953f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (ctx->Stencil.Enabled) {
954f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
9557956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->interpMask = origInterpMask;
956f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
957f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            return;
95810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
95910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
96010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      else {
961f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
962f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
963f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         /* regular depth testing */
964f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_depth_test_span(ctx, span)) {
9657956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->interpMask = origInterpMask;
966f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
967f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            return;
96810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
96910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
970e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
971e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
972e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* if we get here, something passed the depth test */
973e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   ctx->OcclusionResult = GL_TRUE;
974e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9757956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* can't abort span-writing until after occlusion testing */
9767956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (colorMask == 0x0) {
9777956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->interpMask = origInterpMask;
9787956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->arrayMask = origArrayMask;
9797956292a765910077f50352d7cd0174e1e66d26cBrian Paul      return;
9807956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
9817956292a765910077f50352d7cd0174e1e66d26cBrian Paul
982ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /* Now we may need to interpolate the colors */
983ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
984ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      interpolate_colors(ctx, span);
985ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      /* clear the bit - this allows the WriteMonoCISpan optimization below */
986ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      span->interpMask &= ~SPAN_RGBA;
987ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   }
988ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
9896e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
990b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul   if (ctx->Fog.Enabled) {
991711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_rgba_span(ctx, span);
9927956292a765910077f50352d7cd0174e1e66d26cBrian Paul      monoColor = GL_FALSE;
993b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul   }
994b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul
9955071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul   /* Antialias coverage application */
9962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
9977956292a765910077f50352d7cd0174e1e66d26cBrian Paul      GLchan (*rgba)[4] = span->color.rgba;
9985071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      GLuint i;
99910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
100010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
10015071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
10027956292a765910077f50352d7cd0174e1e66d26cBrian Paul      monoColor = GL_FALSE;
10035071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul   }
10045071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
1005cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1006733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_rgba_span(ctx, span);
1007e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1008e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1009e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* normal: write to exactly one buffer */
1010e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (ctx->Color.ColorLogicOpEnabled) {
1011733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_logicop_rgba_span(ctx, span, span->color.rgba);
10127956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1013e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1014e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else if (ctx->Color.BlendEnabled) {
1015733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_blend_span(ctx, span, span->color.rgba);
10167956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1017e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
101895e2c72fd52d87163eb543555345f115f050f3aaBrian Paul
1019e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* Color component masking */
10207956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (colorMask != 0xffffffff) {
1021733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_mask_rgba_span(ctx, span, span->color.rgba);
10227956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1023e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1024e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1025e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* write pixels */
1026733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
1027733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
1028733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* XXX test for mono color */
1029733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->xArray,
1030733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul             span->yArray, (const GLchan (*)[4]) span->color.rgba, span->mask);
1031733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1032733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_pixels(ctx, span->end,
1033733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->xArray, span->yArray,
1034733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     (const GLchan (*)[4]) span->color.rgba,
1035733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->mask);
1036733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1037e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1038e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1039733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
1040733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (monoColor) {
1041733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color */
1042733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            GLchan color[4];
1043733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[RCOMP] = FixedToChan(span->red);
1044733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[GCOMP] = FixedToChan(span->green);
1045733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[BCOMP] = FixedToChan(span->blue);
1046733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[ACOMP] = FixedToChan(span->alpha);
1047733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
1048733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                span->y, color, span->mask);
1049733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* XXX software alpha buffer writes! */
1050733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1051733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
1052733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* each pixel is a different color */
1053733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
10547956292a765910077f50352d7cd0174e1e66d26cBrian Paul                      (const GLchan (*)[4]) span->color.rgba,
1055733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                      span->writeAll ? ((const GLubyte *) NULL) : span->mask);
1056733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (swrast->_RasterMask & ALPHABUF_BIT) {
1057733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
10587956292a765910077f50352d7cd0174e1e66d26cBrian Paul                      (const GLchan (*)[4]) span->color.rgba,
1059733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                      span->writeAll ? ((const GLubyte *) NULL) : span->mask);
1060733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
1061733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1062e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1063e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1064e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
10657956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
10667956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->arrayMask = origArrayMask;
10677956292a765910077f50352d7cd0174e1e66d26cBrian Paul}
1068e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1069e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
107079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1071e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color.  This is used only when
1072f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1073e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
10745071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
1075f1e236987829393c81dc86ea19cb49eefe190317Brian Pauladd_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1076e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1077e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   GLuint i;
1078f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   for (i = 0; i < n; i++) {
10794fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#if CHAN_TYPE == GL_FLOAT
10804fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul      /* no clamping */
1081f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][RCOMP] += specular[i][RCOMP];
1082f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][GCOMP] += specular[i][GCOMP];
1083f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][BCOMP] += specular[i][BCOMP];
10844fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#else
1085f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1086f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1087f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1088e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1089e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1090e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
10914fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#endif
1092e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1093e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1094e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1095e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
109679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1097f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
10987956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
10997956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
110078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
110178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
110278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul_mesa_write_texture_span( GLcontext *ctx, struct sw_span *span,
1103f1e236987829393c81dc86ea19cb49eefe190317Brian Paul                          GLenum primitive )
110478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
110578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
110678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1107f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   const GLuint origArrayMask = span->arrayMask;
1108f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1109733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
11107956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
1111f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(ctx->Texture._ReallyEnabled);
111278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1113ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /*
1114ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1115ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   */
1116ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1117733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1118733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1119733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1120733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1121733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
1122733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      MEMSET(span->mask, 1, span->end);
1123733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
112478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
112578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1126733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
1127733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
1128b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul       || (primitive == GL_POINT) || (primitive == GL_LINE)) {
1129733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1130733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
113178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
113278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
113378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1134b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1135b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1136b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      int i;
1137b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
1138b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         if (span->mask[i]) {
1139b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
1140b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
1141b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
1142b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
1143b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1144b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1145b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1146b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1147b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
114878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1149733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
1150733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
115178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
115278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1153f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Need texture coordinates now */
1154f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if ((span->interpMask & SPAN_TEXTURE)
1155f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       && (span->arrayMask & SPAN_TEXTURE) == 0)
1156f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      interpolate_texcoords(ctx, span);
115778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
115878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Texture with alpha test */
115978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   if (ctx->Color.AlphaEnabled) {
1160f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1161f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1162f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1163f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
1164f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
116578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Texturing without alpha is done after depth-testing which
1166f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       * gives a potential speed-up.
1167f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       */
1168f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      _swrast_multitexture_fragments( ctx, span );
116978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
117078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Do the alpha test */
1171ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      if (!_mesa_alpha_test(ctx, span)) {
1172f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         span->arrayMask = origArrayMask;
1173ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul	 return;
117478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
117578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
117678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1177f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1178f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1179f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
1180711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
118178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
118271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      if (ctx->Stencil.Enabled) {
1183f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
1184f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
118510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1186f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
118771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1188f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      else {
1189f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1190f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
119110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         /* regular depth testing */
1192f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_depth_test_span(ctx, span)) {
1193f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
119410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1195f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
119671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
119771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
119871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1199f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* if we get here, some fragments passed the depth test */
120071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   ctx->OcclusionResult = GL_TRUE;
120171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1202f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1203f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1204f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1205f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1206f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      span->arrayMask = origArrayMask;
1207f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      return;
120871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
120971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1210f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Texture without alpha test */
1211f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (!ctx->Color.AlphaEnabled) {
121271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1213f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1214f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1215f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
121671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1217f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      _swrast_multitexture_fragments( ctx, span );
121871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
121971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1220f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
12212ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
1222f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Add base and specular colors */
1223f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Fog.ColorSumEnabled ||
1224f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       (ctx->Light.Enabled &&
1225f1e236987829393c81dc86ea19cb49eefe190317Brian Paul        ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1226f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_SPEC) {
1227f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_specular(ctx, span);
122871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1229f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      ASSERT(span->arrayMask & SPAN_SPEC);
1230f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      add_colors( span->end, span->color.rgba, span->specArray );
123171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
123271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
12336e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
123471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   if (ctx->Fog.Enabled) {
1235711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_rgba_span(ctx, span);
123671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1237f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
123871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
12392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1240f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLchan (*rgba)[4] = span->color.rgba;
124171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      GLuint i;
124210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
124310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
124471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
124571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
124671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
124771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1248733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_rgba_span(ctx, span);
124971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
125071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   else {
125171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      /* normal: write to exactly one buffer */
125271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      if (ctx->Color.ColorLogicOpEnabled) {
1253733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_logicop_rgba_span(ctx, span, span->color.rgba);
125471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
125595e2c72fd52d87163eb543555345f115f050f3aaBrian Paul      else if (ctx->Color.BlendEnabled) {
1256733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_blend_span(ctx, span, span->color.rgba);
125771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
125871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1259f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (colorMask != 0xffffffff) {
1260733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_mask_rgba_span(ctx, span, span->color.rgba);
126171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
126271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1263733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
1264733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
1265733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
1266733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->xArray,
1267733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul             span->yArray, (const GLchan (*)[4]) span->color.rgba, span->mask);
1268733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1269733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_pixels(ctx, span->end,
1270733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->xArray, span->yArray,
1271733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     (const GLchan (*)[4]) span->color.rgba,
1272733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->mask);
1273733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1274733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
1275733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      else {
1276733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
1277733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1278f1e236987829393c81dc86ea19cb49eefe190317Brian Paul                                       (const GLchan (*)[4]) span->color.rgba,
1279733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                       span->writeAll ? NULL : span->mask);
1280733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (swrast->_RasterMask & ALPHABUF_BIT) {
1281733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
1282733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                   (const GLchan (*)[4]) span->color.rgba,
1283733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                   span->writeAll ? NULL : span->mask);
1284733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
128571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
128671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
128771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1288f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
128910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
129010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1291e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1292e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
129379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1294e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
1295e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1296e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
12975071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
12985071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul_mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
12995071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul                      GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1300e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1301709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1302e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (y < 0 || y >= buffer->Height
1303e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell       || x + (GLint) n < 0 || x >= buffer->Width) {
1304e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1305e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* XXX maybe leave undefined? */
1306e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      BZERO(rgba, 4 * n * sizeof(GLchan));
1307e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1308e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1309e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1310e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
1311e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* left edge clippping */
1312e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1313e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1314e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1315e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1316e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1317e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1318e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length > buffer->Width) {
1319e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            length = buffer->Width;
1320e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1321e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1322e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else if ((GLint) (x + n) > buffer->Width) {
1323e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1324e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1325e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = buffer->Width - x;
1326e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1327e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1328e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1329e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1330e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1331e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1332e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1333e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1334e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1335e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1336e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1337709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell      (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1338e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (buffer->UseSoftwareAlphaBuffers) {
1339733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1340e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1341e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1342e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1343e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1344e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
134579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1346e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read CI pixels from frame buffer.  Clipping will be done to prevent
1347e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1348e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
13495071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
13505071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul_mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
13515071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul                       GLuint n, GLint x, GLint y, GLuint indx[] )
1352e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1353709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1354e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (y < 0 || y >= buffer->Height
1355e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell       || x + (GLint) n < 0 || x >= buffer->Width) {
1356e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1357e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      BZERO(indx, n * sizeof(GLuint));
1358e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1359e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1360e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1361e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
1362e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* left edge clippping */
1363e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1364e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1365e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1366e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1367e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1368e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1369e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length > buffer->Width) {
1370e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            length = buffer->Width;
1371e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1372e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1373e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else if ((GLint) (x + n) > buffer->Width) {
1374e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1375e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1376e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = buffer->Width - x;
1377e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1378e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1379e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1380e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1381e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1382e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1383e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1384e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1385e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1386e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1387e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1388709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell      (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1389e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1390e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1391