s_span.c revision bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4d
1e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library
36e4f594a02fc384b17d5732be652d7d28618aec2Brian Paul * Version:  6.5
422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
5a66393120411071b3f3ccce8583ab961a2935959Michal Krol * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
7e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
8e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * copy of this software and associated documentation files (the "Software"),
9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to deal in the Software without restriction, including without limitation
10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Software is furnished to do so, subject to the following conditions:
1322144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
14e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice shall be included
15e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in all copies or substantial portions of the Software.
1622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
17e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
2679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
27bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul * \file swrast/s_span.c
2879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \brief Span processing functions used by all rasterization functions.
2979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * This is where all the per-fragment tests are performed
3079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \author Brian Paul
31e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
32e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "glheader.h"
34e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "colormac.h"
3571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul#include "context.h"
36e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "macros.h"
373c63452e64df7e10aa073c6c3b9492b1d7dabbb8Brian Paul#include "imports.h"
38e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
397f752fed993e5e9423abac200dd59141edbada56Dave Airlie#include "s_atifragshader.h"
40bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol#include "s_alpha.h"
41a66393120411071b3f3ccce8583ab961a2935959Michal Krol#include "s_arbshader.h"
42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
43cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
44e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
48610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul#include "s_nvfragprog.h"
49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
5155187ea63e980b32c7a701855571332f4357d634Brian Paul#include "s_texcombine.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
5945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_z( GLcontext *ctx, struct sw_span *span )
602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
61e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
6231e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16)
63e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else
65e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      span->z = (GLint) (ctx->Current.RasterPos[2] * depthMax + 0.5F);
662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->zStep = 0;
672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_Z;
682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
7179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's fog interpolation values to the RasterPos fog.
732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
7645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_fog( GLcontext *ctx, struct sw_span *span )
772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
7845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul   span->fog = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
7954e92e8420a028f07b0971ee8aa93be9b4214579Brian Paul   span->fogStep = span->dfogdx = span->dfogdy = 0.0F;
802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_FOG;
812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
85a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Init span's rgba or index interpolation values to the RasterPos color.
862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
8945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_color( GLcontext *ctx, struct sw_span *span )
902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.rgbMode) {
922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan r, g, b, a;
932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red = r;
992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = g;
1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue = b;
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = a;
1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red   = IntToFixed(r);
1042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = IntToFixed(g);
1052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue  = IntToFixed(b);
1062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = IntToFixed(a);
1072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->redStep = 0;
1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->greenStep = 0;
1102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blueStep = 0;
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alphaStep = 0;
1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_RGBA;
1132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1150f3cd3f894612d156de454178effa4c732f96da7Brian Paul      span->index = FloatToFixed(ctx->Current.RasterIndex);
1162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->indexStep = 0;
1172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_INDEX;
1182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1224753d60dd070bb08d0116076bcc08025c86ce857Brian Paul/**
1234753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Init span's texcoord interpolation values to the RasterPos texcoords.
1244753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Used during setup for glDraw/CopyPixels.
1254753d60dd070bb08d0116076bcc08025c86ce857Brian Paul */
1264753d60dd070bb08d0116076bcc08025c86ce857Brian Paulvoid
12745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span )
1284753d60dd070bb08d0116076bcc08025c86ce857Brian Paul{
1294753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   GLuint i;
1304753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
131e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      const GLfloat *tc = ctx->Current.RasterTexCoords[i];
13247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled) {
133a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         COPY_4V(span->tex[i], tc);
134a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      }
135a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      else if (tc[3] > 0.0F) {
136e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         /* use (s/q, t/q, r/q, 1) */
137e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][0] = tc[0] / tc[3];
138e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][1] = tc[1] / tc[3];
139e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][2] = tc[2] / tc[3];
140e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][3] = 1.0;
141e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
142e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      else {
143e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F);
144e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
1455f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul      ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
1465f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul      ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
1474753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   }
1484753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   span->interpMask |= SPAN_TEXTURE;
1494753d60dd070bb08d0116076bcc08025c86ce857Brian Paul}
1504753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
1514753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
1522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.rgba array from the interpolation values */
1532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_colors(GLcontext *ctx, struct sw_span *span)
1552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
15777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLchan (*rgba)[4] = span->array->rgba;
1582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
159a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
161b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_RGBA)  &&
162b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_RGBA));
1632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
1652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
1662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan color[4];
1676a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      color[RCOMP] = FixedToChan(span->red);
1686a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      color[GCOMP] = FixedToChan(span->green);
1696a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      color[BCOMP] = FixedToChan(span->blue);
1706a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      color[ACOMP] = FixedToChan(span->alpha);
1712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
17277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         COPY_CHAN4(span->array->rgba[i], color);
1732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
1776a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul#if CHAN_TYPE == GL_FLOAT
1786a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfloat r = span->red;
1796a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfloat g = span->green;
1806a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfloat b = span->blue;
1816a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfloat a = span->alpha;
1826a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLfloat dr = span->redStep;
1836a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLfloat dg = span->greenStep;
1846a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLfloat db = span->blueStep;
1856a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLfloat da = span->alphaStep;
1866a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul#else
1876a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfixed r = span->red;
1886a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfixed g = span->green;
1896a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfixed b = span->blue;
1906a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      GLfixed a = span->alpha;
1916a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLint dr = span->redStep;
1926a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLint dg = span->greenStep;
1936a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLint db = span->blueStep;
1946a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul      const GLint da = span->alphaStep;
1956a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul#endif
1962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][RCOMP] = FixedToChan(r);
1982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][GCOMP] = FixedToChan(g);
1992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][BCOMP] = FixedToChan(b);
2002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][ACOMP] = FixedToChan(a);
2012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += dr;
2022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += dg;
2032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += db;
2042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         a += da;
2052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_RGBA;
2082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
2122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
2132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_indexes(GLcontext *ctx, struct sw_span *span)
2142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
2162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
2172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
21877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLuint *indexes = span->array->index;
2192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
220a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
221b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_INDEX)  &&
222b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_INDEX));
2232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
2252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
2262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
2272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
2292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
2332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
2352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
2362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
239e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   span->interpMask &= ~SPAN_INDEX;
2402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
24377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul/* Fill in the span.->array->spec array from the interpolation values */
2442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
2452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_specular(GLcontext *ctx, struct sw_span *span)
2462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
247a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
2482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
2492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
2502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan r = FixedToChan(span->specRed);
2512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan g = FixedToChan(span->specGreen);
2522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan b = FixedToChan(span->specBlue);
2532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
25577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][RCOMP] = r;
25677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][GCOMP] = g;
25777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][BCOMP] = b;
2582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
2622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
2632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat r = span->specRed;
2642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat g = span->specGreen;
2652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat b = span->specBlue;
2662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
2672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed r = span->specRed;
2682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed g = span->specGreen;
2692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed b = span->specBlue;
2702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
2712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
27377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][RCOMP] = FixedToChan(r);
27477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][GCOMP] = FixedToChan(g);
27577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][BCOMP] = FixedToChan(b);
2762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += span->specRedStep;
2772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += span->specGreenStep;
2782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += span->specBlueStep;
2792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_SPEC;
2822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
285d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul/* Fill in the span.array.fog values from the interpolation values */
286d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paulstatic void
287d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paulinterpolate_fog(const GLcontext *ctx, struct sw_span *span)
288d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul{
289d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat *fog = span->array->fog;
290d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLfloat fogStep = span->fogStep;
291d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat fogCoord = span->fog;
292d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLuint haveW = (span->interpMask & SPAN_W);
293d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLfloat wStep = haveW ? span->dwdx : 0.0F;
294d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat w = haveW ? span->w : 1.0F;
295d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLuint i;
296d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   for (i = 0; i < span->end; i++) {
297d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      fog[i] = fogCoord / w;
298d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      fogCoord += fogStep;
299d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      w += wStep;
300d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   }
301d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   span->arrayMask |= SPAN_FOG;
302d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul}
303d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
304d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
3052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */
306711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
30745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
3082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
3102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
3112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
312b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_Z)  &&
313b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_Z));
3142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
31531e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16) {
3162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
3173e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
318ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      for (i = 0; i < n; i++) {
31977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = FixedToInt(zval);
3202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
3212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
3232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
3242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
3257265556b9aa0367e9b5031e7cb15ed2a5d73866dBrian Paul      GLuint zval = span->z;
3263e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
3272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
32877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = zval;
3292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
3302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
33232340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   span->interpMask &= ~SPAN_Z;
3332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
3342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
3352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
337c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
33831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
339c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
340c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
34131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
34231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
34331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
34431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
345c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
34631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
34731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
34831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
34931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
350f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
351f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
35231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
35331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
35431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
355c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
356c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
357c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
35831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
35931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/*
36031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This is a faster approximation
361c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
362350353adcd75f94fda63c787c86961716114e0bfBrian PaulGLfloat
36345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
364350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
365350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
366c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
36731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
36831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
36931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
37031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
37131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
37231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
37331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
37431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
37531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
37631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
37731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
37831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
37931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
38031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
381c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
382c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
383d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
384d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul/**
385c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Fill in the span.texcoords array from the interpolation values.
386d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * Note: in the places where we divide by Q (or mult by invQ) we're
387d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * really doing two things: perspective correction and texcoord
388d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * projection.  Remember, for texcoord (s,t,r,q) we need to index
389d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * texels with (s/q, t/q, r/q).
390d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * If we're using a fragment program, we never do the division
391d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * for texcoord projection.  That's done by the TXP instruction
392d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * or user-written code.
393c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
3942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_texcoords(GLcontext *ctx, struct sw_span *span)
3962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_TEXTURE);
398b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(!(span->arrayMask & SPAN_TEXTURE));
3992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
40036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul   if (ctx->Texture._EnabledCoordUnits > 1) {
40131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* multitexture */
40231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      GLuint u;
403b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
40431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
40536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
40631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
40736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            GLfloat texW, texH;
40836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            GLboolean needLambda;
40936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            if (obj) {
41018fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell               const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
41136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               needLambda = (obj->MinFilter != obj->MagFilter)
41247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell                  || ctx->FragmentProgram._Active;
41336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texW = img->WidthScale;
41436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texH = img->HeightScale;
41536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            }
41636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            else {
417d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               /* using a fragment program */
41836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texW = 1.0;
41936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texH = 1.0;
42036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               needLambda = GL_FALSE;
42136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            }
42231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            if (needLambda) {
42377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
42477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
42531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
42631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdy = span->texStepY[u][0];
42731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
42831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdy = span->texStepY[u][1];
42931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
43031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
43131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdy = span->texStepY[u][3];
4322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
4332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
4342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
4352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
4362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
437bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol               if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
438bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol                   ctx->ShaderObjects._FragmentShaderPresent) {
439d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  /* do perspective correction but don't divide s, t, r by q */
440d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  const GLfloat dwdx = span->dwdx;
441d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  GLfloat w = span->w;
442d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
443d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invW = 1.0F / w;
444d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invW;
445d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invW;
446d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invW;
447d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q * invW;
448d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
449d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        dqdx, dqdy, texW, texH,
450d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        s, t, q, invW);
451d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
452d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
453d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
454d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
455d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     w += dwdx;
456d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
457d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
458d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               }
459d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               else {
460d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
461d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
462d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invQ;
463d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invQ;
464d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invQ;
465d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q;
466d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
467d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        dqdx, dqdy, texW, texH,
468d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        s, t, q, invQ);
469d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
470d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
471d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
472d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
473d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
4742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
47531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               span->arrayMask |= SPAN_LAMBDA;
4762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
47731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
47877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
47977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
48031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
48131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
48231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
48331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
4842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
4852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
4862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
4872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
4882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
489bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol               if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
490bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol                   ctx->ShaderObjects._FragmentShaderPresent) {
491d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  /* do perspective correction but don't divide s, t, r by q */
492d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  const GLfloat dwdx = span->dwdx;
493d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  GLfloat w = span->w;
494d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
495d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invW = 1.0F / w;
496d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invW;
497d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invW;
498d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invW;
499d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q * invW;
500d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = 0.0;
501d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
502d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
503d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
504d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
505d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     w += dwdx;
506d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
507d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               }
508d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               else if (dqdx == 0.0F) {
509c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  /* Ortho projection or polygon's parallel to window X axis */
5102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
511c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
51277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
51377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
51477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
51536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul                     texcoord[i][3] = q;
51677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
51731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
51831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
51931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
520c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
521c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               }
522c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               else {
523c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
524c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
52577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
52677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
52777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
52836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul                     texcoord[i][3] = q;
52977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
53031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
53131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
53231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
53331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     q += dqdx;
534c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
5352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
53631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            } /* lambda */
53731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         } /* if */
53831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      } /* for */
5392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
5402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
54131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* single texture */
54231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
54336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      GLfloat texW, texH;
54436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      GLboolean needLambda;
54536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      if (obj) {
54618fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell         const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
54736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         needLambda = (obj->MinFilter != obj->MagFilter)
54847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell            || ctx->FragmentProgram._Active;
54936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texW = (GLfloat) img->WidthScale;
55036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texH = (GLfloat) img->HeightScale;
55136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      }
55236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      else {
55336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         needLambda = GL_FALSE;
55436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texW = texH = 1.0;
55536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      }
556b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
55731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      if (needLambda) {
5582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* just texture unit 0, with lambda */
55977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
56077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat *lambda = span->array->lambda[0];
56131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
56231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdy = span->texStepY[0][0];
56331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
56431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdy = span->texStepY[0][1];
56531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
56631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
56731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdy = span->texStepY[0][3];
5682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
5692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
5702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
5712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
5722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
573bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
574bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol             ctx->ShaderObjects._FragmentShaderPresent) {
575d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* do perspective correction but don't divide s, t, r by q */
576d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            const GLfloat dwdx = span->dwdx;
577d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            GLfloat w = span->w;
578d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
579d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invW = 1.0F / w;
580d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invW;
581d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invW;
582d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invW;
583d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q * invW;
584d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
585d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                  dqdx, dqdy, texW, texH,
586d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                  s, t, q, invW);
587d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
588d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
589d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
590d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
591d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               w += dwdx;
592d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
593d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
594d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else {
595d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* tex.c */
596d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
597d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
598d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
599d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                dqdx, dqdy, texW, texH,
600d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                s, t, q, invQ);
601d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invQ;
602d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invQ;
603d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invQ;
604d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q;
605d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
606d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
607d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
608d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
609d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
6102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
6112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask |= SPAN_LAMBDA;
6122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
6132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      else {
614733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* just texture 0, without lambda */
61577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
61631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
61731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
61831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
61931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
6202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
6212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
6222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
6232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
6242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
625bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         if (ctx->FragmentProgram._Active || ctx->ATIFragmentShader._Enabled ||
626bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol             ctx->ShaderObjects._FragmentShaderPresent) {
627d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* do perspective correction but don't divide s, t, r by q */
628d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            const GLfloat dwdx = span->dwdx;
629d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            GLfloat w = span->w;
630d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
631d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invW = 1.0F / w;
632d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invW;
633d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invW;
634d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invW;
635d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q * invW;
636d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
637d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
638d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
639d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
640d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               w += dwdx;
641d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
642d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
643d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else if (dqdx == 0.0F) {
644c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            /* Ortho projection or polygon's parallel to window X axis */
6452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
646c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
64777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
64877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
64977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
6502b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul               texcoord[i][3] = q;
65131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
65231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
65331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
654c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
655c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         }
656c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         else {
657c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
658c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
65977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
66077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
66177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
6622b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul               texcoord[i][3] = q;
66331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
66431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
66531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
66631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               q += dqdx;
667c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
6682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
6692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
6702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
67110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
672e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
673e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
67479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
675bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol * Fill in the span.varying array from the interpolation values.
676bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol */
677bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krolstatic void
678bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krolinterpolate_varying(GLcontext *ctx, struct sw_span *span)
679bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol{
680bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   GLuint i, j;
681bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
682bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(span->interpMask & SPAN_VARYING);
683bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(!(span->arrayMask & SPAN_VARYING));
684bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
685bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   span->arrayMask |= SPAN_VARYING;
686bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
687bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   for (i = 0; i < MAX_VARYING_VECTORS; i++) {
688bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      for (j = 0; j < VARYINGS_PER_VECTOR; j++) {
689bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         const GLfloat dvdx = span->varStepX[i][j];
690bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLfloat v = span->var[i][j];
691bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         const GLfloat dwdx = span->dwdx;
692bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLfloat w = span->w;
693bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLuint k;
694bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
695bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         for (k = 0; k < span->end; k++) {
696bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            GLfloat invW = 1.0f / w;
697bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            span->array->varying[k][i][j] = v * invW;
698bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            v += dvdx;
699bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            w += dwdx;
700bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         }
701bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      }
702bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   }
703bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol}
704bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
705bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
706bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol/**
707e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
708e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
7095071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
710733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulstipple_polygon_span( GLcontext *ctx, struct sw_span *span )
71110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
71210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint highbit = 0x80000000;
713733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLuint stipple = ctx->PolygonStipple[span->y % 32];
71477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLubyte *mask = span->array->mask;
715733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   GLuint i, m;
716733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
717733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
718733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->arrayMask & SPAN_XY) == 0);
71910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
72010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   m = highbit >> (GLuint) (span->x % 32);
72110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
72210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (i = 0; i < span->end; i++) {
72310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if ((m & stipple) == 0) {
72477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul	 mask[i] = 0;
72510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
72610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      m = m >> 1;
72710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (m == 0) {
72810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         m = highbit;
72910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
73010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
7312ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
73210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
73310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
734e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
73579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
736733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
737733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
738733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
739733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
74010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
74110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
74210f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic GLuint
743733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulclip_span( GLcontext *ctx, struct sw_span *span )
74410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
745733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
746733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
747733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
748733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
749733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
750733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
751733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
75277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *x = span->array->x;
75377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *y = span->array->y;
754733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
75577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLubyte *mask = span->array->mask;
756733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
757b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
758b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
759b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
760b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
761b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
762b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
763b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
764b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
765b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
766b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
767b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
768b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
769b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
77010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
771733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
77210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
773733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
774733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
775733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
776733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
777733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
778733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
779733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
780733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
781733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
782733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
783733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
78410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
785733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
786733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
787733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
788733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
7896ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul         _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
79010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
791733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
792733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
793733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
794733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
795733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
79610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
79710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
798733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
799733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
80010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
80110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
80210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
80379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
804e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Apply all the per-fragment opertions to a span of color index fragments
805e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * and write them to the enabled color drawbuffers.
806e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * The 'span' parameter can be considered to be const.  Note that
8077956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
8087956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
80910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
81010f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
81145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_write_index_span( GLcontext *ctx, struct sw_span *span)
81210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
813e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
814e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const struct gl_framebuffer *fb = ctx->DrawBuffer;
815e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLuint output = 0;
816e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
817e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
818e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   GLuint buf;
81910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
820733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
821b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
822b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
823733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
8247956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
8257956292a765910077f50352d7cd0174e1e66d26cBrian Paul
826733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
827733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
828733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
829733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
830733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
831a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
832733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
83310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
83410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
835733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
836b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
837733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
83886ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
839e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
840e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
841e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
842e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   /* Depth bounds test */
84331e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
844e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      if (!_swrast_depth_bounds_test(ctx, span)) {
845e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul         return;
846e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      }
847e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   }
848e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul
849b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
850a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
851b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
852a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
853b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
85477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
85577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
85677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
85777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
85877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
859b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
860b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
861b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
862b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
863b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
864e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
865b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
86610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
867e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
868e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
869e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   /* Stencil and Z testing */
8707956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
8717956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (span->interpMask & SPAN_Z)
87245bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
87310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8747956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
87545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
8767956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
8777956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
8787956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
8792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
8807956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
8817956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
88245bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
883e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            span->interpMask = origInterpMask;
8847956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
8857956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
8867956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
8872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
88810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
88910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
890b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
89123ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
892939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
89323ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
894b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
895b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
89623ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
897b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
898b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
899b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
9007956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
9017956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
90210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
9032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
90410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
90510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
90610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
9077956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
908dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled ||
909e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexLogicOpEnabled ||
910e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexMask != 0xffffffff ||
911e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       (span->arrayMask & SPAN_COVERAGE)) {
912e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (span->interpMask & SPAN_INDEX) {
913e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         interpolate_indexes(ctx, span);
914e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
9157956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
91610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
9177956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
918dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled) {
91945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_ci_span(ctx, span);
920e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
921e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
9232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
924e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      const GLfloat *coverage = span->array->coverage;
92577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLuint *index = span->array->index;
926e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLuint i;
92710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
92877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         ASSERT(coverage[i] < 16);
92977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
9305071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
9312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
9325071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
933e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   /* Loop over drawing buffers */
934e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
935e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
936e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLuint indexTemp[MAX_WIDTH], *index32;
937e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
938e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
939e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
940e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (ctx->Color.IndexLogicOpEnabled ||
941e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul          ctx->Color.IndexMask != 0xffffffff) {
942e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         /* make copy of incoming indexes */
943e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         MEMCPY(indexTemp, span->array->index, span->end * sizeof(GLuint));
9442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
945e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexLogicOpEnabled) {
946e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            _swrast_logicop_ci_span(ctx, rb, span, indexTemp);
947e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
948e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
949e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
950e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            _swrast_mask_ci_span(ctx, rb, span, indexTemp);
951e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
952e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         index32 = indexTemp;
953e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
954e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else {
955e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         index32 = span->array->index;
956e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
9572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
958e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
959e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         /* all fragments have same color index */
960e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLubyte index8;
961e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLushort index16;
962e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLuint index32;
963e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         void *value;
964e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
965e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (rb->DataType == GL_UNSIGNED_BYTE) {
966e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index8 = FixedToInt(span->index);
967e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            value = &index8;
968e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
969e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         else if (rb->DataType == GL_UNSIGNED_SHORT) {
970e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index16 = FixedToInt(span->index);
971e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            value = &index16;
972733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
973733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
974e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            ASSERT(rb->DataType == GL_UNSIGNED_INT);
975e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index32 = FixedToInt(span->index);
976e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            value = &index32;
977e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
978e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
979e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (span->arrayMask & SPAN_XY) {
980e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            rb->PutMonoValues(ctx, rb, span->end, span->array->x,
981e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                              span->array->y, value, span->array->mask);
982e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
983e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         else {
984e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
985e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                           value, span->array->mask);
986733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
9877956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
9887956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
989e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         /* each fragment is a different color */
990e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLubyte index8[MAX_WIDTH];
991e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLushort index16[MAX_WIDTH];
992e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         void *values;
993e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
994e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (rb->DataType == GL_UNSIGNED_BYTE) {
995e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            GLuint k;
996e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            for (k = 0; k < span->end; k++) {
997e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul               index8[k] = (GLubyte) index32[k];
998e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
999e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            values = index8;
1000e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1001e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         else if (rb->DataType == GL_UNSIGNED_SHORT) {
1002e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            GLuint k;
1003e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            for (k = 0; k < span->end; k++) {
1004e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul               index16[k] = (GLushort) index32[k];
1005e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
1006e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            values = index16;
1007733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1008733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
1009e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            ASSERT(rb->DataType == GL_UNSIGNED_INT);
1010e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            values = index32;
1011e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1012e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1013e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (span->arrayMask & SPAN_XY) {
1014e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            rb->PutValues(ctx, rb, span->end, span->array->x, span->array->y,
1015e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                          values, span->array->mask);
1016e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1017e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         else {
1018e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            rb->PutRow(ctx, rb, span->end, span->x, span->y,
1019e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                       values, span->array->mask);
1020733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
10217956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
1022e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
10232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
10247956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
10252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
1026e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1027e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1028e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
102979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1030e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color.  This is used only when
1031f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1032e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
10335071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
1034f1e236987829393c81dc86ea19cb49eefe190317Brian Pauladd_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1035e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1036e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   GLuint i;
1037f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   for (i = 0; i < n; i++) {
10384fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#if CHAN_TYPE == GL_FLOAT
10394fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul      /* no clamping */
1040f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][RCOMP] += specular[i][RCOMP];
1041f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][GCOMP] += specular[i][GCOMP];
1042f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][BCOMP] += specular[i][BCOMP];
10434fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#else
1044f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1045f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1046f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1047e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1048e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1049e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
10504fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#endif
1051e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1052e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1053e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1054e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
105579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1056e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * XXX merge this code into the _swrast_write_rgba_span() routine!
1057e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul *
1058e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Draw to more than one RGBA color buffer (or none).
1059e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * All fragment operations, up to (but not) blending/logicop should
1060e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * have been done first.
1061e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */
1062e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstatic void
1063e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulmulti_write_rgba_span( GLcontext *ctx, struct sw_span *span )
1064e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{
1065e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1066e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   struct gl_framebuffer *fb = ctx->DrawBuffer;
1067e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLuint output = 0;
1068e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   GLuint i;
1069e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1070e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   ASSERT(span->end < MAX_WIDTH);
1071e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   ASSERT(colorMask != 0x0);
1072e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1073e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   for (i = 0; i < fb->_NumColorDrawBuffers[output]; i++) {
1074e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][i];
1075e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLchan rgbaTmp[MAX_WIDTH][4];
1076e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1077e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* make copy of incoming colors */
1078e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) );
1079e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1080e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (ctx->Color._LogicOpEnabled) {
1081e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         _swrast_logicop_rgba_span(ctx, rb, span, rgbaTmp);
1082e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1083e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (ctx->Color.BlendEnabled) {
1084e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         _swrast_blend_span(ctx, rb, span, rgbaTmp);
1085e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1086e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1087e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (colorMask != 0xffffffff) {
1088e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         _swrast_mask_rgba_span(ctx, rb, span, rgbaTmp);
1089e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1090e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1091e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (span->arrayMask & SPAN_XY) {
1092e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         /* array of pixel coords */
1093bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         ASSERT(rb->PutValues);
1094bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         rb->PutValues(ctx, rb, span->end, span->array->x,
1095bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul                       span->array->y, rgbaTmp, span->array->mask);
1096e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1097e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else {
1098e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         /* horizontal run of pixels */
1099bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         ASSERT(rb->PutRow);
1100bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         rb->PutRow(ctx, rb, span->end, span->x, span->y, rgbaTmp,
1101bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul                    span->array->mask);
1102e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1103e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   }
1104e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul}
1105e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1106e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1107e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/**
1108a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Apply all the per-fragment operations to a span.
1109a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * This now includes texturing (_swrast_write_texture_span() is history).
1110f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
11117956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
11127956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
111378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
111478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
1115a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul_swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
111678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
111778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
111878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1119e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
1120e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
112132340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   const GLboolean deferredTexture = !(ctx->Color.AlphaEnabled ||
112232340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul                                       ctx->FragmentProgram._Active ||
1123071357096e682e9af59ad45ea5abc444ab431837Michal Krol                                       ctx->ShaderObjects._FragmentShaderPresent);
1124f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1125b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
1126b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
1127733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
11287956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
112978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1130ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /*
1131a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1132a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul          span->interpMask, span->arrayMask);
1133ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   */
1134ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1135733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1136733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1137733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1138733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1139733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
1140a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
1141733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
114278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
114378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1144a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Clip to window/scissor box */
1145b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1146733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1147733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
114878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
114978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
115078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1151b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1152a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
1153b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1154a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
1155b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
115677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
115777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
115877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
115977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
116077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1161b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1162b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1163b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1164b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1165b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
116678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1167b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1168733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
116978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
117078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1171a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Interpolate texcoords? */
1172a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   if (ctx->Texture._EnabledCoordUnits
1173a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul       && (span->interpMask & SPAN_TEXTURE)
1174a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul       && (span->arrayMask & SPAN_TEXTURE) == 0) {
1175f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      interpolate_texcoords(ctx, span);
1176a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   }
117778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1178bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   if (ctx->ShaderObjects._FragmentShaderPresent) {
1179bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      interpolate_varying(ctx, span);
1180bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   }
1181bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
118232340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* This is the normal place to compute the resulting fragment color/Z.
118332340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * As an optimization, we try to defer this until after Z/stencil
118432340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * testing in order to try to avoid computing colors that we won't
118532340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * actually need.
1186a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
118732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   if (!deferredTexture) {
1188f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1189f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1190f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
1191f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1192a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      if (span->interpMask & SPAN_SPEC)
119336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         interpolate_specular(ctx, span);
119436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul
1195d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      if (span->interpMask & SPAN_FOG)
1196d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul         interpolate_fog(ctx, span);
1197d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
1198bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      /* Compute fragment colors with fragment program or texture lookups */
1199bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      if (ctx->ShaderObjects._FragmentShaderPresent) {
1200bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         if (span->interpMask & SPAN_Z)
1201bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            _swrast_span_interpolate_z (ctx, span);
1202bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         _swrast_exec_arbshader (ctx, span);
1203a66393120411071b3f3ccce8583ab961a2935959Michal Krol      }
1204a66393120411071b3f3ccce8583ab961a2935959Michal Krol      else if (ctx->FragmentProgram._Active) {
120532340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul         /* frag prog may need Z values */
120632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul         if (span->interpMask & SPAN_Z)
120732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul            _swrast_span_interpolate_z(ctx, span);
1208e22540c2765e034fed558ea1d44488a03fbba170Brian Paul         _swrast_exec_fragment_program( ctx, span );
120932340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul      }
12107f752fed993e5e9423abac200dd59141edbada56Dave Airlie      else if (ctx->ATIFragmentShader._Enabled)
12117f752fed993e5e9423abac200dd59141edbada56Dave Airlie         _swrast_exec_fragment_shader( ctx, span );
1212252d8e78cc07880239b085b713e2d37ddbba86f9Brian Paul      else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE))
1213610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul         _swrast_texture_span( ctx, span );
121478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
121578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Do the alpha test */
12165e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger      if (ctx->Color.AlphaEnabled) {
12175e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger         if (!_swrast_alpha_test(ctx, span)) {
12185e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger            span->arrayMask = origArrayMask;
12195e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger	    return;
12205e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger	 }
122178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
122278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
122378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1224f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1225f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1226f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
122745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
122878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1229e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1230a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Combined Z/stencil tests */
123145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1232e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul            span->interpMask = origInterpMask;
1233f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
123410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1235f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
123671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1237e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1238a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Just regular depth testing */
1239f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1240f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
124145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
1242e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul            span->interpMask = origInterpMask;
1243f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
124410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1245f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
124671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
124771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
124871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1249b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
125023ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1251939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
125223ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1253b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1254b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
125523ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1256b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1257b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
1258b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
1259a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1260f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1261f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1262f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1263e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      span->interpMask = origInterpMask;
1264f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      span->arrayMask = origArrayMask;
1265f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      return;
126671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
126771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
126832340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* If we were able to defer fragment color computation to now, there's
126932340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * a good chance that many fragments will have already been killed by
127032340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * Z/stencil testing.
1271a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
127232340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   if (deferredTexture) {
1273f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1274f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1275f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
127671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1277a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      if (span->interpMask & SPAN_SPEC)
127836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         interpolate_specular(ctx, span);
127936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul
1280d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      if (span->interpMask & SPAN_FOG)
1281d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul         interpolate_fog(ctx, span);
1282d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
1283bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      if (ctx->ShaderObjects._FragmentShaderPresent) {
1284bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         if (span->interpMask & SPAN_Z)
1285bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            _swrast_span_interpolate_z (ctx, span);
1286bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         _swrast_exec_arbshader (ctx, span);
1287bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      }
1288a66393120411071b3f3ccce8583ab961a2935959Michal Krol      else if (ctx->FragmentProgram._Active)
1289e22540c2765e034fed558ea1d44488a03fbba170Brian Paul         _swrast_exec_fragment_program( ctx, span );
12907f752fed993e5e9423abac200dd59141edbada56Dave Airlie      else if (ctx->ATIFragmentShader._Enabled)
12917f752fed993e5e9423abac200dd59141edbada56Dave Airlie         _swrast_exec_fragment_shader( ctx, span );
1292252d8e78cc07880239b085b713e2d37ddbba86f9Brian Paul      else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE))
1293610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul         _swrast_texture_span( ctx, span );
129471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
129571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1296f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
12972ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
12989d148e6b2be33fe7ac72aaa3be239dc1bc8878a9Keith Whitwell   if (!ctx->FragmentProgram._Enabled) {
1299dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      /* Add base and specular colors */
1300dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      if (ctx->Fog.ColorSumEnabled ||
1301dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul          (ctx->Light.Enabled &&
1302dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1303dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         if (span->interpMask & SPAN_SPEC) {
1304dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul            interpolate_specular(ctx, span);
1305dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         }
1306a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         if (span->arrayMask & SPAN_SPEC) {
1307a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul            add_colors( span->end, span->array->rgba, span->array->spec );
1308a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
1309a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         else {
1310a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul            /* We probably added the base/specular colors during the
1311a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             * vertex stage!
1312a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             */
1313a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
131471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
131571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
131671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
13176e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
131809da0b8e6621a831e3eeb9381430f2bed18a22adBrian Paul   if (swrast->_FogEnabled) {
131945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_rgba_span(ctx, span);
132071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1321f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
132271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
13232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
132477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLchan (*rgba)[4] = span->array->rgba;
132577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLfloat *coverage = span->array->coverage;
132671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      GLuint i;
132710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
132877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
132971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
133071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
133171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1332ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1333ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul#if CHAN_TYPE == GL_FLOAT
1334ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   if (ctx->Color.ClampFragmentColor) {
1335ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      GLchan (*rgba)[4] = span->array->rgba;
1336ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      GLuint i;
1337ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      for (i = 0; i < span->end; i++) {
1338ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0, CHAN_MAXF);
1339ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0, CHAN_MAXF);
1340ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0, CHAN_MAXF);
1341ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0, CHAN_MAXF);
1342ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      }
1343ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   }
1344ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul#endif
1345ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul
134671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1347a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      /* need to do blend/logicop separately for each color buffer */
1348733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_rgba_span(ctx, span);
134971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
135071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   else {
135171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      /* normal: write to exactly one buffer */
1352e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];
1353e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
135457857ca0925116d6d254fef7e705cfe0b650d77fBrian Paul      if (ctx->Color._LogicOpEnabled) {
1355e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         _swrast_logicop_rgba_span(ctx, rb, span, span->array->rgba);
135671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
135795e2c72fd52d87163eb543555345f115f050f3aaBrian Paul      else if (ctx->Color.BlendEnabled) {
1358e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         _swrast_blend_span(ctx, rb, span, span->array->rgba);
135971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
136071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1361e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      /* Color component masking */
1362f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (colorMask != 0xffffffff) {
1363e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         _swrast_mask_rgba_span(ctx, rb, span, span->array->rgba);
136471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
136571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1366a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      /* Finally, write the pixels to a color buffer */
1367733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
1368733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
1369bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         ASSERT(rb->PutValues);
1370bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1371bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         /* XXX check datatype */
1372bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         rb->PutValues(ctx, rb, span->end, span->array->x, span->array->y,
1373bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul                       span->array->rgba, span->array->mask);
1374733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
1375733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      else {
1376733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
1377bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         ASSERT(rb->PutRow);
1378bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1379bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         /* XXX check datatype */
1380bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul         rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1381bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul                    span->writeAll ? NULL : span->array->mask);
138271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
138371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
138471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1385e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   span->interpMask = origInterpMask;
1386f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
138710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
138810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1389e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1390e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
139179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1392e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
1393e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1394e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
13955071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1396e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1397a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul                        GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1398e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1399e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1400e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1401a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1402a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1403e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1404e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* XXX maybe leave rgba values undefined? */
14056ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul      _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1406e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1407e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1408e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1409e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
14107e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1411e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1412e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1413e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1414e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1415e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1416e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1417a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1418a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1419e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1420e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1421a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1422e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1423e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1424a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1425e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1426e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1427e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1428e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1429e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1430e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1431e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1432e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1433e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1434e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1435e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1436bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb);
1437bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->GetRow);
1438bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
1439bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1440bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      rb->GetRow(ctx, rb, length, x + skip, y, rgba + skip);
1441e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1442e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1443e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1444e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
144579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1446e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read CI pixels from frame buffer.  Clipping will be done to prevent
1447e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1448e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
14495071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1450e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1451e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                         GLuint n, GLint x, GLint y, GLuint index[] )
1452e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1453e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1454e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1455a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1456a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1457e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1458e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      _mesa_bzero(index, n * sizeof(GLuint));
1459e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1460e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1461e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1462e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
14637e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1464e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1465e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1466e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1467e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1468e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1469e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1470a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1471a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1472e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1473e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1474a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1475e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1476e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1477a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1478e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1479e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1480e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1481e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1482e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1483e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1484e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1485e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1486e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1487e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1488e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1489e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->GetRow);
1490e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1491e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1492e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (rb->DataType == GL_UNSIGNED_BYTE) {
1493e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLubyte index8[MAX_WIDTH];
1494e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1495e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index8);
1496e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1497e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index8[i];
1498e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1499e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_SHORT) {
1500e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLushort index16[MAX_WIDTH];
1501e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1502e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index16);
1503e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1504e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index16[i];
1505e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1506e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_INT) {
1507e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1508e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1509e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1510e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
151167074332728acba86da7630353673b458713bb8aBrian Paul
151267074332728acba86da7630353673b458713bb8aBrian Paul
151367074332728acba86da7630353673b458713bb8aBrian Paul/**
151467074332728acba86da7630353673b458713bb8aBrian Paul * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
151567074332728acba86da7630353673b458713bb8aBrian Paul * reading values outside the buffer bounds.
151667074332728acba86da7630353673b458713bb8aBrian Paul * We can use this for reading any format/type of renderbuffer.
151767074332728acba86da7630353673b458713bb8aBrian Paul * \param valueSize is the size in bytes of each value put into the
151867074332728acba86da7630353673b458713bb8aBrian Paul *                  values array.
151967074332728acba86da7630353673b458713bb8aBrian Paul */
152067074332728acba86da7630353673b458713bb8aBrian Paulvoid
152167074332728acba86da7630353673b458713bb8aBrian Paul_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
152267074332728acba86da7630353673b458713bb8aBrian Paul                   GLuint count, const GLint x[], const GLint y[],
152367074332728acba86da7630353673b458713bb8aBrian Paul                   void *values, GLuint valueSize)
152467074332728acba86da7630353673b458713bb8aBrian Paul{
152567074332728acba86da7630353673b458713bb8aBrian Paul   GLuint i, inCount = 0, inStart = 0;
152667074332728acba86da7630353673b458713bb8aBrian Paul
152767074332728acba86da7630353673b458713bb8aBrian Paul   for (i = 0; i < count; i++) {
152867074332728acba86da7630353673b458713bb8aBrian Paul      if (x[i] >= 0 && y[i] >= 0 && x[i] < rb->Width && y[i] < rb->Height) {
152967074332728acba86da7630353673b458713bb8aBrian Paul         /* inside */
153067074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount == 0)
153167074332728acba86da7630353673b458713bb8aBrian Paul            inStart = i;
153267074332728acba86da7630353673b458713bb8aBrian Paul         inCount++;
153367074332728acba86da7630353673b458713bb8aBrian Paul      }
153467074332728acba86da7630353673b458713bb8aBrian Paul      else {
153567074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount > 0) {
153667074332728acba86da7630353673b458713bb8aBrian Paul            /* read [inStart, inStart + inCount) */
153767074332728acba86da7630353673b458713bb8aBrian Paul            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
153867074332728acba86da7630353673b458713bb8aBrian Paul                          (GLubyte *) values + inStart * valueSize);
153967074332728acba86da7630353673b458713bb8aBrian Paul            inCount = 0;
154067074332728acba86da7630353673b458713bb8aBrian Paul         }
154167074332728acba86da7630353673b458713bb8aBrian Paul      }
154267074332728acba86da7630353673b458713bb8aBrian Paul   }
154367074332728acba86da7630353673b458713bb8aBrian Paul   if (inCount > 0) {
154467074332728acba86da7630353673b458713bb8aBrian Paul      /* read last values */
154567074332728acba86da7630353673b458713bb8aBrian Paul      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
154667074332728acba86da7630353673b458713bb8aBrian Paul                    (GLubyte *) values + inStart * valueSize);
154767074332728acba86da7630353673b458713bb8aBrian Paul   }
154867074332728acba86da7630353673b458713bb8aBrian Paul}
15493fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15503fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15513fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul/**
15523fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul * Wrapper for gl_renderbuffer::PutRow() which does clipping.
15533fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul */
15543fd819aef8139761ce86cb8d763de83a11c81b33Brian Paulvoid
15553fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
15563fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                GLuint count, GLint x, GLint y,
15573fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                const GLvoid *values, GLuint valueSize)
15583fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul{
15593fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   GLint skip = 0;
15603fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15613fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (y < 0 || y >= rb->Height)
15623fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* above or below */
15633fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15643fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x + (GLint) count <= 0 || x >= rb->Width)
15653fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* entirely left or right */
15663fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15673fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x + count > rb->Width) {
15683fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* right clip */
15693fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      GLint clip = x + count - rb->Width;
15703fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= clip;
15713fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
15723fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15733fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x < 0) {
15743fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* left clip */
15753fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      skip = -x;
15763fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      x = 0;
15773fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= skip;
15783fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
15793fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15803fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   rb->PutRow(ctx, rb, count, x, y,
15813fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul              (const GLubyte *) values + skip * valueSize, NULL);
15823fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul}
1583f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1584f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1585f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul/**
1586f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1587f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul */
1588f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paulvoid
1589f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1590f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLuint count, GLint x, GLint y,
1591f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLvoid *values, GLuint valueSize)
1592f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul{
1593f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   GLint skip = 0;
1594f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1595f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (y < 0 || y >= rb->Height)
1596f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* above or below */
1597f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1598f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + (GLint) count <= 0 || x >= rb->Width)
1599f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* entirely left or right */
1600f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1601f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + count > rb->Width) {
1602f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* right clip */
1603f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      GLint clip = x + count - rb->Width;
1604f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= clip;
1605f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1606f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1607f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x < 0) {
1608f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* left clip */
1609f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      skip = -x;
1610f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      x = 0;
1611f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= skip;
1612f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1613f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1614f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1615f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul}
1616