s_span.c revision bb19e64d12eaf27e2adc3faac7e09555bb66d724
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"
38f971e24cf0341dd2779196a0836327b74fc82336Brian Paul#include "image.h"
39e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
407f752fed993e5e9423abac200dd59141edbada56Dave Airlie#include "s_atifragshader.h"
41bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol#include "s_alpha.h"
42a66393120411071b3f3ccce8583ab961a2935959Michal Krol#include "s_arbshader.h"
43e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
44cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
48e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
49610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul#include "s_nvfragprog.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
51e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
5255187ea63e980b32c7a701855571332f4357d634Brian Paul#include "s_texcombine.h"
53e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
5579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's Z interpolation values to the RasterPos Z.
572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
60cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_z( GLcontext *ctx, SWspan *span )
612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
62e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
6331e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16)
64e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else
66e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      span->z = (GLint) (ctx->Current.RasterPos[2] * depthMax + 0.5F);
672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->zStep = 0;
682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_Z;
692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
7279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's fog interpolation values to the RasterPos fog.
742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
77cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_fog( GLcontext *ctx, SWspan *span )
782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
7945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul   span->fog = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
8054e92e8420a028f07b0971ee8aa93be9b4214579Brian Paul   span->fogStep = span->dfogdx = span->dfogdy = 0.0F;
812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_FOG;
822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
86a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Init span's rgba or index interpolation values to the RasterPos color.
872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
90cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_color( GLcontext *ctx, SWspan *span )
912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.rgbMode) {
932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan r, g, b, a;
942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red = r;
1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = g;
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue = b;
1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = a;
1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
1042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red   = IntToFixed(r);
1052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = IntToFixed(g);
1062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue  = IntToFixed(b);
1072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = IntToFixed(a);
1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->redStep = 0;
1102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->greenStep = 0;
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blueStep = 0;
1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alphaStep = 0;
1132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_RGBA;
1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1160f3cd3f894612d156de454178effa4c732f96da7Brian Paul      span->index = FloatToFixed(ctx->Current.RasterIndex);
1172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->indexStep = 0;
1182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_INDEX;
1192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1234753d60dd070bb08d0116076bcc08025c86ce857Brian Paul/**
1244753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Init span's texcoord interpolation values to the RasterPos texcoords.
1254753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Used during setup for glDraw/CopyPixels.
1264753d60dd070bb08d0116076bcc08025c86ce857Brian Paul */
1274753d60dd070bb08d0116076bcc08025c86ce857Brian Paulvoid
128cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_texcoords( GLcontext *ctx, SWspan *span )
1294753d60dd070bb08d0116076bcc08025c86ce857Brian Paul{
1304753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   GLuint i;
131ee4e75bd6f768b7210436feeb32b4545ed62e025Brian Paul   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
132e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      const GLfloat *tc = ctx->Current.RasterTexCoords[i];
1337e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell      if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled) {
134a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         COPY_4V(span->tex[i], tc);
135a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      }
136a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      else if (tc[3] > 0.0F) {
137e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         /* use (s/q, t/q, r/q, 1) */
138e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][0] = tc[0] / tc[3];
139e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][1] = tc[1] / tc[3];
140e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][2] = tc[2] / tc[3];
141e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         span->tex[i][3] = 1.0;
142e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
143e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      else {
144e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F);
145e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
1465f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul      ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
1475f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul      ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
1484753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   }
1494753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   span->interpMask |= SPAN_TEXTURE;
1504753d60dd070bb08d0116076bcc08025c86ce857Brian Paul}
1514753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
1524753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
153d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
154e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul * Interpolate primary colors to fill in the span->array->color array.
155d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
156f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
157e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paulinterpolate_colors(SWspan *span)
1582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
1612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
162e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   ASSERT((span->interpMask & SPAN_RGBA)  &&
163e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul          !(span->arrayMask & SPAN_RGBA));
1642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
165e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   switch (span->array->ChanType) {
1661e3223c02a2f6155beb5784cadbea1f46703829aBrian Paul#if CHAN_BITS != 32
167e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_BYTE:
168e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
169e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
170e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
171d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLubyte color[4];
172e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
173e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
174e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
175e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
176d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
177d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4UBV(rgba[i], color);
178d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
179d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
180e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
181e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = span->red;
182e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = span->green;
183e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = span->blue;
184e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed a = span->alpha;
185e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = span->redStep;
186e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = span->greenStep;
187e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = span->blueStep;
188e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint da = span->alphaStep;
189d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
190e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][RCOMP] = FixedToChan(r);
191e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][GCOMP] = FixedToChan(g);
192e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][BCOMP] = FixedToChan(b);
193e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][ACOMP] = FixedToChan(a);
194e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               r += dr;
195e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               g += dg;
196e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               b += db;
197e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               a += da;
198d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
199d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
200e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
201e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
202e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_SHORT:
203e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
204e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
205e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
206e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort color[4];
207e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
208e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
209e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
210e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
211d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
212d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4V(rgba[i], color);
213d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
214d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
215e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
216e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort (*rgba)[4] = span->array->color.sz2.rgba;
217d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfixed r, g, b, a;
218d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint dr, dg, db, da;
219e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            r = span->red;
220e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            g = span->green;
221e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            b = span->blue;
222e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            a = span->alpha;
223e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = span->redStep;
224e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dg = span->greenStep;
225e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            db = span->blueStep;
226e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            da = span->alphaStep;
227d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
228d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][RCOMP] = FixedToChan(r);
229d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][GCOMP] = FixedToChan(g);
230d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][BCOMP] = FixedToChan(b);
231d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][ACOMP] = FixedToChan(a);
232d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
233d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
234d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
235d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a += da;
236d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
237d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
238e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
239e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
240e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul#endif
241e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_FLOAT:
242e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
243e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
244e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLfloat r, g, b, a, dr, dg, db, da;
245e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         r = span->red;
246e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         g = span->green;
247e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         b = span->blue;
248e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         a = span->alpha;
249e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
250e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = dg = db = da = 0.0;
251e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
252e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
253e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = span->redStep;
254e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dg = span->greenStep;
255e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            db = span->blueStep;
256e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            da = span->alphaStep;
257e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
258e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         for (i = 0; i < n; i++) {
259e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][RCOMP] = r;
260e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][GCOMP] = g;
261e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][BCOMP] = b;
262e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][ACOMP] = a;
263e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            r += dr;
264e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            g += dg;
265e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            b += db;
266e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            a += da;
267e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
268e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
269e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
270e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   default:
271e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      _mesa_problem(NULL, "bad datatype in interpolate_colors");
272e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   }
273e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   span->arrayMask |= SPAN_RGBA;
274e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul}
275e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
276e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
277e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul/**
278e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul * Interpolate specular/secondary colors.
279e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul */
280f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
281e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paulinterpolate_specular(SWspan *span)
282e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul{
283e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   const GLuint n = span->end;
284e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   GLuint i;
285e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
286e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   switch (span->array->ChanType) {
287c351858de8e51fa4a6425cf176cc43689189f3ffBrian Paul#if CHAN_BITS != 32
288e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_BYTE:
289e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
290e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLubyte (*spec)[4] = span->array->color.sz1.spec;
291e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
292e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLubyte color[4];
293e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->specRed);
294e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->specGreen);
295e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->specBlue);
296e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = 0;
297e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            for (i = 0; i < n; i++) {
298e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               COPY_4UBV(spec[i], color);
299d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
300e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
301e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
302e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = span->specRed;
303e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = span->specGreen;
304e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = span->specBlue;
305e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = span->specRedStep;
306e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = span->specGreenStep;
307e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = span->specBlueStep;
308d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
309e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][RCOMP] = CLAMP(FixedToChan(r), 0, 255);
310e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][GCOMP] = CLAMP(FixedToChan(g), 0, 255);
311e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][BCOMP] = CLAMP(FixedToChan(b), 0, 255);
312e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][ACOMP] = 0;
313d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
314d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
315d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
316d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
317d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
318e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
319e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
320e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_SHORT:
321e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
322e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLushort (*spec)[4] = span->array->color.sz2.spec;
323e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
324e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort color[4];
325e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->specRed);
326e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->specGreen);
327e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->specBlue);
328e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = 0;
329e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            for (i = 0; i < n; i++) {
330e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               COPY_4V(spec[i], color);
331d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
332e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
333e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
334e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = FloatToFixed(span->specRed);
335e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = FloatToFixed(span->specGreen);
336e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = FloatToFixed(span->specBlue);
337e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = FloatToFixed(span->specRedStep);
338e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = FloatToFixed(span->specGreenStep);
339e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = FloatToFixed(span->specBlueStep);
340e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            for (i = 0; i < n; i++) {
341e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][RCOMP] = FixedToInt(r);
342e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][GCOMP] = FixedToInt(g);
343e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][BCOMP] = FixedToInt(b);
344e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][ACOMP] = 0;
345e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               r += dr;
346e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               g += dg;
347e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               b += db;
348d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
349e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
350e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
351e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
352c351858de8e51fa4a6425cf176cc43689189f3ffBrian Paul#endif
353e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_FLOAT:
354e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
355e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLfloat (*spec)[4] = span->array->color.sz4.spec;
356e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
357e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfloat color[4];
358e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = span->specRed;
359e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = span->specGreen;
360e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = span->specBlue;
361e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = 0.0F;
362d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
363e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               COPY_4V(spec[i], color);
364e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            }
365e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
366e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
367e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfloat r = span->specRed;
368e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfloat g = span->specGreen;
369e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfloat b = span->specBlue;
370e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfloat dr = span->specRedStep;
371e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfloat dg = span->specGreenStep;
372e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfloat db = span->specBlueStep;
373e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            for (i = 0; i < n; i++) {
374e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][RCOMP] = r;
375e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][GCOMP] = g;
376e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][BCOMP] = b;
377e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][ACOMP] = 0.0F;
378d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
379d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
380d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
381d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
382d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
3832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
384e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
385e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   default:
386e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      _mesa_problem(NULL, "bad datatype in interpolate_specular");
3872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
388e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   span->arrayMask |= SPAN_SPEC;
3892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
3902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
393f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
394cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_indexes(GLcontext *ctx, SWspan *span)
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
3972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
3982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
39977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLuint *indexes = span->array->index;
4002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
401a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
402b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_INDEX)  &&
403b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_INDEX));
4042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
4062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
4072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
4082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
4092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
4102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
4132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
4142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
4152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
4162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
4172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
420e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   span->interpMask &= ~SPAN_INDEX;
4212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
424d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul/* Fill in the span.array.fog values from the interpolation values */
425f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
426cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_fog(const GLcontext *ctx, SWspan *span)
427d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul{
428d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat *fog = span->array->fog;
429d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLfloat fogStep = span->fogStep;
430d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat fogCoord = span->fog;
431d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLuint haveW = (span->interpMask & SPAN_W);
432d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLfloat wStep = haveW ? span->dwdx : 0.0F;
433d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat w = haveW ? span->w : 1.0F;
434d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLuint i;
435d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   for (i = 0; i < span->end; i++) {
436d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      fog[i] = fogCoord / w;
437d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      fogCoord += fogStep;
438d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      w += wStep;
439d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   }
440d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   span->arrayMask |= SPAN_FOG;
441d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul}
442d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
443d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
4442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */
445711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
446cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
4472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
4482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
4492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
4502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
451b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_Z)  &&
452b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_Z));
4532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
45431e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16) {
4552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
4563e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
457ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      for (i = 0; i < n; i++) {
45877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = FixedToInt(zval);
4592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
4632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
4647265556b9aa0367e9b5031e7cb15ed2a5d73866dBrian Paul      GLuint zval = span->z;
4653e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
4662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
46777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = zval;
4682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
47132340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   span->interpMask &= ~SPAN_Z;
4722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
4732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
476c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
47731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
478c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
479c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
48031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
48131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
48231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
48331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
484c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
48531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
48631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
48731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
48831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
489f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
490f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
49131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
49231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
49331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
494c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
495c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
496c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
49731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
49831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/*
49931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This is a faster approximation
500c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
501350353adcd75f94fda63c787c86961716114e0bfBrian PaulGLfloat
50245bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
503350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
504350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
505c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
50631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
50731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
50831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
50931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
51031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
51131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
51231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
51331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
51431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
51531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
51631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
51731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
51831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
51931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
520c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
521c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
522d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
523d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul/**
524c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Fill in the span.texcoords array from the interpolation values.
525d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * Note: in the places where we divide by Q (or mult by invQ) we're
526d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * really doing two things: perspective correction and texcoord
527d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * projection.  Remember, for texcoord (s,t,r,q) we need to index
528d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * texels with (s/q, t/q, r/q).
529d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * If we're using a fragment program, we never do the division
530d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * for texcoord projection.  That's done by the TXP instruction
531d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * or user-written code.
532c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
5332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
534cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_texcoords(GLcontext *ctx, SWspan *span)
5352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
5362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_TEXTURE);
537b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(!(span->arrayMask & SPAN_TEXTURE));
5382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
53936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul   if (ctx->Texture._EnabledCoordUnits > 1) {
54031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* multitexture */
54131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      GLuint u;
542b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
543ee4e75bd6f768b7210436feeb32b4545ed62e025Brian Paul      /* XXX CoordUnits vs. ImageUnits */
54431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
54536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
54631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
54736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            GLfloat texW, texH;
54836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            GLboolean needLambda;
54936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            if (obj) {
55018fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell               const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
55136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               needLambda = (obj->MinFilter != obj->MagFilter)
5527e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell                  || ctx->FragmentProgram._Enabled;
55336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texW = img->WidthScale;
55436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texH = img->HeightScale;
55536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            }
55636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            else {
557d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               /* using a fragment program */
55836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texW = 1.0;
55936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texH = 1.0;
56036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               needLambda = GL_FALSE;
56136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            }
56231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            if (needLambda) {
56377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
56477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
56531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
56631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdy = span->texStepY[u][0];
56731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
56831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdy = span->texStepY[u][1];
56931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
57031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
57131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdy = span->texStepY[u][3];
5722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
5732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
5742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
5752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
5762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
5777e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell               if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
578bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol                   ctx->ShaderObjects._FragmentShaderPresent) {
579d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  /* do perspective correction but don't divide s, t, r by q */
580d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  const GLfloat dwdx = span->dwdx;
581d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  GLfloat w = span->w;
582d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
583d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invW = 1.0F / w;
584d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invW;
585d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invW;
586d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invW;
587d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q * invW;
588d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
589d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        dqdx, dqdy, texW, texH,
590d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        s, t, q, invW);
591d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
592d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
593d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
594d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
595d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     w += dwdx;
596d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
597d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
598d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               }
599d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               else {
600d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
601d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
602d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invQ;
603d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invQ;
604d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invQ;
605d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q;
606d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
607d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        dqdx, dqdy, texW, texH,
608d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        s, t, q, invQ);
609d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
610d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
611d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
612d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
613d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
6142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
61531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               span->arrayMask |= SPAN_LAMBDA;
6162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
61731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
61877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
61977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
62031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
62131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
62231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
62331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
6242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
6252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
6262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
6272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
6282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
6297e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell               if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
630bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol                   ctx->ShaderObjects._FragmentShaderPresent) {
631d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  /* do perspective correction but don't divide s, t, r by q */
632d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  const GLfloat dwdx = span->dwdx;
633d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  GLfloat w = span->w;
634d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
635d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invW = 1.0F / w;
636d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invW;
637d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invW;
638d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invW;
639d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q * invW;
640d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = 0.0;
641d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
642d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
643d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
644d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
645d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     w += dwdx;
646d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
647d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               }
648d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               else if (dqdx == 0.0F) {
649c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  /* Ortho projection or polygon's parallel to window X axis */
6502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
651c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
65277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
65377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
65477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
65536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul                     texcoord[i][3] = q;
65677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
65731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
65831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
65931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
660c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
661c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               }
662c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               else {
663c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
664c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
66577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
66677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
66777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
66836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul                     texcoord[i][3] = q;
66977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
67031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
67131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
67231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
67331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     q += dqdx;
674c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
6752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
67631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            } /* lambda */
67731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         } /* if */
67831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      } /* for */
6792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
6802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
68131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* single texture */
68231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
68336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      GLfloat texW, texH;
68436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      GLboolean needLambda;
68536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      if (obj) {
68618fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell         const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
68736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         needLambda = (obj->MinFilter != obj->MagFilter)
6887e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell            || ctx->FragmentProgram._Enabled;
68936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texW = (GLfloat) img->WidthScale;
69036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texH = (GLfloat) img->HeightScale;
69136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      }
69236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      else {
69336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         needLambda = GL_FALSE;
69436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texW = texH = 1.0;
69536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      }
696b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
69731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      if (needLambda) {
6982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* just texture unit 0, with lambda */
69977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
70077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat *lambda = span->array->lambda[0];
70131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
70231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdy = span->texStepY[0][0];
70331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
70431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdy = span->texStepY[0][1];
70531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
70631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
70731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdy = span->texStepY[0][3];
7082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
7092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
7102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
7112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
7122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
7137e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell         if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
714bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol             ctx->ShaderObjects._FragmentShaderPresent) {
715d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* do perspective correction but don't divide s, t, r by q */
716d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            const GLfloat dwdx = span->dwdx;
717d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            GLfloat w = span->w;
718d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
719d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invW = 1.0F / w;
720d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invW;
721d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invW;
722d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invW;
723d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q * invW;
724d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
725d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                  dqdx, dqdy, texW, texH,
726d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                  s, t, q, invW);
727d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
728d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
729d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
730d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
731d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               w += dwdx;
732d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
733d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
734d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else {
735d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* tex.c */
736d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
737d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
738d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
739d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                dqdx, dqdy, texW, texH,
740d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                s, t, q, invQ);
741d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invQ;
742d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invQ;
743d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invQ;
744d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q;
745d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
746d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
747d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
748d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
749d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
7502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
7512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask |= SPAN_LAMBDA;
7522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
7532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      else {
754733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* just texture 0, without lambda */
75577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
75631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
75731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
75831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
75931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
7602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
7612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
7622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
7632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
7642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
7657e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell         if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
766bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol             ctx->ShaderObjects._FragmentShaderPresent) {
767d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* do perspective correction but don't divide s, t, r by q */
768d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            const GLfloat dwdx = span->dwdx;
769d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            GLfloat w = span->w;
770d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
771d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invW = 1.0F / w;
772d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invW;
773d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invW;
774d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invW;
775d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q * invW;
776d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
777d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
778d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
779d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
780d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               w += dwdx;
781d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
782d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
783d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else if (dqdx == 0.0F) {
784c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            /* Ortho projection or polygon's parallel to window X axis */
7852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
786c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
78777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
78877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
78977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
7902b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul               texcoord[i][3] = q;
79131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
79231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
79331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
794c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
795c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         }
796c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         else {
797c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
798c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
79977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
80077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
80177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
8022b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul               texcoord[i][3] = q;
80331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
80431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
80531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
80631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               q += dqdx;
807c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
8082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
8092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
8102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
81110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
812e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
813e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
81479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
815bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol * Fill in the span.varying array from the interpolation values.
816bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol */
817f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
818cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_varying(GLcontext *ctx, SWspan *span)
819bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol{
820bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   GLuint i, j;
821bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
822bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(span->interpMask & SPAN_VARYING);
823bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(!(span->arrayMask & SPAN_VARYING));
824bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
825bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   span->arrayMask |= SPAN_VARYING;
826bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
827bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   for (i = 0; i < MAX_VARYING_VECTORS; i++) {
828bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      for (j = 0; j < VARYINGS_PER_VECTOR; j++) {
829bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         const GLfloat dvdx = span->varStepX[i][j];
830bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLfloat v = span->var[i][j];
831bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         const GLfloat dwdx = span->dwdx;
832bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLfloat w = span->w;
833bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLuint k;
834bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
835bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         for (k = 0; k < span->end; k++) {
836bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            GLfloat invW = 1.0f / w;
837bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            span->array->varying[k][i][j] = v * invW;
838bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            v += dvdx;
839bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            w += dwdx;
840bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         }
841bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      }
842bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   }
843bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol}
844bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
845bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
846bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol/**
847e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
848e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
849f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
850cdb27e8242215271364602995d85607cfc06d441Brian Paulstipple_polygon_span( GLcontext *ctx, SWspan *span )
85110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
85210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint highbit = 0x80000000;
853733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLuint stipple = ctx->PolygonStipple[span->y % 32];
85477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLubyte *mask = span->array->mask;
855733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   GLuint i, m;
856733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
857733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
858733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->arrayMask & SPAN_XY) == 0);
85910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
86010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   m = highbit >> (GLuint) (span->x % 32);
86110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
86210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (i = 0; i < span->end; i++) {
86310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if ((m & stipple) == 0) {
86477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul	 mask[i] = 0;
86510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
86610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      m = m >> 1;
86710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (m == 0) {
86810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         m = highbit;
86910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
87010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
8712ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
87210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
87310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
874e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
87579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
876733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
877733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
878733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
879733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
88010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
88110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
882f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE GLuint
883cdb27e8242215271364602995d85607cfc06d441Brian Paulclip_span( GLcontext *ctx, SWspan *span )
88410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
885733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
886733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
887733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
888733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
889733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
890733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
891733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
89277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *x = span->array->x;
89377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *y = span->array->y;
894733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
89577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLubyte *mask = span->array->mask;
896733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
897b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
898b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
899b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
900b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
901b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
902b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
903b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
904b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
905b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
906b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
907b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
908b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
909b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
91010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
911733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
91210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
913733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
914733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
915733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
916733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
917733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
918733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
919733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
920733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
921733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
922733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
923733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
92410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
925733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
926733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
927733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
928733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
9296ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul         _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
93010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
931733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
932733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
933733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
934733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
935733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
93610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
93710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
938733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
939733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
94010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
94110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
94210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
94379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
944e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Apply all the per-fragment opertions to a span of color index fragments
945e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * and write them to the enabled color drawbuffers.
946e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * The 'span' parameter can be considered to be const.  Note that
9477956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
9487956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
94910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
95010f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
951cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_index_span( GLcontext *ctx, SWspan *span)
95210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
953e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
954e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
955e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
95610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
957733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
958b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
959b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
960733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
9617956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
9627956292a765910077f50352d7cd0174e1e66d26cBrian Paul
963733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
964733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
965733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
966733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
967733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
968a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
969733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
97010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
97110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
972733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
973b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
974733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
97586ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
976e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
977e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
978e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
979e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   /* Depth bounds test */
98031e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
981e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      if (!_swrast_depth_bounds_test(ctx, span)) {
982e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul         return;
983e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      }
984e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   }
985e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul
986b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
987a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
988b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
989a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
990b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
99177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
99277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
99377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
99477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
99577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
996b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
997b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
998b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
999b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1000b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
1001e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
1002b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
100310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
1004e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1005e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1006e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   /* Stencil and Z testing */
10077956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
10087956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (span->interpMask & SPAN_Z)
100945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
101010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
10117956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
101245bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
10137956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
10147956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
10157956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
10162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
10177956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
10187956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
101945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
1020e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            span->interpMask = origInterpMask;
10217956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
10227956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
10237956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
10242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
102510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
102610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1027b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
102823ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1029939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
103023ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1031b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1032b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
103323ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1034b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1035b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
1036b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
10377956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
10387956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
103910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
10402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
104110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
104210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
104310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
10447956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
1045dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled ||
1046e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexLogicOpEnabled ||
1047e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexMask != 0xffffffff ||
1048e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       (span->arrayMask & SPAN_COVERAGE)) {
1049e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (span->interpMask & SPAN_INDEX) {
1050e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         interpolate_indexes(ctx, span);
1051e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
10527956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
105310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
10547956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
1055dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled) {
105645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_ci_span(ctx, span);
1057e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1058e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
10592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
10602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1061e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      const GLfloat *coverage = span->array->coverage;
106277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLuint *index = span->array->index;
1063e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLuint i;
106410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
106577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         ASSERT(coverage[i] < 16);
106677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
10675071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
10682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
10695071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
1070ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
1071ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
1072ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
1073ba001224a18fa12792696ef393e708e90092127eBrian Paul   {
1074ba001224a18fa12792696ef393e708e90092127eBrian Paul      struct gl_framebuffer *fb = ctx->DrawBuffer;
1075a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      const GLuint output = 0; /* only frag progs can write to other outputs */
1076ba001224a18fa12792696ef393e708e90092127eBrian Paul      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1077ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint indexSave[MAX_WIDTH];
1078ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint buf;
1079e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1080ba001224a18fa12792696ef393e708e90092127eBrian Paul      if (numDrawBuffers > 1) {
1081ba001224a18fa12792696ef393e708e90092127eBrian Paul         /* save indexes for second, third renderbuffer writes */
1082ba001224a18fa12792696ef393e708e90092127eBrian Paul         _mesa_memcpy(indexSave, span->array->index,
1083ba001224a18fa12792696ef393e708e90092127eBrian Paul                      span->end * sizeof(indexSave[0]));
1084ba001224a18fa12792696ef393e708e90092127eBrian Paul      }
1085e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1086ba001224a18fa12792696ef393e708e90092127eBrian Paul      for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
1087ba001224a18fa12792696ef393e708e90092127eBrian Paul         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1088ba001224a18fa12792696ef393e708e90092127eBrian Paul         ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
10892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1090e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexLogicOpEnabled) {
1091f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_logicop_ci_span(ctx, rb, span);
1092e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1093e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1094e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
1095f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_mask_ci_span(ctx, rb, span);
1096e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
10972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1098ba001224a18fa12792696ef393e708e90092127eBrian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
1099ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* all fragments have same color index */
1100ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8;
1101ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16;
1102ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLuint index32;
1103ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *value;
1104e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1105ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
1106ba001224a18fa12792696ef393e708e90092127eBrian Paul               index8 = FixedToInt(span->index);
1107ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index8;
1108ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1109ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1110ba001224a18fa12792696ef393e708e90092127eBrian Paul               index16 = FixedToInt(span->index);
1111ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index16;
1112ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1113ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1114ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1115ba001224a18fa12792696ef393e708e90092127eBrian Paul               index32 = FixedToInt(span->index);
1116ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index32;
1117ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1118e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1119ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
1120ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoValues(ctx, rb, span->end, span->array->x,
1121ba001224a18fa12792696ef393e708e90092127eBrian Paul                                 span->array->y, value, span->array->mask);
1122e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
1123ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1124ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
1125ba001224a18fa12792696ef393e708e90092127eBrian Paul                              value, span->array->mask);
1126e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
1127733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1128733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
1129ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* each fragment is a different color */
1130ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8[MAX_WIDTH];
1131ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16[MAX_WIDTH];
1132ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *values;
1133ba001224a18fa12792696ef393e708e90092127eBrian Paul
1134ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
1135ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
1136ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
1137ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index8[k] = (GLubyte) span->array->index[k];
1138ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
1139ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index8;
1140ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1141ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1142ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
1143ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
1144ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index16[k] = (GLushort) span->array->index[k];
1145ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
1146ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index16;
1147ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1148ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1149ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1150ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = span->array->index;
1151ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1152e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1153ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
1154ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutValues(ctx, rb, span->end,
1155ba001224a18fa12792696ef393e708e90092127eBrian Paul                             span->array->x, span->array->y,
1156ba001224a18fa12792696ef393e708e90092127eBrian Paul                             values, span->array->mask);
1157ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1158ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1159ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutRow(ctx, rb, span->end, span->x, span->y,
1160e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                          values, span->array->mask);
1161ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1162e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1163ba001224a18fa12792696ef393e708e90092127eBrian Paul
1164ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (buf + 1 < numDrawBuffers) {
1165ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* restore original span values */
1166ba001224a18fa12792696ef393e708e90092127eBrian Paul            _mesa_memcpy(span->array->index, indexSave,
1167ba001224a18fa12792696ef393e708e90092127eBrian Paul                         span->end * sizeof(indexSave[0]));
1168733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1169ba001224a18fa12792696ef393e708e90092127eBrian Paul      } /* for buf */
1170e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
11712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
11727956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
11732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
1174e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1175e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1176e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
117779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1178e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color.  This is used only when
1179f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1180e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
1181f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1182cdb27e8242215271364602995d85607cfc06d441Brian Pauladd_specular(GLcontext *ctx, SWspan *span)
1183e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1184d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   switch (span->array->ChanType) {
1185d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_UNSIGNED_BYTE:
1186d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1187d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1188d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLubyte (*spec)[4] = span->array->color.sz1.spec;
1189d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1190d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1191d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1192d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1193d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1194d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1195d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] = MIN2(r, 255);
1196d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] = MIN2(g, 255);
1197d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] = MIN2(b, 255);
1198d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] = MIN2(a, 255);
1199d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1200d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1201d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1202d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_UNSIGNED_SHORT:
1203d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1204d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1205d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLushort (*spec)[4] = span->array->color.sz2.spec;
1206d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1207d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1208d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1209d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1210d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1211d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1212d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] = MIN2(r, 65535);
1213d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] = MIN2(g, 65535);
1214d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] = MIN2(b, 65535);
1215d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] = MIN2(a, 65535);
1216d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1217d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1218d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1219d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_FLOAT:
1220d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1221d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
1222d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLfloat (*spec)[4] = span->array->color.sz4.spec;
1223d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1224d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1225d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] += spec[i][RCOMP];
1226d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] += spec[i][GCOMP];
1227d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] += spec[i][BCOMP];
1228d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] += spec[i][ACOMP];
1229d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1230d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1231d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1232d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   default:
1233d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      _mesa_problem(ctx, "Invalid datatype in add_specular");
1234e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1235e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1236e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1237e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
123879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1239b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul * Apply antialiasing coverage value to alpha values.
1240b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul */
1241f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1242b88af5b4681d2085cd784b930dc259b66a55347eBrian Paulapply_aa_coverage(SWspan *span)
1243b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul{
1244b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   const GLfloat *coverage = span->array->coverage;
1245b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   GLuint i;
1246b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1247b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1248b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1249e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1250e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
1251b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] >= 0.0);
1252b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] <= 1.0);
1253b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1254b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1255b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1256b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1257b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1258e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1259e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
1260b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1261b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1262b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else {
1263b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
1264b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1265b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
1266b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1267b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1268b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul}
1269b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
1270b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
1271b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul/**
127231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul * Clamp span's float colors to [0,1]
127331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul */
1274f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
127531293910b4e982f2ef54d79aff78f2f854121da1Brian Paulclamp_colors(SWspan *span)
127631293910b4e982f2ef54d79aff78f2f854121da1Brian Paul{
127731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
127831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   GLuint i;
127931293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->array->ChanType == GL_FLOAT);
128031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   for (i = 0; i < span->end; i++) {
128131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
128231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
128331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
128431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
128531293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   }
128631293910b4e982f2ef54d79aff78f2f854121da1Brian Paul}
128731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
128831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
128931293910b4e982f2ef54d79aff78f2f854121da1Brian Paul/**
1290d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul * Convert the span's color arrays to the given type.
1291d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
1292f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1293cdb27e8242215271364602995d85607cfc06d441Brian Paulconvert_color_type(GLcontext *ctx, SWspan *span, GLenum newType)
1294d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul{
1295f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   GLvoid *src, *dst;
1296f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1297f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz1.rgba;
1298f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1299f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1300f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz2.rgba;
1301f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1302f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
1303f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz4.rgba;
1304f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1305f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (newType == GL_UNSIGNED_BYTE) {
1306f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz1.rgba;
1307f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1308f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (newType == GL_UNSIGNED_BYTE) {
1309f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz2.rgba;
1310f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1311f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
1312f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz4.rgba;
1313f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1314d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1315f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   _mesa_convert_colors(span->array->ChanType, src,
1316f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        newType, dst,
1317f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        span->end, span->array->mask);
1318d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1319d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   span->array->ChanType = newType;
1320d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul}
1321d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1322d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1323d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1324d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
132561c89be3135cedc795e48d36283769298e250837Brian Paul * Apply fragment shader, fragment program or normal texturing to span.
132661c89be3135cedc795e48d36283769298e250837Brian Paul */
1327f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
132861c89be3135cedc795e48d36283769298e250837Brian Paulshade_texture_span(GLcontext *ctx, SWspan *span)
132961c89be3135cedc795e48d36283769298e250837Brian Paul{
133061c89be3135cedc795e48d36283769298e250837Brian Paul   /* Now we need the rgba array, fill it in if needed */
133161c89be3135cedc795e48d36283769298e250837Brian Paul   if (span->interpMask & SPAN_RGBA)
133261c89be3135cedc795e48d36283769298e250837Brian Paul      interpolate_colors(span);
133361c89be3135cedc795e48d36283769298e250837Brian Paul
1334f614a6190562e550257afca0d04e3846648942e8Brian Paul   if (ctx->Texture._EnabledCoordUnits && (span->interpMask & SPAN_TEXTURE))
1335f614a6190562e550257afca0d04e3846648942e8Brian Paul      interpolate_texcoords(ctx, span);
1336f614a6190562e550257afca0d04e3846648942e8Brian Paul
133761c89be3135cedc795e48d36283769298e250837Brian Paul   if (ctx->ShaderObjects._FragmentShaderPresent ||
133861c89be3135cedc795e48d36283769298e250837Brian Paul       ctx->FragmentProgram._Enabled ||
133961c89be3135cedc795e48d36283769298e250837Brian Paul       ctx->ATIFragmentShader._Enabled) {
134061c89be3135cedc795e48d36283769298e250837Brian Paul
134161c89be3135cedc795e48d36283769298e250837Brian Paul      /* use float colors if running a fragment program or shader */
134261c89be3135cedc795e48d36283769298e250837Brian Paul      const GLenum oldType = span->array->ChanType;
134361c89be3135cedc795e48d36283769298e250837Brian Paul      const GLenum newType = GL_FLOAT;
134461c89be3135cedc795e48d36283769298e250837Brian Paul      if (oldType != newType) {
134561c89be3135cedc795e48d36283769298e250837Brian Paul         GLvoid *src = (oldType == GL_UNSIGNED_BYTE)
134661c89be3135cedc795e48d36283769298e250837Brian Paul            ? (GLvoid *) span->array->color.sz1.rgba
134761c89be3135cedc795e48d36283769298e250837Brian Paul            : (GLvoid *) span->array->color.sz2.rgba;
134861c89be3135cedc795e48d36283769298e250837Brian Paul         _mesa_convert_colors(oldType, src,
134961c89be3135cedc795e48d36283769298e250837Brian Paul                              newType, span->array->color.sz4.rgba,
135061c89be3135cedc795e48d36283769298e250837Brian Paul                              span->end, span->array->mask);
135161c89be3135cedc795e48d36283769298e250837Brian Paul         span->array->ChanType = newType;
135261c89be3135cedc795e48d36283769298e250837Brian Paul      }
135361c89be3135cedc795e48d36283769298e250837Brian Paul
135461c89be3135cedc795e48d36283769298e250837Brian Paul      /* fragment programs/shaders may need specular, fog and Z coords */
135561c89be3135cedc795e48d36283769298e250837Brian Paul      if (span->interpMask & SPAN_SPEC)
135661c89be3135cedc795e48d36283769298e250837Brian Paul         interpolate_specular(span);
135761c89be3135cedc795e48d36283769298e250837Brian Paul
135861c89be3135cedc795e48d36283769298e250837Brian Paul      if (span->interpMask & SPAN_FOG)
135961c89be3135cedc795e48d36283769298e250837Brian Paul         interpolate_fog(ctx, span);
136061c89be3135cedc795e48d36283769298e250837Brian Paul
136161c89be3135cedc795e48d36283769298e250837Brian Paul      if (span->interpMask & SPAN_Z)
136261c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_span_interpolate_z (ctx, span);
136361c89be3135cedc795e48d36283769298e250837Brian Paul
136461c89be3135cedc795e48d36283769298e250837Brian Paul      /* Run fragment program/shader now */
136561c89be3135cedc795e48d36283769298e250837Brian Paul      if (ctx->ShaderObjects._FragmentShaderPresent) {
1366828d15a6e0907fe4bb7c564d453a2b1a05f109bcBrian Paul         interpolate_varying(ctx, span);
1367828d15a6e0907fe4bb7c564d453a2b1a05f109bcBrian Paul         _swrast_exec_arbshader(ctx, span);
136861c89be3135cedc795e48d36283769298e250837Brian Paul      }
136961c89be3135cedc795e48d36283769298e250837Brian Paul      else if (ctx->FragmentProgram._Enabled) {
137061c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_program(ctx, span);
137161c89be3135cedc795e48d36283769298e250837Brian Paul      }
137261c89be3135cedc795e48d36283769298e250837Brian Paul      else {
137361c89be3135cedc795e48d36283769298e250837Brian Paul         ASSERT(ctx->ATIFragmentShader._Enabled);
137461c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_shader(ctx, span);
137561c89be3135cedc795e48d36283769298e250837Brian Paul      }
137661c89be3135cedc795e48d36283769298e250837Brian Paul   }
137761c89be3135cedc795e48d36283769298e250837Brian Paul   else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE)) {
137861c89be3135cedc795e48d36283769298e250837Brian Paul      /* conventional texturing */
137961c89be3135cedc795e48d36283769298e250837Brian Paul      _swrast_texture_span(ctx, span);
138061c89be3135cedc795e48d36283769298e250837Brian Paul   }
138161c89be3135cedc795e48d36283769298e250837Brian Paul}
138261c89be3135cedc795e48d36283769298e250837Brian Paul
138361c89be3135cedc795e48d36283769298e250837Brian Paul
138461c89be3135cedc795e48d36283769298e250837Brian Paul
138561c89be3135cedc795e48d36283769298e250837Brian Paul/**
1386a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Apply all the per-fragment operations to a span.
1387a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * This now includes texturing (_swrast_write_texture_span() is history).
1388f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
13897956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
13907956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
139178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
139278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
1393cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
139478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
139561c89be3135cedc795e48d36283769298e250837Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
139678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1397e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
1398e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
1399c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul   const GLenum chanType = span->array->ChanType;
140061c89be3135cedc795e48d36283769298e250837Brian Paul   const GLboolean shader
140161c89be3135cedc795e48d36283769298e250837Brian Paul      = ctx->FragmentProgram._Enabled
140261c89be3135cedc795e48d36283769298e250837Brian Paul      || ctx->ShaderObjects._FragmentShaderPresent
140361c89be3135cedc795e48d36283769298e250837Brian Paul      || ctx->ATIFragmentShader._Enabled;
140461c89be3135cedc795e48d36283769298e250837Brian Paul   const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
1405bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   GLboolean deferredTexture;
140661c89be3135cedc795e48d36283769298e250837Brian Paul
1407bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /*
1408bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1409bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul          span->interpMask, span->arrayMask);
1410bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   */
1411f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
141231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->primitive == GL_POINT ||
141331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_LINE ||
141431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul	  span->primitive == GL_POLYGON ||
141531293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_BITMAP);
1416733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
14177956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
141831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT((span->interpMask & SPAN_RGBA) ^ (span->arrayMask & SPAN_RGBA));
141978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1420bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /* check for conditions that prevent deferred shading */
1421bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   if (ctx->Color.AlphaEnabled) {
1422bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      /* alpha test depends on post-texture/shader colors */
1423bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      deferredTexture = GL_FALSE;
1424bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   }
1425bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   else if (shaderOrTexture) {
1426bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      if (ctx->FragmentProgram._Enabled &&
1427bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul          (ctx->FragmentProgram.Current->Base.OutputsWritten
1428bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul           & (1 << FRAG_RESULT_DEPR))) {
1429bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         /* Z comes from fragment program */
1430bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         deferredTexture = GL_FALSE;
1431bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      }
1432bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      else if (ctx->ShaderObjects._FragmentShaderPresent) {
1433bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         /* XXX how do we test if Z is written by shader? */
1434bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         deferredTexture = GL_FALSE; /* never defer to be safe */
1435bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      }
1436bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      else {
1437bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         /* ATI frag shader or conventional texturing */
1438bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         deferredTexture = GL_TRUE;
1439bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      }
1440bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   }
1441bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   else {
1442bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      /* no texturing or shadering */
1443bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      deferredTexture = GL_FALSE;
1444bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   }
1445ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1446bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /* Fragment write masks */
1447733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1448733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1449733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1450733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1451733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
1452a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
1453733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
145478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
145578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1456a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Clip to window/scissor box */
1457b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1458733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1459733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
146078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
146178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
146278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1463b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1464a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
1465b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1466a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
1467b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
146877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
146977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
147077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
147177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
147277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1473b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1474b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1475b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1476b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1477b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
147878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1479b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1480733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
148178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
148278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
148332340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* This is the normal place to compute the resulting fragment color/Z.
148432340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * As an optimization, we try to defer this until after Z/stencil
148532340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * testing in order to try to avoid computing colors that we won't
148632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * actually need.
1487a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
148861c89be3135cedc795e48d36283769298e250837Brian Paul   if (shaderOrTexture && !deferredTexture) {
148961c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
149061c89be3135cedc795e48d36283769298e250837Brian Paul   }
1491c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul
149261c89be3135cedc795e48d36283769298e250837Brian Paul   /* Do the alpha test */
149361c89be3135cedc795e48d36283769298e250837Brian Paul   if (ctx->Color.AlphaEnabled) {
149461c89be3135cedc795e48d36283769298e250837Brian Paul      if (!_swrast_alpha_test(ctx, span)) {
149561c89be3135cedc795e48d36283769298e250837Brian Paul         goto end;
149678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
149778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
149878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1499f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1500f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1501f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
150245bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
150378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1504e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1505a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Combined Z/stencil tests */
150645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1507c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1508f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
150971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1510e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1511a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Just regular depth testing */
1512f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1513f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
151445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
1515c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1516f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
151771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
151871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
151971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1520b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
152123ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1522939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
152323ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1524b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1525b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
152623ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1527b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1528b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
1529b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
1530a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1531f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1532f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1533f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1534c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul      goto end;
153571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
153671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
153732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* If we were able to defer fragment color computation to now, there's
153832340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * a good chance that many fragments will have already been killed by
153932340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * Z/stencil testing.
1540a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
154132340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   if (deferredTexture) {
154261c89be3135cedc795e48d36283769298e250837Brian Paul      ASSERT(shaderOrTexture);
154361c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
154461c89be3135cedc795e48d36283769298e250837Brian Paul   }
1545d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
154661c89be3135cedc795e48d36283769298e250837Brian Paul   if ((span->arrayMask & SPAN_RGBA) == 0) {
154761c89be3135cedc795e48d36283769298e250837Brian Paul      interpolate_colors(span);
154871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
154971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1550f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
15512ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
155261c89be3135cedc795e48d36283769298e250837Brian Paul   if (!shader) {
1553dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      /* Add base and specular colors */
1554dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      if (ctx->Fog.ColorSumEnabled ||
1555dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul          (ctx->Light.Enabled &&
1556dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1557dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         if (span->interpMask & SPAN_SPEC) {
1558e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            interpolate_specular(span);
1559dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         }
1560a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         if (span->arrayMask & SPAN_SPEC) {
1561d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            add_specular(ctx, span);
1562a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
1563a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         else {
1564a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul            /* We probably added the base/specular colors during the
1565a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             * vertex stage!
1566a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             */
1567a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
156871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
156971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
157071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
15716e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
157209da0b8e6621a831e3eeb9381430f2bed18a22adBrian Paul   if (swrast->_FogEnabled) {
157345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_rgba_span(ctx, span);
157471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1575f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
157671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
15772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1578b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      apply_aa_coverage(span);
157971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
158071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1581ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
158231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   if (ctx->Color.ClampFragmentColor &&
158331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul       span->array->ChanType == GL_FLOAT) {
158431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      clamp_colors(span);
1585ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   }
1586ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul
1587ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
1588ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
1589ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
1590ba001224a18fa12792696ef393e708e90092127eBrian Paul   {
1591ba001224a18fa12792696ef393e708e90092127eBrian Paul      struct gl_framebuffer *fb = ctx->DrawBuffer;
1592a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      const GLuint output = 0; /* only frag progs can write to other outputs */
1593ba001224a18fa12792696ef393e708e90092127eBrian Paul      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1594ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLchan rgbaSave[MAX_WIDTH][4];
1595ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint buf;
1596e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1597d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      if (numDrawBuffers > 0) {
1598d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         if (fb->_ColorDrawBuffers[output][0]->DataType
1599d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul             != span->array->ChanType) {
1600d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            convert_color_type(ctx, span,
1601d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul                               fb->_ColorDrawBuffers[output][0]->DataType);
1602d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1603d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1604d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1605ba001224a18fa12792696ef393e708e90092127eBrian Paul      if (numDrawBuffers > 1) {
1606ba001224a18fa12792696ef393e708e90092127eBrian Paul         /* save colors for second, third renderbuffer writes */
1607ba001224a18fa12792696ef393e708e90092127eBrian Paul         _mesa_memcpy(rgbaSave, span->array->rgba,
1608ba001224a18fa12792696ef393e708e90092127eBrian Paul                      4 * span->end * sizeof(GLchan));
160971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
161071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1611ba001224a18fa12792696ef393e708e90092127eBrian Paul      for (buf = 0; buf < numDrawBuffers; buf++) {
1612ba001224a18fa12792696ef393e708e90092127eBrian Paul         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1613f971e24cf0341dd2779196a0836327b74fc82336Brian Paul         ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
161471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1615ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (ctx->Color._LogicOpEnabled) {
1616f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_logicop_rgba_span(ctx, rb, span);
1617ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1618ba001224a18fa12792696ef393e708e90092127eBrian Paul         else if (ctx->Color.BlendEnabled) {
1619f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_blend_span(ctx, rb, span);
1620ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1621ba001224a18fa12792696ef393e708e90092127eBrian Paul
1622ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (colorMask != 0xffffffff) {
1623f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_mask_rgba_span(ctx, rb, span);
1624ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1625ba001224a18fa12792696ef393e708e90092127eBrian Paul
1626ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (span->arrayMask & SPAN_XY) {
1627ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* array of pixel coords */
1628ba001224a18fa12792696ef393e708e90092127eBrian Paul            ASSERT(rb->PutValues);
1629ba001224a18fa12792696ef393e708e90092127eBrian Paul            rb->PutValues(ctx, rb, span->end,
1630ba001224a18fa12792696ef393e708e90092127eBrian Paul                          span->array->x, span->array->y,
1631ba001224a18fa12792696ef393e708e90092127eBrian Paul                          span->array->rgba, span->array->mask);
1632ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1633ba001224a18fa12792696ef393e708e90092127eBrian Paul         else {
1634ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* horizontal run of pixels */
1635ba001224a18fa12792696ef393e708e90092127eBrian Paul            ASSERT(rb->PutRow);
1636ba001224a18fa12792696ef393e708e90092127eBrian Paul            rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1637ba001224a18fa12792696ef393e708e90092127eBrian Paul                       span->writeAll ? NULL: span->array->mask);
1638ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1639ba001224a18fa12792696ef393e708e90092127eBrian Paul
1640ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (buf + 1 < numDrawBuffers) {
1641ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* restore original span values */
1642ba001224a18fa12792696ef393e708e90092127eBrian Paul            _mesa_memcpy(span->array->rgba, rgbaSave,
1643ba001224a18fa12792696ef393e708e90092127eBrian Paul                         4 * span->end * sizeof(GLchan));
1644ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1645ba001224a18fa12792696ef393e708e90092127eBrian Paul      } /* for buf */
16461e3223c02a2f6155beb5784cadbea1f46703829aBrian Paul
164771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
164871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1649c3caaa3dd45809e672177ab322445fe51d03af25Brian Paulend:
165061c89be3135cedc795e48d36283769298e250837Brian Paul   /* restore these values before returning */
1651e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   span->interpMask = origInterpMask;
1652f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
165361c89be3135cedc795e48d36283769298e250837Brian Paul   span->array->ChanType = chanType;
165410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
165510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1656e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
165779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1658e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
1659e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
166076e778dce59aa6f290db50242df945943fc47b05Brian Paul * \param type  datatype for returned colors
166176e778dce59aa6f290db50242df945943fc47b05Brian Paul * \param rgba  the returned colors
1662e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
16635071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1664e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
166576e778dce59aa6f290db50242df945943fc47b05Brian Paul                        GLuint n, GLint x, GLint y, GLenum dstType,
166676e778dce59aa6f290db50242df945943fc47b05Brian Paul                        GLvoid *rgba)
1667e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1668e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1669e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1670a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1671a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1672e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1673e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* XXX maybe leave rgba values undefined? */
16746ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul      _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1675e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1676e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1677e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1678e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
16797e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1680e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1681e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1682e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1683e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1684e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1685e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1686a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1687a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1688e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1689e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1690a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1691e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1692e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1693a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1694e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1695e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1696e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1697e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1698e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1699e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1700e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1701e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1702e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1703e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1704e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1705bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb);
1706bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->GetRow);
1707bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
170876e778dce59aa6f290db50242df945943fc47b05Brian Paul
170976e778dce59aa6f290db50242df945943fc47b05Brian Paul      if (rb->DataType == dstType) {
171076e778dce59aa6f290db50242df945943fc47b05Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y,
171176e778dce59aa6f290db50242df945943fc47b05Brian Paul                    (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
171276e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
171376e778dce59aa6f290db50242df945943fc47b05Brian Paul      else {
171476e778dce59aa6f290db50242df945943fc47b05Brian Paul         GLuint temp[MAX_WIDTH * 4];
171576e778dce59aa6f290db50242df945943fc47b05Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, temp);
171676e778dce59aa6f290db50242df945943fc47b05Brian Paul         _mesa_convert_colors(rb->DataType, temp,
171776e778dce59aa6f290db50242df945943fc47b05Brian Paul                   dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
171876e778dce59aa6f290db50242df945943fc47b05Brian Paul                   length, NULL);
171976e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
1720e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1721e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1722e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1723e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
172479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1725e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read CI pixels from frame buffer.  Clipping will be done to prevent
1726e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1727e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
17285071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1729e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1730e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                         GLuint n, GLint x, GLint y, GLuint index[] )
1731e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1732e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1733e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1734a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1735a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1736e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1737e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      _mesa_bzero(index, n * sizeof(GLuint));
1738e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1739e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1740e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1741e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
17427e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1743e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1744e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1745e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1746e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1747e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1748e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1749a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1750a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1751e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1752e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1753a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1754e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1755e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1756a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1757e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1758e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1759e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1760e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1761e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1762e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1763e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1764e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1765e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1766e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1767e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1768e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->GetRow);
1769e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1770e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1771e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (rb->DataType == GL_UNSIGNED_BYTE) {
1772e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLubyte index8[MAX_WIDTH];
1773e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1774e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index8);
1775e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1776e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index8[i];
1777e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1778e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_SHORT) {
1779e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLushort index16[MAX_WIDTH];
1780e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1781e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index16);
1782e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1783e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index16[i];
1784e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1785e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_INT) {
1786e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1787e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1788e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1789e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
179067074332728acba86da7630353673b458713bb8aBrian Paul
179167074332728acba86da7630353673b458713bb8aBrian Paul
179267074332728acba86da7630353673b458713bb8aBrian Paul/**
179367074332728acba86da7630353673b458713bb8aBrian Paul * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
179467074332728acba86da7630353673b458713bb8aBrian Paul * reading values outside the buffer bounds.
179567074332728acba86da7630353673b458713bb8aBrian Paul * We can use this for reading any format/type of renderbuffer.
1796ba001224a18fa12792696ef393e708e90092127eBrian Paul * \param valueSize is the size in bytes of each value (pixel) put into the
179767074332728acba86da7630353673b458713bb8aBrian Paul *                  values array.
179867074332728acba86da7630353673b458713bb8aBrian Paul */
179967074332728acba86da7630353673b458713bb8aBrian Paulvoid
180067074332728acba86da7630353673b458713bb8aBrian Paul_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
180167074332728acba86da7630353673b458713bb8aBrian Paul                   GLuint count, const GLint x[], const GLint y[],
180267074332728acba86da7630353673b458713bb8aBrian Paul                   void *values, GLuint valueSize)
180367074332728acba86da7630353673b458713bb8aBrian Paul{
180467074332728acba86da7630353673b458713bb8aBrian Paul   GLuint i, inCount = 0, inStart = 0;
180567074332728acba86da7630353673b458713bb8aBrian Paul
180667074332728acba86da7630353673b458713bb8aBrian Paul   for (i = 0; i < count; i++) {
180767074332728acba86da7630353673b458713bb8aBrian Paul      if (x[i] >= 0 && y[i] >= 0 && x[i] < rb->Width && y[i] < rb->Height) {
180867074332728acba86da7630353673b458713bb8aBrian Paul         /* inside */
180967074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount == 0)
181067074332728acba86da7630353673b458713bb8aBrian Paul            inStart = i;
181167074332728acba86da7630353673b458713bb8aBrian Paul         inCount++;
181267074332728acba86da7630353673b458713bb8aBrian Paul      }
181367074332728acba86da7630353673b458713bb8aBrian Paul      else {
181467074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount > 0) {
181567074332728acba86da7630353673b458713bb8aBrian Paul            /* read [inStart, inStart + inCount) */
181667074332728acba86da7630353673b458713bb8aBrian Paul            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
181767074332728acba86da7630353673b458713bb8aBrian Paul                          (GLubyte *) values + inStart * valueSize);
181867074332728acba86da7630353673b458713bb8aBrian Paul            inCount = 0;
181967074332728acba86da7630353673b458713bb8aBrian Paul         }
182067074332728acba86da7630353673b458713bb8aBrian Paul      }
182167074332728acba86da7630353673b458713bb8aBrian Paul   }
182267074332728acba86da7630353673b458713bb8aBrian Paul   if (inCount > 0) {
182367074332728acba86da7630353673b458713bb8aBrian Paul      /* read last values */
182467074332728acba86da7630353673b458713bb8aBrian Paul      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
182567074332728acba86da7630353673b458713bb8aBrian Paul                    (GLubyte *) values + inStart * valueSize);
182667074332728acba86da7630353673b458713bb8aBrian Paul   }
182767074332728acba86da7630353673b458713bb8aBrian Paul}
18283fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
18293fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
18303fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul/**
18313fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1832a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
18333fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul */
18343fd819aef8139761ce86cb8d763de83a11c81b33Brian Paulvoid
18353fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
18363fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                GLuint count, GLint x, GLint y,
18373fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                const GLvoid *values, GLuint valueSize)
18383fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul{
18393fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   GLint skip = 0;
18403fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
18413fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (y < 0 || y >= rb->Height)
18423fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* above or below */
18433fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
18443fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x + (GLint) count <= 0 || x >= rb->Width)
18453fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* entirely left or right */
18463fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
18473fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x + count > rb->Width) {
18483fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* right clip */
18493fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      GLint clip = x + count - rb->Width;
18503fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= clip;
18513fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
18523fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
18533fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x < 0) {
18543fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* left clip */
18553fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      skip = -x;
18563fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      x = 0;
18573fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= skip;
18583fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
18593fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
18603fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   rb->PutRow(ctx, rb, count, x, y,
18613fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul              (const GLubyte *) values + skip * valueSize, NULL);
18623fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul}
1863f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1864f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1865f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul/**
1866f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1867a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
1868f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul */
1869f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paulvoid
1870f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1871f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLuint count, GLint x, GLint y,
1872f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLvoid *values, GLuint valueSize)
1873f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul{
1874f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   GLint skip = 0;
1875f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1876f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (y < 0 || y >= rb->Height)
1877f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* above or below */
1878f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1879f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + (GLint) count <= 0 || x >= rb->Width)
1880f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* entirely left or right */
1881f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1882f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + count > rb->Width) {
1883f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* right clip */
1884f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      GLint clip = x + count - rb->Width;
1885f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= clip;
1886f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1887f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1888f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x < 0) {
1889f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* left clip */
1890f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      skip = -x;
1891f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      x = 0;
1892f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= skip;
1893f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1894f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1895f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1896f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul}
1897a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1898a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1899a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul/**
1900a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Get RGBA pixels from the given renderbuffer.  Put the pixel colors into
1901a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * the span's specular color arrays.  The specular color arrays should no
1902a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * longer be needed by time this function is called.
1903a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Used by blending, logicop and masking functions.
1904a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \return pointer to the colors we read.
1905a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul */
1906a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paulvoid *
1907a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1908cdb27e8242215271364602995d85607cfc06d441Brian Paul                      SWspan *span)
1909a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul{
191076e778dce59aa6f290db50242df945943fc47b05Brian Paul   const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1911a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   void *rbPixels;
1912a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1913a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /*
1914a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    * Determine pixel size (in bytes).
1915a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    * Point rbPixels to a temporary space (use specular color arrays).
1916a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    */
1917a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1918a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz1.spec;
1919a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1920a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1921a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz2.spec;
1922a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1923a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1924a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz4.spec;
1925a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1926a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1927a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /* Get destination values from renderbuffer */
1928a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->arrayMask & SPAN_XY) {
1929a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1930a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                         rbPixels, pixelSize);
1931a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1932a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1933a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1934a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                      rbPixels, pixelSize);
1935a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1936a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1937a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   return rbPixels;
1938a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul}
1939