s_span.c revision 711e27fda27e4235b20a4cf73c2767c984ab2b81
1711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul/* $Id: s_span.c,v 1.36 2002/02/17 17:30:57 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"
39e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "mem.h"
40e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
41e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alpha.h"
42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alphabuf.h"
43e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
44cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
48e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
51e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_texture.h"
52e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
5479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's Z interpolation values to the RasterPos Z.
562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_z( GLcontext *ctx, struct sw_span *span )
602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.depthBits <= 16)
622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax);
632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else
642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax);
652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->zStep = 0;
662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_Z;
672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
7079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's fog interpolation values to the RasterPos fog.
722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_fog( GLcontext *ctx, struct sw_span *span )
762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
77c9ceef41fe89f5ba6e16ec51c1f9b7bfd8119c64Brian Paul   span->fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->fogStep = 0;
792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_FOG;
802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's color or index interpolation values to the RasterPos color.
852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_color( GLcontext *ctx, struct sw_span *span )
892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.rgbMode) {
912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan r, g, b, a;
922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red = r;
982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = g;
992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue = b;
1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = a;
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red   = IntToFixed(r);
1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = IntToFixed(g);
1042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue  = IntToFixed(b);
1052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = IntToFixed(a);
1062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
1072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->redStep = 0;
1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->greenStep = 0;
1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blueStep = 0;
1102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alphaStep = 0;
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_RGBA;
1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->index = IntToFixed(ctx->Current.RasterIndex);
1152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->indexStep = 0;
1162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_INDEX;
1172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.rgba array from the interpolation values */
1222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_colors(GLcontext *ctx, struct sw_span *span)
1242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed r = span->red;
1262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed g = span->green;
1272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed b = span->blue;
1282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed a = span->alpha;
1292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint dr = span->redStep;
1302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint dg = span->greenStep;
1312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint db = span->blueStep;
1322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint da = span->alphaStep;
1332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
1342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLchan (*rgba)[4] = span->color.rgba;
1352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
1362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_RGBA);
1382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
1402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
1412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan color[4];
1422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[RCOMP] = FixedToChan(r);
1432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[GCOMP] = FixedToChan(g);
1442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[BCOMP] = FixedToChan(b);
1452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[ACOMP] = FixedToChan(a);
1462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         COPY_CHAN4(span->color.rgba[i], color);
1482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
1522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][RCOMP] = FixedToChan(r);
1542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][GCOMP] = FixedToChan(g);
1552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][BCOMP] = FixedToChan(b);
1562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][ACOMP] = FixedToChan(a);
1572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += dr;
1582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += dg;
1592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += db;
1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         a += da;
1612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_RGBA;
1642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
1682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_indexes(GLcontext *ctx, struct sw_span *span)
1702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
1722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
1732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
1742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint *indexes = span->color.index;
1752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
1762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_INDEX);
1772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
1792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
1802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
1812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
1832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
1872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
1892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
1902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
1932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.specArray array from the interpolation values */
1972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_specular(GLcontext *ctx, struct sw_span *span)
1992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
2012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
2022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan r = FixedToChan(span->specRed);
2032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan g = FixedToChan(span->specGreen);
2042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan b = FixedToChan(span->specBlue);
2052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
2072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][RCOMP] = r;
2082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][GCOMP] = g;
2092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][BCOMP] = b;
2102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
2142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
2152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat r = span->specRed;
2162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat g = span->specGreen;
2172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat b = span->specBlue;
2182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
2192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed r = span->specRed;
2202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed g = span->specGreen;
2212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed b = span->specBlue;
2222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
2232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
2252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][RCOMP] = FixedToChan(r);
2262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][GCOMP] = FixedToChan(g);
2272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->specArray[i][BCOMP] = FixedToChan(b);
2282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += span->specRedStep;
2292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += span->specGreenStep;
2302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += span->specBlueStep;
2312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_SPEC;
2342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */
238711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
239711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul_mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
2402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
2422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
2432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_Z);
2452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.depthBits <= 16) {
2472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
2482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->zArray[i] = FixedToInt(zval);
2502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
2512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
2552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
2562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->zArray[i] = zval;
2582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
2592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
2622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
265c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
266c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Return log_base_2(x) / 2.
267c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * We divide by two here since we didn't square rho in the triangle function.
268c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
269c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#ifdef USE_IEEE
270c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
271c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
272c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/* This is pretty fast, but not accurate enough (only 2 fractional bits).
273c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Based on code from http://www.stereopsis.com/log2.html
274c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
275c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paulstatic INLINE GLfloat HALF_LOG2(GLfloat x)
276c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
277c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   const GLfloat y = x * x * x * x;
278c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   const GLuint ix = *((GLuint *) &y);
279c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   const GLuint exp = (ix >> 23) & 0xFF;
280c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   const GLint log2 = ((GLint) exp) - 127;
281c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   return (GLfloat) log2 * (0.5 / 4.0);  /* 4, because of x^4 above */
282c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
283c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
284c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
285c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/* Pretty fast, and accurate.
286c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Based on code from http://www.flipcode.com/totd/
287c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
288c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paulstatic INLINE GLfloat HALF_LOG2(GLfloat val)
289c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
290c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   GLint *exp_ptr = (GLint *) &val;
291c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   GLint x = *exp_ptr;
292c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   const GLint log_2 = ((x >> 23) & 255) - 128;
293c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   x &= ~(255 << 23);
294c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   x += 127 << 23;
295c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   *exp_ptr = x;
296c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   val = ((-1.0f/3) * val + 2) * val - 2.0f/3;
297c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul   return 0.5F * (val + log_2);
298c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
299c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
300c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#else /* USE_IEEE */
301c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
302c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/* Slow, portable solution.
303c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * NOTE: log_base_2(x) = log(x) / log(2)
304c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * NOTE: 1.442695 = 1/log(2).
305c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
306c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#define HALF_LOG2(x)  ((GLfloat) (log(x) * (1.442695F * 0.5F)))
3072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
308c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif /* USE_IEEE */
309c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
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) {
3232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      if (span->interpMask & SPAN_LAMBDA) {
3242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* multitexture, lambda */
3252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint u;
3262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
3272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            if (ctx->Texture.Unit[u]._ReallyEnabled) {
328c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat rho = span->rho[u];
3292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat ds = span->texStep[u][0];
3302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat dt = span->texStep[u][1];
3312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat dr = span->texStep[u][2];
3322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat dq = span->texStep[u][3];
3332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
3342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
3352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
3362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
3372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
338c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               if (dq == 0.0) {
339c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  /* Ortho projection or polygon's parallel to window X axis */
3402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
341c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  const GLfloat lambda = HALF_LOG2(rho * invQ * invQ);
342c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
343c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][0] = s * invQ;
344c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][1] = t * invQ;
345c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][2] = r * invQ;
346c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->lambda[u][i] = lambda;
347c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     s += ds;
348c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     t += dt;
349c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     r += dr;
350c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
351c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               }
352c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               else {
353c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
354c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
355c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][0] = s * invQ;
356c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][1] = t * invQ;
357c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][2] = r * invQ;
358c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->lambda[u][i] = HALF_LOG2(rho * invQ * invQ);
359c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     s += ds;
360c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     t += dt;
361c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     r += dr;
362c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     q += dq;
363c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
3642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
3652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
3662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
3672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask |= SPAN_LAMBDA;
3682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      else {
3702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* multitexture, no lambda */
3712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint u;
3722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
3732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            if (ctx->Texture.Unit[u]._ReallyEnabled) {
3742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat ds = span->texStep[u][0];
3752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat dt = span->texStep[u][1];
3762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat dr = span->texStep[u][2];
3772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               const GLfloat dq = span->texStep[u][3];
3782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
3792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
3802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
3812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
3822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
383c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               if (dq == 0.0) {
384c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  /* Ortho projection or polygon's parallel to window X axis */
3852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
386c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
387c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][0] = s * invQ;
388c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][1] = t * invQ;
389c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][2] = r * invQ;
390c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     s += ds;
391c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     t += dt;
392c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     r += dr;
393c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
394c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               }
395c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               else {
396c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
397c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
398c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][0] = s * invQ;
399c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][1] = t * invQ;
400c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     span->texcoords[u][i][2] = r * invQ;
401c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     s += ds;
402c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     t += dt;
403c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     r += dr;
404c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     q += dq;
405c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
4062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
4072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
4082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
4092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
4122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      if (span->interpMask & SPAN_LAMBDA) {
4132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* just texture unit 0, with lambda */
414c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         const GLfloat rho = span->rho[0];
4152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat ds = span->texStep[0][0];
4162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat dt = span->texStep[0][1];
4172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat dr = span->texStep[0][2];
4182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat dq = span->texStep[0][3];
4192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
4202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
4212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
4222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
4232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
424c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         if (dq == 0.0) {
425c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            /* Ortho projection or polygon's parallel to window X axis */
4262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
427c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            const GLfloat lambda = HALF_LOG2(rho * invQ * invQ);
428c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
429c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][0] = s * invQ;
430c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][1] = t * invQ;
431c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][2] = r * invQ;
432c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->lambda[0][i] = lambda;
433c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               s += ds;
434c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               t += dt;
435c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               r += dr;
436c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
437c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         }
438c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         else {
439c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
440c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
441c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][0] = s * invQ;
442c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][1] = t * invQ;
443c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][2] = r * invQ;
444c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->lambda[0][i] = HALF_LOG2(rho * invQ * invQ);
445c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               s += ds;
446c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               t += dt;
447c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               r += dr;
448c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               q += dq;
449c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
4502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
4512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask |= SPAN_LAMBDA;
4522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      else {
454733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* just texture 0, without lambda */
4552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat ds = span->texStep[0][0];
4562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat dt = span->texStep[0][1];
4572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat dr = span->texStep[0][2];
4582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         const GLfloat dq = span->texStep[0][3];
4592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
4602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
4612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
4622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
4632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
464c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         if (dq == 0.0) {
465c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            /* Ortho projection or polygon's parallel to window X axis */
4662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
467c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
468c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][0] = s * invQ;
469c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][1] = t * invQ;
470c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][2] = r * invQ;
471c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               s += ds;
472c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               t += dt;
473c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               r += dr;
474c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
475c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         }
476c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         else {
477c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
478c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
479c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][0] = s * invQ;
480c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][1] = t * invQ;
481c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               span->texcoords[0][i][2] = r * invQ;
482c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               s += ds;
483c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               t += dt;
484c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               r += dr;
485c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               q += dq;
486c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
4872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
4882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
49010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
491e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
492e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
49379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
494e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
495e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
4965071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
497733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulstipple_polygon_span( GLcontext *ctx, struct sw_span *span )
49810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
49910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint highbit = 0x80000000;
500733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLuint stipple = ctx->PolygonStipple[span->y % 32];
501733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   GLuint i, m;
502733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
503733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
504733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->arrayMask & SPAN_XY) == 0);
50510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
50610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   m = highbit >> (GLuint) (span->x % 32);
50710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
50810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (i = 0; i < span->end; i++) {
50910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if ((m & stipple) == 0) {
51010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul	 span->mask[i] = 0;
51110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
51210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      m = m >> 1;
51310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (m == 0) {
51410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         m = highbit;
51510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
51610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
5172ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
51810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
51910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
520e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
52179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
522733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
523733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
524733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
525733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
52610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
52710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
52810f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic GLuint
529733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulclip_span( GLcontext *ctx, struct sw_span *span )
53010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
531733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
532733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
533733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
534733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
535733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
536733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
537733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
538733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint *x = span->xArray;
539733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint *y = span->yArray;
540733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
541733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLubyte *mask = span->mask;
542733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
543b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
544b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
545b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
546b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
547b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
548b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
549b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
550b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
551b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
552b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
553b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
554b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
555b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
55610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
557733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
55810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
559733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
560733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
561733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
562733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
563733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
564733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
565733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
566733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
567733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
568733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
569733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
57010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
571733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
572733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
573733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
574733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
575733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         BZERO(span->mask, (xmin - x) * sizeof(GLubyte));
57610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
577733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
578733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
579733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
580733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
581733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
58210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
58310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
584733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
585733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
58610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
58710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
58810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
589e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
59079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
591e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Draw to more than one color buffer (or none).
592e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
5935071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
594733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_index_span( GLcontext *ctx, struct sw_span *span )
595e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
596709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
597e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   GLuint bufferBit;
598e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
599e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* loop over four possible dest color buffers */
600e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
601e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (bufferBit & ctx->Color.DrawDestMask) {
602e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         GLuint indexTmp[MAX_WIDTH];
603733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(span->end < MAX_WIDTH);
604e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
605e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (bufferBit == FRONT_LEFT_BIT)
606e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
607e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         else if (bufferBit == FRONT_RIGHT_BIT)
608e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
609e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         else if (bufferBit == BACK_LEFT_BIT)
610e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
611e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         else
612e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
613e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
614e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* make copy of incoming indexes */
615733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         MEMCPY( indexTmp, span->color.index, span->end * sizeof(GLuint) );
616733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
617e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (ctx->Color.IndexLogicOpEnabled) {
618733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_logicop_ci_span(ctx, span, indexTmp);
619e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
620733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
6217956292a765910077f50352d7cd0174e1e66d26cBrian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
622733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_mask_index_span(ctx, span, indexTmp);
623733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
624733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
625733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (span->arrayMask & SPAN_XY) {
626733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* array of pixel coords */
627733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
628733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->xArray, span->yArray,
629733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              indexTmp, span->mask);
630733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
631733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
632733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* horizontal run of pixels */
633733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
634733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            indexTmp, span->mask);
635e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
636e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
637e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
638e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
639e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* restore default dest buffer */
640e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer);
641e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
642e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
643e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
64479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
64510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul * Draw to more than one RGBA color buffer (or none).
646f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * All fragment operations, up to (but not) blending/logicop should
647f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * have been done first.
64810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
64910f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic void
650733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_rgba_span( GLcontext *ctx, struct sw_span *span )
65110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
65210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
65310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   GLuint bufferBit;
65410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
65510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
656733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(colorMask != 0x0);
657733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
65810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   if (ctx->Color.DrawBuffer == GL_NONE)
65910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
66010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
66110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* loop over four possible dest color buffers */
66210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (bufferBit = 1; bufferBit <= 8; bufferBit = bufferBit << 1) {
66310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (bufferBit & ctx->Color.DrawDestMask) {
66410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         GLchan rgbaTmp[MAX_WIDTH][4];
665733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(span->end < MAX_WIDTH);
66610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
66710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         if (bufferBit == FRONT_LEFT_BIT) {
66810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_LEFT);
66910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontLeftAlpha;
67010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
67110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else if (bufferBit == FRONT_RIGHT_BIT) {
67210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_FRONT_RIGHT);
67310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->FrontRightAlpha;
67410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
67510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else if (bufferBit == BACK_LEFT_BIT) {
67610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_LEFT);
67710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackLeftAlpha;
67810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
67910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else {
68010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            (void) (*ctx->Driver.SetDrawBuffer)( ctx, GL_BACK_RIGHT);
68110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            ctx->DrawBuffer->Alpha = ctx->DrawBuffer->BackRightAlpha;
68210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
68310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
68410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         /* make copy of incoming colors */
685733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         MEMCPY( rgbaTmp, span->color.rgba, 4 * span->end * sizeof(GLchan) );
68610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
68710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         if (ctx->Color.ColorLogicOpEnabled) {
688733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_logicop_rgba_span(ctx, span, rgbaTmp);
68910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
69010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else if (ctx->Color.BlendEnabled) {
691733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_blend_span(ctx, span, rgbaTmp);
69210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
693733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
694733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (colorMask != 0xffffffff) {
695733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_mask_rgba_span(ctx, span, rgbaTmp);
69610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
69710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
698733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (span->arrayMask & SPAN_XY) {
699733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* array of pixel coords */
700733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
701733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->xArray, span->yArray,
702733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              (const GLchan (*)[4]) rgbaTmp,
703733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->mask);
704733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
705733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_pixels(ctx, span->end,
706733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                        span->xArray, span->yArray,
707733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                        (const GLchan (*)[4]) rgbaTmp,
708733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                        span->mask);
709733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
710733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
711733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
712733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* horizontal run of pixels */
713733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
714733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            (const GLchan (*)[4]) rgbaTmp,
715733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            span->mask);
716733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (swrast->_RasterMask & ALPHABUF_BIT) {
717733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
718733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                      (const GLchan (*)[4]) rgbaTmp,
719733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                      span->mask);
720733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
72110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
72210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
72310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
72410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
72510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* restore default dest buffer */
72610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   (void) (*ctx->Driver.SetDrawBuffer)( ctx, ctx->Color.DriverDrawBuffer );
72710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
72810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
72910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
730e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
73179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
7327956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span.
7337956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
7347956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
73510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
73610f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
7372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_write_index_span( GLcontext *ctx, struct sw_span *span,
7382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul			GLenum primitive)
73910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
74010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
7417956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint origInterpMask = span->interpMask;
7422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint origArrayMask = span->arrayMask;
74310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
744733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
745733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
7467956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
7477956292a765910077f50352d7cd0174e1e66d26cBrian Paul
748733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
749733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
750733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
751733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
752733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
753733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      MEMSET(span->mask, 1, span->end);
754733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
75510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
75610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
757733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
758733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
759b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul       || (primitive == GL_POINT) || (primitive == GL_LINE)) {
760733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
76186ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
762e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
763e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
764e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
765b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
766b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
767b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      int i;
768b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
769b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         if (span->mask[i]) {
770b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
771b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
772b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
773b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
774b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
775b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
776b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
777b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
778b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
779e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
780733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
78110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
782e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
783e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
7847956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Depth test and stencil */
7857956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
7867956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (span->interpMask & SPAN_Z)
787711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
78810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
7897956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
79079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
7917956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
7927956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
7937956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
7942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
7957956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
7967956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
79779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul         if (!_mesa_depth_test_span(ctx, span)) {
7987956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
7997956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
8007956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
8012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
80210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
80310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
80410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* if we get here, something passed the depth test */
80510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   ctx->OcclusionResult = GL_TRUE;
80610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8077956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
8087956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
80910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
8102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
81110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
81210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
81310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8147956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
8157956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (span->interpMask & SPAN_INDEX) {
8162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      interpolate_indexes(ctx, span);
8177956292a765910077f50352d7cd0174e1e66d26cBrian Paul      /* clear the bit - this allows the WriteMonoCISpan optimization below */
8187956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->interpMask &= ~SPAN_INDEX;
8197956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
82010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8217956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
8222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Fog.Enabled) {
823711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_ci_span(ctx, span);
824e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
825e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
8262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
8272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
8282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
8297956292a765910077f50352d7cd0174e1e66d26cBrian Paul      GLuint *index = span->color.index;
83010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
8312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         ASSERT(span->coverage[i] < 16);
8322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) (span->coverage[i]));
8335071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
8342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
8355071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
8362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
8372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* draw to zero or two or more buffers */
838733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_index_span(ctx, span);
839e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
840e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
8412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* normal situation: draw to exactly one buffer */
8422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      if (ctx->Color.IndexLogicOpEnabled) {
843733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_logicop_ci_span(ctx, span, span->color.index);
84410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
8452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8467956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Color.IndexMask != 0xffffffff) {
847733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_mask_index_span(ctx, span, span->color.index);
848e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
8492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* write pixels */
851733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
852733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
853733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
854733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color index */
855733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
856733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                span->xArray, span->yArray,
857733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                FixedToInt(span->index),
858733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                span->mask);
859733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
860733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
861733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->xArray,
862733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->yArray, span->color.index,
863733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->mask );
864733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
8657956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
8667956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
867733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
868733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
869733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color index */
870733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
871733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              FixedToInt(span->index),
872733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              span->mask);
873733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
874733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
875733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
876733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            span->color.index, span->mask);
877733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
8787956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
879e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
8802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8817956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
8822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
883e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
884e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
885e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
88679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
8877956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span.
8887956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
8897956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
8905d2621928823a06006c1586efe78fe8bf65a7e1fBrian Paul */
8915071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
89210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul_mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span,
8932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul		       GLenum primitive)
894e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
895cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8967956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
8977956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint origInterpMask = span->interpMask;
8982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint origArrayMask = span->arrayMask;
8997956292a765910077f50352d7cd0174e1e66d26cBrian Paul   GLboolean monoColor;
9007956292a765910077f50352d7cd0174e1e66d26cBrian Paul
901733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
9027956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
903ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
904bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#ifdef DEBUG
905733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (ctx->Fog.Enabled)
906733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
907bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul   if (ctx->Depth.Test)
908bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul      ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
909bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#endif
910733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
911733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /*
912bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul   printf("%s()  interp 0x%x  array 0x%x  p=0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask, primitive);
913733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   */
914e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
915733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
916733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
917733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
918733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
919733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
920733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      MEMSET(span->mask, 1, span->end);
921733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
922733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
923e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9247956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Determine if we have mono-chromatic colors */
9257956292a765910077f50352d7cd0174e1e66d26cBrian Paul   monoColor = (span->interpMask & SPAN_RGBA) &&
9267956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->redStep == 0 && span->greenStep == 0 &&
9277956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->blueStep == 0 && span->alphaStep == 0;
9287956292a765910077f50352d7cd0174e1e66d26cBrian Paul
929733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
930733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
931b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul       || (primitive == GL_POINT) || (primitive == GL_LINE)) {
932733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
93386ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
934e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
935e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
936e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
937b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
938b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
939b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      int i;
940b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
941b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         if (span->mask[i]) {
942b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
943b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
944b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
945b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
946b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
947b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
948b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
949b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
950b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
951e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
9527956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
9537956292a765910077f50352d7cd0174e1e66d26cBrian Paul      stipple_polygon_span(ctx, span);
95410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
95510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
956e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Do the alpha test */
957e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (ctx->Color.AlphaEnabled) {
958ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      if (!_mesa_alpha_test(ctx, span)) {
9597956292a765910077f50352d7cd0174e1e66d26cBrian Paul         span->interpMask = origInterpMask;
9602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask = origArrayMask;
961e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 return;
962e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
96310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
96410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
965f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
966f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
967f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
968711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
969f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
970f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (ctx->Stencil.Enabled) {
971f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
9727956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->interpMask = origInterpMask;
973f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
974f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            return;
97510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
97610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
97710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      else {
978f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
979f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
980f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         /* regular depth testing */
981f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_depth_test_span(ctx, span)) {
9827956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->interpMask = origInterpMask;
983f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
984f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            return;
98510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
98610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
987e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
988e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
989e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* if we get here, something passed the depth test */
990e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   ctx->OcclusionResult = GL_TRUE;
991e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9927956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* can't abort span-writing until after occlusion testing */
9937956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (colorMask == 0x0) {
9947956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->interpMask = origInterpMask;
9957956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->arrayMask = origArrayMask;
9967956292a765910077f50352d7cd0174e1e66d26cBrian Paul      return;
9977956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
9987956292a765910077f50352d7cd0174e1e66d26cBrian Paul
999ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /* Now we may need to interpolate the colors */
1000ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
1001ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      interpolate_colors(ctx, span);
1002ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      /* clear the bit - this allows the WriteMonoCISpan optimization below */
1003ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      span->interpMask &= ~SPAN_RGBA;
1004ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   }
1005ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
10066e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
1007b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul   if (ctx->Fog.Enabled) {
1008711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_rgba_span(ctx, span);
10097956292a765910077f50352d7cd0174e1e66d26cBrian Paul      monoColor = GL_FALSE;
1010b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul   }
1011b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul
10125071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul   /* Antialias coverage application */
10132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
10147956292a765910077f50352d7cd0174e1e66d26cBrian Paul      GLchan (*rgba)[4] = span->color.rgba;
10155071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      GLuint i;
101610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
101710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
10185071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
10197956292a765910077f50352d7cd0174e1e66d26cBrian Paul      monoColor = GL_FALSE;
10205071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul   }
10215071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
1022cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1023733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_rgba_span(ctx, span);
1024e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1025e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1026e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* normal: write to exactly one buffer */
1027e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (ctx->Color.ColorLogicOpEnabled) {
1028733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_logicop_rgba_span(ctx, span, span->color.rgba);
10297956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1030e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1031e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else if (ctx->Color.BlendEnabled) {
1032733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_blend_span(ctx, span, span->color.rgba);
10337956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1034e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
103595e2c72fd52d87163eb543555345f115f050f3aaBrian Paul
1036e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* Color component masking */
10377956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (colorMask != 0xffffffff) {
1038733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_mask_rgba_span(ctx, span, span->color.rgba);
10397956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1040e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1041e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1042e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* write pixels */
1043733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
1044733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
1045733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* XXX test for mono color */
1046733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->xArray,
1047733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul             span->yArray, (const GLchan (*)[4]) span->color.rgba, span->mask);
1048733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1049733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_pixels(ctx, span->end,
1050733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->xArray, span->yArray,
1051733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     (const GLchan (*)[4]) span->color.rgba,
1052733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->mask);
1053733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1054e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1055e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1056733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
1057733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (monoColor) {
1058733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color */
1059733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            GLchan color[4];
1060733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[RCOMP] = FixedToChan(span->red);
1061733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[GCOMP] = FixedToChan(span->green);
1062733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[BCOMP] = FixedToChan(span->blue);
1063733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[ACOMP] = FixedToChan(span->alpha);
1064733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
1065733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                span->y, color, span->mask);
1066733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* XXX software alpha buffer writes! */
1067733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1068733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
1069733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* each pixel is a different color */
1070733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
10717956292a765910077f50352d7cd0174e1e66d26cBrian Paul                      (const GLchan (*)[4]) span->color.rgba,
1072733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                      span->writeAll ? ((const GLubyte *) NULL) : span->mask);
1073733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (swrast->_RasterMask & ALPHABUF_BIT) {
1074733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
10757956292a765910077f50352d7cd0174e1e66d26cBrian Paul                      (const GLchan (*)[4]) span->color.rgba,
1076733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                      span->writeAll ? ((const GLubyte *) NULL) : span->mask);
1077733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
1078733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1079e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1080e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1081e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
10827956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
10837956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->arrayMask = origArrayMask;
10847956292a765910077f50352d7cd0174e1e66d26cBrian Paul}
1085e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1086e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
108779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1088e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color.  This is used only when
1089f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1090e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
10915071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
1092f1e236987829393c81dc86ea19cb49eefe190317Brian Pauladd_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1093e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1094e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   GLuint i;
1095f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   for (i = 0; i < n; i++) {
10964fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#if CHAN_TYPE == GL_FLOAT
10974fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul      /* no clamping */
1098f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][RCOMP] += specular[i][RCOMP];
1099f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][GCOMP] += specular[i][GCOMP];
1100f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][BCOMP] += specular[i][BCOMP];
11014fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#else
1102f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1103f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1104f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1105e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1106e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1107e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
11084fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#endif
1109e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1110e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1111e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1112e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
111379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1114f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
11157956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
11167956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
111778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
111878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
111978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul_mesa_write_texture_span( GLcontext *ctx, struct sw_span *span,
1120f1e236987829393c81dc86ea19cb49eefe190317Brian Paul                          GLenum primitive )
112178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
112278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
112378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1124f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   const GLuint origArrayMask = span->arrayMask;
1125f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1126733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
11277956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
1128f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(ctx->Texture._ReallyEnabled);
112978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1130ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /*
1131ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1132ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   */
1133ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1134733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1135733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1136733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1137733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1138733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
1139733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      MEMSET(span->mask, 1, span->end);
1140733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
114178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
114278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1143733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
1144733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (primitive == GL_BITMAP)
1145b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul       || (primitive == GL_POINT) || (primitive == GL_LINE)) {
1146733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1147733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
114878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
114978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
115078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1151b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1152b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1153b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      int i;
1154b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
1155b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         if (span->mask[i]) {
1156b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] >= ctx->DrawBuffer->_Xmin);
1157b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->xArray[i] < ctx->DrawBuffer->_Xmax);
1158b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] >= ctx->DrawBuffer->_Ymin);
1159b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            assert(span->yArray[i] < ctx->DrawBuffer->_Ymax);
1160b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1161b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1162b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1163b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1164b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
116578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1166733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (ctx->Polygon.StippleFlag && primitive == GL_POLYGON) {
1167733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
116878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
116978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1170f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Need texture coordinates now */
1171f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if ((span->interpMask & SPAN_TEXTURE)
1172f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       && (span->arrayMask & SPAN_TEXTURE) == 0)
1173f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      interpolate_texcoords(ctx, span);
117478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
117578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Texture with alpha test */
117678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   if (ctx->Color.AlphaEnabled) {
1177f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1178f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1179f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1180f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
1181f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
118278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Texturing without alpha is done after depth-testing which
1183f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       * gives a potential speed-up.
1184f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       */
1185f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      _swrast_multitexture_fragments( ctx, span );
118678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
118778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Do the alpha test */
1188ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      if (!_mesa_alpha_test(ctx, span)) {
1189f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         span->arrayMask = origArrayMask;
1190ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul	 return;
119178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
119278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
119378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1194f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1195f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1196f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
1197711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
119878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
119971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      if (ctx->Stencil.Enabled) {
1200f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
1201f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
120210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1203f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
120471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1205f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      else {
1206f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1207f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
120810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         /* regular depth testing */
1209f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_depth_test_span(ctx, span)) {
1210f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
121110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1212f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
121371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
121471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
121571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1216f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* if we get here, some fragments passed the depth test */
121771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   ctx->OcclusionResult = GL_TRUE;
121871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1219f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1220f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1221f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1222f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1223f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      span->arrayMask = origArrayMask;
1224f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      return;
122571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
122671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1227f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Texture without alpha test */
1228f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (!ctx->Color.AlphaEnabled) {
122971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1230f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1231f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1232f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
123371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1234f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      _swrast_multitexture_fragments( ctx, span );
123571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
123671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1237f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
12382ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
1239f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Add base and specular colors */
1240f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Fog.ColorSumEnabled ||
1241f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       (ctx->Light.Enabled &&
1242f1e236987829393c81dc86ea19cb49eefe190317Brian Paul        ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1243f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_SPEC) {
1244f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_specular(ctx, span);
124571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1246f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      ASSERT(span->arrayMask & SPAN_SPEC);
1247f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      add_colors( span->end, span->color.rgba, span->specArray );
124871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
124971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
12506e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
125171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   if (ctx->Fog.Enabled) {
1252711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_rgba_span(ctx, span);
125371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1254f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
125571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
12562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1257f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLchan (*rgba)[4] = span->color.rgba;
125871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      GLuint i;
125910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
126010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * span->coverage[i]);
126171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
126271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
126371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
126471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1265733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_rgba_span(ctx, span);
126671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
126771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   else {
126871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      /* normal: write to exactly one buffer */
126971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      if (ctx->Color.ColorLogicOpEnabled) {
1270733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_logicop_rgba_span(ctx, span, span->color.rgba);
127171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
127295e2c72fd52d87163eb543555345f115f050f3aaBrian Paul      else if (ctx->Color.BlendEnabled) {
1273733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_blend_span(ctx, span, span->color.rgba);
127471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
127571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1276f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (colorMask != 0xffffffff) {
1277733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_mask_rgba_span(ctx, span, span->color.rgba);
127871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
127971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1280733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
1281733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
1282733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
1283733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->xArray,
1284733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul             span->yArray, (const GLchan (*)[4]) span->color.rgba, span->mask);
1285733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1286733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_pixels(ctx, span->end,
1287733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->xArray, span->yArray,
1288733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     (const GLchan (*)[4]) span->color.rgba,
1289733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                     span->mask);
1290733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1291733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
1292733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      else {
1293733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
1294733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
1295f1e236987829393c81dc86ea19cb49eefe190317Brian Paul                                       (const GLchan (*)[4]) span->color.rgba,
1296733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                       span->writeAll ? NULL : span->mask);
1297733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (swrast->_RasterMask & ALPHABUF_BIT) {
1298733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
1299733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                   (const GLchan (*)[4]) span->color.rgba,
1300733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                   span->writeAll ? NULL : span->mask);
1301733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
130271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
130371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
130471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1305f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
130610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
130710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1308e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1309e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
131079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1311e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
1312e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1313e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
13145071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
13155071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul_mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
13165071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul                      GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1317e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1318709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1319e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (y < 0 || y >= buffer->Height
1320e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell       || x + (GLint) n < 0 || x >= buffer->Width) {
1321e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1322e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* XXX maybe leave undefined? */
1323e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      BZERO(rgba, 4 * n * sizeof(GLchan));
1324e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1325e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1326e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1327e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
1328e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* left edge clippping */
1329e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1330e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1331e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1332e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1333e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1334e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1335e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length > buffer->Width) {
1336e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            length = buffer->Width;
1337e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1338e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1339e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else if ((GLint) (x + n) > buffer->Width) {
1340e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1341e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1342e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = buffer->Width - x;
1343e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1344e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1345e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1346e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1347e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1348e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1349e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1350e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1351e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1352e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1353e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1354709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell      (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1355e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (buffer->UseSoftwareAlphaBuffers) {
1356733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1357e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1358e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1359e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1360e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1361e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
136279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1363e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read CI pixels from frame buffer.  Clipping will be done to prevent
1364e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1365e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
13665071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
13675071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul_mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
13685071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul                       GLuint n, GLint x, GLint y, GLuint indx[] )
1369e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1370709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1371e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (y < 0 || y >= buffer->Height
1372e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell       || x + (GLint) n < 0 || x >= buffer->Width) {
1373e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1374e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      BZERO(indx, n * sizeof(GLuint));
1375e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1376e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1377e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1378e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
1379e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* left edge clippping */
1380e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1381e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1382e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1383e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1384e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1385e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1386e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length > buffer->Width) {
1387e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            length = buffer->Width;
1388e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1389e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1390e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else if ((GLint) (x + n) > buffer->Width) {
1391e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1392e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1393e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = buffer->Width - x;
1394e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1395e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1396e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1397e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1398e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1399e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1400e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1401e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1402e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1403e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1404e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1405709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell      (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1406e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1407e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1408