s_span.c revision f971e24cf0341dd2779196a0836327b74fc82336
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/**
154d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul * Interpolate colors to fill in the span->array->color array.
155d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul * \param specular  if true, interpolate specular, else interpolate rgba.
156d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
1572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
158cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_colors(GLcontext *ctx, SWspan *span, GLboolean specular)
1592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
1612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
162a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
1632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
164d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   if (!specular) {
165d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      ASSERT((span->interpMask & SPAN_RGBA)  &&
166d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul             !(span->arrayMask & SPAN_RGBA));
167d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   }
1682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
1702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
171d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      switch (span->array->ChanType) {
172d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      case GL_UNSIGNED_BYTE:
173d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         {
174d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLubyte (*rgba)[4] = specular
175d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               ? span->array->color.sz1.spec : span->array->color.sz1.rgba;
176d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLubyte color[4];
177d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            if (specular) {
178d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[RCOMP] = FixedToInt(span->specRed);
179d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[GCOMP] = FixedToInt(span->specGreen);
180d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[BCOMP] = FixedToInt(span->specBlue);
181d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[ACOMP] = 0;
182d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
183d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            else {
184d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[RCOMP] = FixedToInt(span->red);
185d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[GCOMP] = FixedToInt(span->green);
186d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[BCOMP] = FixedToInt(span->blue);
187d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[ACOMP] = FixedToInt(span->alpha);
188d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
189d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
190d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4UBV(rgba[i], color);
191d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
192d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
193d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         break;
194d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      case GL_UNSIGNED_SHORT:
195d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         {
196d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLushort (*rgba)[4] = specular
197d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               ? span->array->color.sz2.spec : span->array->color.sz2.rgba;
198d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLushort color[4];
199d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            if (specular) {
200d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[RCOMP] = FixedToInt(span->specRed);
201d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[GCOMP] = FixedToInt(span->specGreen);
202d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[BCOMP] = FixedToInt(span->specBlue);
203d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[ACOMP] = 0;
204d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
205d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            else {
206d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[RCOMP] = FixedToInt(span->red);
207d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[GCOMP] = FixedToInt(span->green);
208d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[BCOMP] = FixedToInt(span->blue);
209d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[ACOMP] = FixedToInt(span->alpha);
210d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
211d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
212d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4V(rgba[i], color);
213d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
214d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
215d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         break;
216d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      case GL_FLOAT:
217d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         {
218d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfloat (*rgba)[4] = specular ?
219d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               span->array->color.sz4.spec : span->array->color.sz4.rgba;
220d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfloat color[4];
221d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            ASSERT(CHAN_TYPE == GL_FLOAT);
222d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            if (specular) {
223d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[RCOMP] = span->specRed;
224d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[GCOMP] = span->specGreen;
225d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[BCOMP] = span->specBlue;
226d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[ACOMP] = 0.0F;
227d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
228d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            else {
229d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[RCOMP] = span->red;
230d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[GCOMP] = span->green;
231d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[BCOMP] = span->blue;
232d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               color[ACOMP] = span->alpha;
233d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
234d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
235d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4V(rgba[i], color);
236d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
237d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
238d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         break;
239d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      default:
240d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         _mesa_problem(ctx, "bad datatype in interpolate_colors");
2412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
245d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      switch (span->array->ChanType) {
246d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      case GL_UNSIGNED_BYTE:
247d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         {
248d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLubyte (*rgba)[4] = specular
249d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               ? span->array->color.sz1.spec : span->array->color.sz1.rgba;
250d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfixed r, g, b, a;
251d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint dr, dg, db, da;
252d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            if (specular) {
253d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r = span->specRed;
254d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g = span->specGreen;
255d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b = span->specBlue;
256d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a = 0;
257d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dr = span->specRedStep;
258d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dg = span->specGreenStep;
259d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               db = span->specBlueStep;
260d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               da = 0;
261d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
262d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            else {
263d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r = span->red;
264d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g = span->green;
265d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b = span->blue;
266d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a = span->alpha;
267d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dr = span->redStep;
268d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dg = span->greenStep;
269d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               db = span->blueStep;
270d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               da = span->alphaStep;
271d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
272d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
273d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][RCOMP] = FixedToChan(r);
274d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][GCOMP] = FixedToChan(g);
275d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][BCOMP] = FixedToChan(b);
276d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][ACOMP] = FixedToChan(a);
277d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
278d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
279d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
280d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a += da;
281d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
282d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
283d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         break;
284d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      case GL_UNSIGNED_SHORT:
285d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         {
286d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLushort (*rgba)[4] = specular
287d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               ? span->array->color.sz2.spec : span->array->color.sz2.rgba;
288d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfixed r, g, b, a;
289d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint dr, dg, db, da;
290d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            if (specular) {
291d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r = span->specRed;
292d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g = span->specGreen;
293d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b = span->specBlue;
294d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a = 0;
295d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dr = span->specRedStep;
296d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dg = span->specGreenStep;
297d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               db = span->specBlueStep;
298d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               da = 0;
299d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
300d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            else {
301d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r = span->red;
302d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g = span->green;
303d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b = span->blue;
304d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a = span->alpha;
305d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dr = span->redStep;
306d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dg = span->greenStep;
307d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               db = span->blueStep;
308d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               da = span->alphaStep;
309d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
310d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
311d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][RCOMP] = FixedToChan(r);
312d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][GCOMP] = FixedToChan(g);
313d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][BCOMP] = FixedToChan(b);
314d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][ACOMP] = FixedToChan(a);
315d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
316d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
317d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
318d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a += da;
319d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
320d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
321d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         break;
322d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      case GL_FLOAT:
323d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         {
324d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfloat (*rgba)[4] = specular ?
325d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               span->array->color.sz4.spec : span->array->color.sz4.rgba;
326d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfloat r, g, b, a, dr, dg, db, da;
327d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            if (specular) {
328d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r = span->specRed;
329d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g = span->specGreen;
330d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b = span->specBlue;
331d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a = 0.0F;
332d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dr = span->specRedStep;
333d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dg = span->specGreenStep;
334d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               db = span->specBlueStep;
335d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               da = 0.0F;
336d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
337d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            else {
338d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r = span->red;
339d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g = span->green;
340d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b = span->blue;
341d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a = span->alpha;
342d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dr = span->redStep;
343d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               dg = span->greenStep;
344d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               db = span->blueStep;
345d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               da = span->alphaStep;
346d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
347f971e24cf0341dd2779196a0836327b74fc82336Brian Paul            /*
348d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            ASSERT(CHAN_TYPE == GL_FLOAT);
349f971e24cf0341dd2779196a0836327b74fc82336Brian Paul            */
350d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
351d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][RCOMP] = r;
352d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][GCOMP] = g;
353d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][BCOMP] = b;
354d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][ACOMP] = a;
355d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
356d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
357d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
358d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a += da;
359d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
360d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
361d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         break;
362d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      default:
363d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         _mesa_problem(ctx, "bad datatype in interpolate_colors");
3642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
366d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   span->arrayMask |= (specular ? SPAN_SPEC : SPAN_RGBA);
3672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
3682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
3712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
372cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_indexes(GLcontext *ctx, SWspan *span)
3732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
3752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
3762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
37777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLuint *indexes = span->array->index;
3782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
379a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
380b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_INDEX)  &&
381b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_INDEX));
3822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
3842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
3852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
3862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
3872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
3882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
3902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
3912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
3922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
3932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
3942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
3972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
398e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   span->interpMask &= ~SPAN_INDEX;
3992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
402d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul/* Fill in the span.array.fog values from the interpolation values */
403d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paulstatic void
404cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_fog(const GLcontext *ctx, SWspan *span)
405d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul{
406d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat *fog = span->array->fog;
407d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLfloat fogStep = span->fogStep;
408d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat fogCoord = span->fog;
409d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLuint haveW = (span->interpMask & SPAN_W);
410d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLfloat wStep = haveW ? span->dwdx : 0.0F;
411d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLfloat w = haveW ? span->w : 1.0F;
412d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLuint i;
413d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   for (i = 0; i < span->end; i++) {
414d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      fog[i] = fogCoord / w;
415d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      fogCoord += fogStep;
416d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      w += wStep;
417d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   }
418d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   span->arrayMask |= SPAN_FOG;
419d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul}
420d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
421d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
4222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */
423711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
424cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
4252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
4262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
4272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
4282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
429b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_Z)  &&
430b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_Z));
4312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
43231e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16) {
4332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
4343e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
435ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      for (i = 0; i < n; i++) {
43677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = FixedToInt(zval);
4372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
4412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
4427265556b9aa0367e9b5031e7cb15ed2a5d73866dBrian Paul      GLuint zval = span->z;
4433e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
4442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
44577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = zval;
4462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
44932340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   span->interpMask &= ~SPAN_Z;
4502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
4512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
454c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
45531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
456c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
457c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
45831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
45931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
46031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
46131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
462c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
46331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
46431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
46531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
46631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
467f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
468f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
46931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
47031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
47131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
472c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
473c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
474c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
47531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
47631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/*
47731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This is a faster approximation
478c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
479350353adcd75f94fda63c787c86961716114e0bfBrian PaulGLfloat
48045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
481350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
482350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
483c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
48431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
48531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
48631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
48731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
48831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
48931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
49031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
49131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
49231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
49331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
49431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
49531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
49631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
49731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
498c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
499c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
500d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
501d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul/**
502c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Fill in the span.texcoords array from the interpolation values.
503d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * Note: in the places where we divide by Q (or mult by invQ) we're
504d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * really doing two things: perspective correction and texcoord
505d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * projection.  Remember, for texcoord (s,t,r,q) we need to index
506d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * texels with (s/q, t/q, r/q).
507d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * If we're using a fragment program, we never do the division
508d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * for texcoord projection.  That's done by the TXP instruction
509d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * or user-written code.
510c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
5112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
512cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_texcoords(GLcontext *ctx, SWspan *span)
5132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
5142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_TEXTURE);
515b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(!(span->arrayMask & SPAN_TEXTURE));
5162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
51736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul   if (ctx->Texture._EnabledCoordUnits > 1) {
51831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* multitexture */
51931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      GLuint u;
520b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
521ee4e75bd6f768b7210436feeb32b4545ed62e025Brian Paul      /* XXX CoordUnits vs. ImageUnits */
52231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
52336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
52431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
52536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            GLfloat texW, texH;
52636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            GLboolean needLambda;
52736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            if (obj) {
52818fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell               const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
52936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               needLambda = (obj->MinFilter != obj->MagFilter)
5307e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell                  || ctx->FragmentProgram._Enabled;
53136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texW = img->WidthScale;
53236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texH = img->HeightScale;
53336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            }
53436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            else {
535d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               /* using a fragment program */
53636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texW = 1.0;
53736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               texH = 1.0;
53836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul               needLambda = GL_FALSE;
53936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul            }
54031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            if (needLambda) {
54177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
54277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
54331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
54431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdy = span->texStepY[u][0];
54531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
54631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdy = span->texStepY[u][1];
54731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
54831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
54931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdy = span->texStepY[u][3];
5502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
5512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
5522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
5532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
5542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
5557e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell               if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
556bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol                   ctx->ShaderObjects._FragmentShaderPresent) {
557d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  /* do perspective correction but don't divide s, t, r by q */
558d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  const GLfloat dwdx = span->dwdx;
559d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  GLfloat w = span->w;
560d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
561d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invW = 1.0F / w;
562d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invW;
563d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invW;
564d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invW;
565d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q * invW;
566d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
567d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        dqdx, dqdy, texW, texH,
568d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        s, t, q, invW);
569d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
570d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
571d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
572d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
573d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     w += dwdx;
574d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
575d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
576d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               }
577d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               else {
578d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
579d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
580d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invQ;
581d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invQ;
582d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invQ;
583d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q;
584d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
585d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        dqdx, dqdy, texW, texH,
586d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                        s, t, q, invQ);
587d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
588d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
589d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
590d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
591d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
5922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
59331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               span->arrayMask |= SPAN_LAMBDA;
5942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
59531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
59677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
59777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
59831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
59931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
60031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
60131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
6022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
6032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
6042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
6052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
6062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
6077e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell               if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
608bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol                   ctx->ShaderObjects._FragmentShaderPresent) {
609d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  /* do perspective correction but don't divide s, t, r by q */
610d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  const GLfloat dwdx = span->dwdx;
611d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  GLfloat w = span->w;
612d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  for (i = 0; i < span->end; i++) {
613d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     const GLfloat invW = 1.0F / w;
614d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][0] = s * invW;
615d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][1] = t * invW;
616d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][2] = r * invW;
617d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     texcoord[i][3] = q * invW;
618d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     lambda[i] = 0.0;
619d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     s += dsdx;
620d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     t += dtdx;
621d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     r += drdx;
622d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     q += dqdx;
623d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                     w += dwdx;
624d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                  }
625d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               }
626d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               else if (dqdx == 0.0F) {
627c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  /* Ortho projection or polygon's parallel to window X axis */
6282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
629c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
63077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
63177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
63277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
63336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul                     texcoord[i][3] = q;
63477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
63531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
63631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
63731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
638c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
639c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               }
640c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               else {
641c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
642c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
64377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
64477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
64577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
64636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul                     texcoord[i][3] = q;
64777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
64831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
64931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
65031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
65131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     q += dqdx;
652c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
6532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
65431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            } /* lambda */
65531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         } /* if */
65631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      } /* for */
6572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
6582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
65931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* single texture */
66031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
66136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      GLfloat texW, texH;
66236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      GLboolean needLambda;
66336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      if (obj) {
66418fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell         const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
66536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         needLambda = (obj->MinFilter != obj->MagFilter)
6667e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell            || ctx->FragmentProgram._Enabled;
66736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texW = (GLfloat) img->WidthScale;
66836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texH = (GLfloat) img->HeightScale;
66936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      }
67036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      else {
67136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         needLambda = GL_FALSE;
67236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul         texW = texH = 1.0;
67336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul      }
674b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
67531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      if (needLambda) {
6762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* just texture unit 0, with lambda */
67777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
67877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat *lambda = span->array->lambda[0];
67931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
68031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdy = span->texStepY[0][0];
68131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
68231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdy = span->texStepY[0][1];
68331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
68431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
68531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdy = span->texStepY[0][3];
6862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
6872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
6882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
6892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
6902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
6917e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell         if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
692bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol             ctx->ShaderObjects._FragmentShaderPresent) {
693d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* do perspective correction but don't divide s, t, r by q */
694d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            const GLfloat dwdx = span->dwdx;
695d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            GLfloat w = span->w;
696d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
697d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invW = 1.0F / w;
698d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invW;
699d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invW;
700d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invW;
701d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q * invW;
702d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
703d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                  dqdx, dqdy, texW, texH,
704d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                  s, t, q, invW);
705d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
706d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
707d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
708d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
709d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               w += dwdx;
710d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
711d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
712d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else {
713d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* tex.c */
714d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
715d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
716d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
717d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                dqdx, dqdy, texW, texH,
718d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul                                                s, t, q, invQ);
719d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invQ;
720d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invQ;
721d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invQ;
722d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q;
723d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
724d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
725d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
726d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
727d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
7282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
7292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask |= SPAN_LAMBDA;
7302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
7312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      else {
732733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* just texture 0, without lambda */
73377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
73431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
73531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
73631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
73731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
7382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
7392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
7402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
7412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
7422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
7437e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell         if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled ||
744bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol             ctx->ShaderObjects._FragmentShaderPresent) {
745d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            /* do perspective correction but don't divide s, t, r by q */
746d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            const GLfloat dwdx = span->dwdx;
747d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            GLfloat w = span->w;
748d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            for (i = 0; i < span->end; i++) {
749d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               const GLfloat invW = 1.0F / w;
750d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][0] = s * invW;
751d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][1] = t * invW;
752d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][2] = r * invW;
753d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               texcoord[i][3] = q * invW;
754d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               s += dsdx;
755d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               t += dtdx;
756d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               r += drdx;
757d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               q += dqdx;
758d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul               w += dwdx;
759d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
760d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
761d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else if (dqdx == 0.0F) {
762c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            /* Ortho projection or polygon's parallel to window X axis */
7632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
764c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
76577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
76677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
76777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
7682b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul               texcoord[i][3] = q;
76931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
77031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
77131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
772c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
773c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         }
774c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         else {
775c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
776c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
77777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
77877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
77977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
7802b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul               texcoord[i][3] = q;
78131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
78231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
78331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
78431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               q += dqdx;
785c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
7862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
7872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
7882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
78910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
790e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
791e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
79279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
793bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol * Fill in the span.varying array from the interpolation values.
794bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol */
795bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krolstatic void
796cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_varying(GLcontext *ctx, SWspan *span)
797bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol{
798bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   GLuint i, j;
799bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
800bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(span->interpMask & SPAN_VARYING);
801bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(!(span->arrayMask & SPAN_VARYING));
802bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
803bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   span->arrayMask |= SPAN_VARYING;
804bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
805bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   for (i = 0; i < MAX_VARYING_VECTORS; i++) {
806bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      for (j = 0; j < VARYINGS_PER_VECTOR; j++) {
807bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         const GLfloat dvdx = span->varStepX[i][j];
808bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLfloat v = span->var[i][j];
809bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         const GLfloat dwdx = span->dwdx;
810bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLfloat w = span->w;
811bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         GLuint k;
812bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
813bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         for (k = 0; k < span->end; k++) {
814bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            GLfloat invW = 1.0f / w;
815bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            span->array->varying[k][i][j] = v * invW;
816bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            v += dvdx;
817bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            w += dwdx;
818bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         }
819bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      }
820bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   }
821bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol}
822bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
823bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
824bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol/**
825e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
826e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
8275071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
828cdb27e8242215271364602995d85607cfc06d441Brian Paulstipple_polygon_span( GLcontext *ctx, SWspan *span )
82910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
83010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint highbit = 0x80000000;
831733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLuint stipple = ctx->PolygonStipple[span->y % 32];
83277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLubyte *mask = span->array->mask;
833733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   GLuint i, m;
834733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
835733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
836733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->arrayMask & SPAN_XY) == 0);
83710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
83810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   m = highbit >> (GLuint) (span->x % 32);
83910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
84010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (i = 0; i < span->end; i++) {
84110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if ((m & stipple) == 0) {
84277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul	 mask[i] = 0;
84310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
84410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      m = m >> 1;
84510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (m == 0) {
84610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         m = highbit;
84710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
84810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
8492ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
85010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
85110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
852e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
85379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
854733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
855733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
856733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
857733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
85810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
85910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
86010f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic GLuint
861cdb27e8242215271364602995d85607cfc06d441Brian Paulclip_span( GLcontext *ctx, SWspan *span )
86210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
863733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
864733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
865733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
866733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
867733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
868733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
869733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
87077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *x = span->array->x;
87177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *y = span->array->y;
872733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
87377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLubyte *mask = span->array->mask;
874733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
875b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
876b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
877b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
878b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
879b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
880b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
881b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
882b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
883b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
884b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
885b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
886b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
887b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
88810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
889733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
89010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
891733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
892733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
893733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
894733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
895733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
896733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
897733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
898733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
899733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
900733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
901733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
90210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
903733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
904733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
905733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
906733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
9076ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul         _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
90810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
909733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
910733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
911733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
912733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
913733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
91410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
91510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
916733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
917733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
91810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
91910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
92010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
92179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
922e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Apply all the per-fragment opertions to a span of color index fragments
923e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * and write them to the enabled color drawbuffers.
924e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * The 'span' parameter can be considered to be const.  Note that
9257956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
9267956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
92710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
92810f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
929cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_index_span( GLcontext *ctx, SWspan *span)
93010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
931e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
932e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
933e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
93410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
935733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
936b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
937b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
938733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
9397956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
9407956292a765910077f50352d7cd0174e1e66d26cBrian Paul
941733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
942733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
943733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
944733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
945733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
946a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
947733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
94810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
94910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
950733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
951b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
952733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
95386ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
954e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
955e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
956e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
957e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   /* Depth bounds test */
95831e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
959e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      if (!_swrast_depth_bounds_test(ctx, span)) {
960e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul         return;
961e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      }
962e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   }
963e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul
964b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
965a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
966b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
967a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
968b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
96977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
97077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
97177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
97277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
97377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
974b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
975b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
976b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
977b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
978b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
979e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
980b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
98110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
982e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
983e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
984e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   /* Stencil and Z testing */
9857956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
9867956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (span->interpMask & SPAN_Z)
98745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
98810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
9897956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
99045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
9917956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
9927956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
9937956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
9942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
9957956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
9967956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
99745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
998e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            span->interpMask = origInterpMask;
9997956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
10007956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
10017956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
10022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
100310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
100410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1005b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
100623ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1007939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
100823ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1009b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1010b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
101123ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1012b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1013b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
1014b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
10157956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
10167956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
101710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
10182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
101910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
102010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
102110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
10227956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
1023dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled ||
1024e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexLogicOpEnabled ||
1025e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexMask != 0xffffffff ||
1026e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       (span->arrayMask & SPAN_COVERAGE)) {
1027e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (span->interpMask & SPAN_INDEX) {
1028e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         interpolate_indexes(ctx, span);
1029e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
10307956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
103110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
10327956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
1033dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled) {
103445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_ci_span(ctx, span);
1035e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1036e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
10372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
10382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1039e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      const GLfloat *coverage = span->array->coverage;
104077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLuint *index = span->array->index;
1041e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLuint i;
104210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
104377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         ASSERT(coverage[i] < 16);
104477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
10455071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
10462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
10475071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
1048ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
1049ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
1050ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
1051ba001224a18fa12792696ef393e708e90092127eBrian Paul   {
1052ba001224a18fa12792696ef393e708e90092127eBrian Paul      struct gl_framebuffer *fb = ctx->DrawBuffer;
1053a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      const GLuint output = 0; /* only frag progs can write to other outputs */
1054ba001224a18fa12792696ef393e708e90092127eBrian Paul      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1055ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint indexSave[MAX_WIDTH];
1056ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint buf;
1057e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1058ba001224a18fa12792696ef393e708e90092127eBrian Paul      if (numDrawBuffers > 1) {
1059ba001224a18fa12792696ef393e708e90092127eBrian Paul         /* save indexes for second, third renderbuffer writes */
1060ba001224a18fa12792696ef393e708e90092127eBrian Paul         _mesa_memcpy(indexSave, span->array->index,
1061ba001224a18fa12792696ef393e708e90092127eBrian Paul                      span->end * sizeof(indexSave[0]));
1062ba001224a18fa12792696ef393e708e90092127eBrian Paul      }
1063e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1064ba001224a18fa12792696ef393e708e90092127eBrian Paul      for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
1065ba001224a18fa12792696ef393e708e90092127eBrian Paul         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1066ba001224a18fa12792696ef393e708e90092127eBrian Paul         ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
10672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1068e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexLogicOpEnabled) {
1069f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_logicop_ci_span(ctx, rb, span);
1070e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1071e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1072e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
1073f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_mask_ci_span(ctx, rb, span);
1074e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
10752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1076ba001224a18fa12792696ef393e708e90092127eBrian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
1077ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* all fragments have same color index */
1078ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8;
1079ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16;
1080ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLuint index32;
1081ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *value;
1082e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1083ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
1084ba001224a18fa12792696ef393e708e90092127eBrian Paul               index8 = FixedToInt(span->index);
1085ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index8;
1086ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1087ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1088ba001224a18fa12792696ef393e708e90092127eBrian Paul               index16 = FixedToInt(span->index);
1089ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index16;
1090ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1091ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1092ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1093ba001224a18fa12792696ef393e708e90092127eBrian Paul               index32 = FixedToInt(span->index);
1094ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index32;
1095ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1096e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1097ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
1098ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoValues(ctx, rb, span->end, span->array->x,
1099ba001224a18fa12792696ef393e708e90092127eBrian Paul                                 span->array->y, value, span->array->mask);
1100e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
1101ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1102ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
1103ba001224a18fa12792696ef393e708e90092127eBrian Paul                              value, span->array->mask);
1104e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
1105733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1106733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
1107ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* each fragment is a different color */
1108ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8[MAX_WIDTH];
1109ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16[MAX_WIDTH];
1110ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *values;
1111ba001224a18fa12792696ef393e708e90092127eBrian Paul
1112ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
1113ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
1114ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
1115ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index8[k] = (GLubyte) span->array->index[k];
1116ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
1117ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index8;
1118ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1119ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1120ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
1121ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
1122ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index16[k] = (GLushort) span->array->index[k];
1123ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
1124ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index16;
1125ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1126ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1127ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1128ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = span->array->index;
1129ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1130e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1131ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
1132ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutValues(ctx, rb, span->end,
1133ba001224a18fa12792696ef393e708e90092127eBrian Paul                             span->array->x, span->array->y,
1134ba001224a18fa12792696ef393e708e90092127eBrian Paul                             values, span->array->mask);
1135ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1136ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1137ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutRow(ctx, rb, span->end, span->x, span->y,
1138e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                          values, span->array->mask);
1139ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1140e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1141ba001224a18fa12792696ef393e708e90092127eBrian Paul
1142ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (buf + 1 < numDrawBuffers) {
1143ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* restore original span values */
1144ba001224a18fa12792696ef393e708e90092127eBrian Paul            _mesa_memcpy(span->array->index, indexSave,
1145ba001224a18fa12792696ef393e708e90092127eBrian Paul                         span->end * sizeof(indexSave[0]));
1146733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1147ba001224a18fa12792696ef393e708e90092127eBrian Paul      } /* for buf */
1148e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
11492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
11507956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
11512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
1152e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1153e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1154e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
115579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1156e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color.  This is used only when
1157f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1158e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
11595071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
1160cdb27e8242215271364602995d85607cfc06d441Brian Pauladd_specular(GLcontext *ctx, SWspan *span)
1161e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1162d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   switch (span->array->ChanType) {
1163d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_UNSIGNED_BYTE:
1164d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1165d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1166d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLubyte (*spec)[4] = span->array->color.sz1.spec;
1167d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1168d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1169d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1170d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1171d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1172d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1173d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] = MIN2(r, 255);
1174d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] = MIN2(g, 255);
1175d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] = MIN2(b, 255);
1176d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] = MIN2(a, 255);
1177d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1178d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1179d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1180d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_UNSIGNED_SHORT:
1181d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1182d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1183d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLushort (*spec)[4] = span->array->color.sz2.spec;
1184d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1185d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1186d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1187d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1188d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1189d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1190d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] = MIN2(r, 65535);
1191d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] = MIN2(g, 65535);
1192d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] = MIN2(b, 65535);
1193d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] = MIN2(a, 65535);
1194d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1195d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1196d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1197d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_FLOAT:
1198d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1199d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
1200d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLfloat (*spec)[4] = span->array->color.sz4.spec;
1201d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1202d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1203d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] += spec[i][RCOMP];
1204d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] += spec[i][GCOMP];
1205d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] += spec[i][BCOMP];
1206d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] += spec[i][ACOMP];
1207d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1208d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1209d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1210d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   default:
1211d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      _mesa_problem(ctx, "Invalid datatype in add_specular");
1212e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1213e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1214e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1215e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
121679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1217d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul * Convert the span's color arrays to the given type.
1218e18d0f82b6271103e292fde5bab6fceccb96f90aBrian Paul * XXX this could be put into image.c and reused in several places.
1219d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
1220d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paulstatic void
1221cdb27e8242215271364602995d85607cfc06d441Brian Paulconvert_color_type(GLcontext *ctx, SWspan *span, GLenum newType)
1222d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul{
1223f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   GLvoid *src, *dst;
1224f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1225f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz1.rgba;
1226f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1227f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1228f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz2.rgba;
1229f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1230f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
1231f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz4.rgba;
1232f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1233f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (newType == GL_UNSIGNED_BYTE) {
1234f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz1.rgba;
1235f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1236f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (newType == GL_UNSIGNED_BYTE) {
1237f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz2.rgba;
1238f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1239f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
1240f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz4.rgba;
1241f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1242d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1243f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   _mesa_convert_colors(span->array->ChanType, src,
1244f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        newType, dst,
1245f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        span->end, span->array->mask);
1246d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1247d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   span->array->ChanType = newType;
1248d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul}
1249d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1250d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1251d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1252d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
1253a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Apply all the per-fragment operations to a span.
1254a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * This now includes texturing (_swrast_write_texture_span() is history).
1255f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
12567956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
12577956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
125878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
125978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
1260cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
126178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
126278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
126378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1264e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
1265e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
126632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   const GLboolean deferredTexture = !(ctx->Color.AlphaEnabled ||
12677e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell                                       ctx->FragmentProgram._Enabled ||
1268071357096e682e9af59ad45ea5abc444ab431837Michal Krol                                       ctx->ShaderObjects._FragmentShaderPresent);
1269f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1270b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
1271b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
1272733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
12737956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
127478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1275ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /*
1276a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1277a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul          span->interpMask, span->arrayMask);
1278ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   */
1279ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1280733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1281733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1282733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1283733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1284733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
1285a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
1286733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
128778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
128878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1289a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Clip to window/scissor box */
1290b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1291733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1292733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
129378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
129478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
129578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1296b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1297a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
1298b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1299a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
1300b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
130177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
130277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
130377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
130477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
130577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1306b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1307b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1308b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1309b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1310b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
131178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1312b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1313733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
131478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
131578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1316a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Interpolate texcoords? */
1317a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   if (ctx->Texture._EnabledCoordUnits
1318a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul       && (span->interpMask & SPAN_TEXTURE)
1319a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul       && (span->arrayMask & SPAN_TEXTURE) == 0) {
1320f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      interpolate_texcoords(ctx, span);
1321a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   }
132278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1323bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   if (ctx->ShaderObjects._FragmentShaderPresent) {
1324bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      interpolate_varying(ctx, span);
1325bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   }
1326bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
132732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* This is the normal place to compute the resulting fragment color/Z.
132832340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * As an optimization, we try to defer this until after Z/stencil
132932340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * testing in order to try to avoid computing colors that we won't
133032340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * actually need.
1331a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
133232340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   if (!deferredTexture) {
1333f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1334f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1335d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         interpolate_colors(ctx, span, GL_FALSE);
1336f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1337a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      if (span->interpMask & SPAN_SPEC)
1338d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         interpolate_colors(ctx, span, GL_TRUE);
133936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul
1340d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      if (span->interpMask & SPAN_FOG)
1341d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul         interpolate_fog(ctx, span);
1342d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
1343bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      /* Compute fragment colors with fragment program or texture lookups */
1344365582dd6f632aafbc1c817aa57926d679bb2efcMichal Krol#if FEATURE_ARB_fragment_shader
1345bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      if (ctx->ShaderObjects._FragmentShaderPresent) {
1346bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         if (span->interpMask & SPAN_Z)
1347bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            _swrast_span_interpolate_z (ctx, span);
1348bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         _swrast_exec_arbshader (ctx, span);
1349a66393120411071b3f3ccce8583ab961a2935959Michal Krol      }
1350365582dd6f632aafbc1c817aa57926d679bb2efcMichal Krol      else
1351365582dd6f632aafbc1c817aa57926d679bb2efcMichal Krol#endif
13527e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell      if (ctx->FragmentProgram._Enabled) {
135332340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul         /* frag prog may need Z values */
135432340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul         if (span->interpMask & SPAN_Z)
135532340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul            _swrast_span_interpolate_z(ctx, span);
1356e22540c2765e034fed558ea1d44488a03fbba170Brian Paul         _swrast_exec_fragment_program( ctx, span );
135732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul      }
13587f752fed993e5e9423abac200dd59141edbada56Dave Airlie      else if (ctx->ATIFragmentShader._Enabled)
13597f752fed993e5e9423abac200dd59141edbada56Dave Airlie         _swrast_exec_fragment_shader( ctx, span );
1360252d8e78cc07880239b085b713e2d37ddbba86f9Brian Paul      else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE))
1361610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul         _swrast_texture_span( ctx, span );
136278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
136378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Do the alpha test */
13645e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger      if (ctx->Color.AlphaEnabled) {
13655e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger         if (!_swrast_alpha_test(ctx, span)) {
13665e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger            span->arrayMask = origArrayMask;
13675e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger	    return;
13685e01f9a11489079d8509927774d8239c1857224aRoland Scheidegger	 }
136978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
137078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
137178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1372f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1373f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1374f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
137545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
137678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1377e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1378a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Combined Z/stencil tests */
137945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1380e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul            span->interpMask = origInterpMask;
1381f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
138210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1383f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
138471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1385e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1386a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Just regular depth testing */
1387f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1388f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
138945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
1390e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul            span->interpMask = origInterpMask;
1391f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
139210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1393f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
139471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
139571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
139671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1397b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
139823ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1399939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
140023ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1401b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1402b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
140323ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1404b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1405b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
1406b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
1407a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1408f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1409f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1410f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1411e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      span->interpMask = origInterpMask;
1412f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      span->arrayMask = origArrayMask;
1413f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      return;
141471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
141571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
141632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* If we were able to defer fragment color computation to now, there's
141732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * a good chance that many fragments will have already been killed by
141832340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * Z/stencil testing.
1419a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
142032340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   if (deferredTexture) {
1421f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1422f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1423d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         interpolate_colors(ctx, span, GL_FALSE);
142471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1425a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      if (span->interpMask & SPAN_SPEC)
1426d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         interpolate_colors(ctx, span, GL_TRUE);
142736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul
1428d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      if (span->interpMask & SPAN_FOG)
1429d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul         interpolate_fog(ctx, span);
1430d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
1431365582dd6f632aafbc1c817aa57926d679bb2efcMichal Krol#if FEATURE_ARB_fragment_shader
1432bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      if (ctx->ShaderObjects._FragmentShaderPresent) {
1433bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         if (span->interpMask & SPAN_Z)
1434bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol            _swrast_span_interpolate_z (ctx, span);
1435bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         _swrast_exec_arbshader (ctx, span);
1436bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      }
1437365582dd6f632aafbc1c817aa57926d679bb2efcMichal Krol      else
1438365582dd6f632aafbc1c817aa57926d679bb2efcMichal Krol#endif
14397e9799ac3d7f3b1b90f098420d413be95916c541Keith Whitwell      if (ctx->FragmentProgram._Enabled)
1440e22540c2765e034fed558ea1d44488a03fbba170Brian Paul         _swrast_exec_fragment_program( ctx, span );
14417f752fed993e5e9423abac200dd59141edbada56Dave Airlie      else if (ctx->ATIFragmentShader._Enabled)
14427f752fed993e5e9423abac200dd59141edbada56Dave Airlie         _swrast_exec_fragment_shader( ctx, span );
1443252d8e78cc07880239b085b713e2d37ddbba86f9Brian Paul      else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE))
1444610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul         _swrast_texture_span( ctx, span );
144571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
144671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1447f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
14482ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
14499d148e6b2be33fe7ac72aaa3be239dc1bc8878a9Keith Whitwell   if (!ctx->FragmentProgram._Enabled) {
1450dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      /* Add base and specular colors */
1451dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      if (ctx->Fog.ColorSumEnabled ||
1452dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul          (ctx->Light.Enabled &&
1453dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1454dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         if (span->interpMask & SPAN_SPEC) {
1455d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            interpolate_colors(ctx, span, GL_TRUE);
1456dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         }
1457a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         if (span->arrayMask & SPAN_SPEC) {
1458d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            add_specular(ctx, span);
1459a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
1460a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         else {
1461a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul            /* We probably added the base/specular colors during the
1462a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             * vertex stage!
1463a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             */
1464a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
146571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
146671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
146771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
14686e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
146909da0b8e6621a831e3eeb9381430f2bed18a22adBrian Paul   if (swrast->_FogEnabled) {
147045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_rgba_span(ctx, span);
147171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1472f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
147371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
14742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
147577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLchan (*rgba)[4] = span->array->rgba;
147677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLfloat *coverage = span->array->coverage;
147771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      GLuint i;
147810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
147977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
148071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
148171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
148271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1483ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
1484ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul#if CHAN_TYPE == GL_FLOAT
1485ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   if (ctx->Color.ClampFragmentColor) {
1486ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      GLchan (*rgba)[4] = span->array->rgba;
1487ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      GLuint i;
1488ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      for (i = 0; i < span->end; i++) {
1489ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0, CHAN_MAXF);
1490ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0, CHAN_MAXF);
1491ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0, CHAN_MAXF);
1492ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul         rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0, CHAN_MAXF);
1493ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul      }
1494ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   }
1495ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul#endif
1496ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul
1497ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
1498ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
1499ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
1500ba001224a18fa12792696ef393e708e90092127eBrian Paul   {
1501ba001224a18fa12792696ef393e708e90092127eBrian Paul      struct gl_framebuffer *fb = ctx->DrawBuffer;
1502a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      const GLuint output = 0; /* only frag progs can write to other outputs */
1503ba001224a18fa12792696ef393e708e90092127eBrian Paul      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1504ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLchan rgbaSave[MAX_WIDTH][4];
1505ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint buf;
1506e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1507d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      if (numDrawBuffers > 0) {
1508d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         if (fb->_ColorDrawBuffers[output][0]->DataType
1509d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul             != span->array->ChanType) {
1510d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            convert_color_type(ctx, span,
1511d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul                               fb->_ColorDrawBuffers[output][0]->DataType);
1512d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1513d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1514d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1515ba001224a18fa12792696ef393e708e90092127eBrian Paul      if (numDrawBuffers > 1) {
1516ba001224a18fa12792696ef393e708e90092127eBrian Paul         /* save colors for second, third renderbuffer writes */
1517ba001224a18fa12792696ef393e708e90092127eBrian Paul         _mesa_memcpy(rgbaSave, span->array->rgba,
1518ba001224a18fa12792696ef393e708e90092127eBrian Paul                      4 * span->end * sizeof(GLchan));
151971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
152071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1521ba001224a18fa12792696ef393e708e90092127eBrian Paul      for (buf = 0; buf < numDrawBuffers; buf++) {
1522ba001224a18fa12792696ef393e708e90092127eBrian Paul         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1523f971e24cf0341dd2779196a0836327b74fc82336Brian Paul         ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
152471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1525ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (ctx->Color._LogicOpEnabled) {
1526f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_logicop_rgba_span(ctx, rb, span);
1527ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1528ba001224a18fa12792696ef393e708e90092127eBrian Paul         else if (ctx->Color.BlendEnabled) {
1529f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_blend_span(ctx, rb, span);
1530ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1531ba001224a18fa12792696ef393e708e90092127eBrian Paul
1532ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (colorMask != 0xffffffff) {
1533f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_mask_rgba_span(ctx, rb, span);
1534ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1535ba001224a18fa12792696ef393e708e90092127eBrian Paul
1536ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (span->arrayMask & SPAN_XY) {
1537ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* array of pixel coords */
1538ba001224a18fa12792696ef393e708e90092127eBrian Paul            ASSERT(rb->PutValues);
1539ba001224a18fa12792696ef393e708e90092127eBrian Paul            rb->PutValues(ctx, rb, span->end,
1540ba001224a18fa12792696ef393e708e90092127eBrian Paul                          span->array->x, span->array->y,
1541ba001224a18fa12792696ef393e708e90092127eBrian Paul                          span->array->rgba, span->array->mask);
1542ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1543ba001224a18fa12792696ef393e708e90092127eBrian Paul         else {
1544ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* horizontal run of pixels */
1545ba001224a18fa12792696ef393e708e90092127eBrian Paul            ASSERT(rb->PutRow);
1546ba001224a18fa12792696ef393e708e90092127eBrian Paul            rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1547ba001224a18fa12792696ef393e708e90092127eBrian Paul                       span->writeAll ? NULL: span->array->mask);
1548ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1549ba001224a18fa12792696ef393e708e90092127eBrian Paul
1550ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (buf + 1 < numDrawBuffers) {
1551ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* restore original span values */
1552ba001224a18fa12792696ef393e708e90092127eBrian Paul            _mesa_memcpy(span->array->rgba, rgbaSave,
1553ba001224a18fa12792696ef393e708e90092127eBrian Paul                         4 * span->end * sizeof(GLchan));
1554ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1555ba001224a18fa12792696ef393e708e90092127eBrian Paul      } /* for buf */
155671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
155771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1558e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   span->interpMask = origInterpMask;
1559f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
156010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
156110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1562e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1563e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
156479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1565e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
1566e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1567e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
15685071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1569e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1570a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul                        GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1571e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1572e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1573e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1574a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1575a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1576e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1577e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* XXX maybe leave rgba values undefined? */
15786ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul      _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1579e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1580e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1581e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1582e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
15837e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1584e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1585e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1586e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1587e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1588e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1589e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1590a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1591a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1592e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1593e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1594a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1595e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1596e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1597a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1598e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1599e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1600e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1601e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1602e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1603e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1604e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1605e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1606e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1607e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1608e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1609bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb);
1610bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->GetRow);
1611bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
161265dccf377de51d6cbc15cb968eec85ba3f1febc1Brian Paul      ASSERT(rb->DataType == CHAN_TYPE);
1613bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      rb->GetRow(ctx, rb, length, x + skip, y, rgba + skip);
1614e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1615e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1616e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1617e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
161879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1619e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read CI pixels from frame buffer.  Clipping will be done to prevent
1620e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1621e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
16225071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1623e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1624e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                         GLuint n, GLint x, GLint y, GLuint index[] )
1625e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1626e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1627e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1628a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1629a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1630e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1631e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      _mesa_bzero(index, n * sizeof(GLuint));
1632e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1633e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1634e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1635e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
16367e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1637e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1638e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1639e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1640e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1641e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1642e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1643a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1644a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1645e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1646e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1647a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1648e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1649e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1650a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1651e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1652e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1653e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1654e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1655e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1656e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1657e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1658e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1659e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1660e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1661e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1662e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->GetRow);
1663e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1664e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1665e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (rb->DataType == GL_UNSIGNED_BYTE) {
1666e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLubyte index8[MAX_WIDTH];
1667e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1668e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index8);
1669e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1670e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index8[i];
1671e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1672e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_SHORT) {
1673e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLushort index16[MAX_WIDTH];
1674e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1675e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index16);
1676e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1677e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index16[i];
1678e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1679e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_INT) {
1680e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1681e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1682e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1683e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
168467074332728acba86da7630353673b458713bb8aBrian Paul
168567074332728acba86da7630353673b458713bb8aBrian Paul
168667074332728acba86da7630353673b458713bb8aBrian Paul/**
168767074332728acba86da7630353673b458713bb8aBrian Paul * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
168867074332728acba86da7630353673b458713bb8aBrian Paul * reading values outside the buffer bounds.
168967074332728acba86da7630353673b458713bb8aBrian Paul * We can use this for reading any format/type of renderbuffer.
1690ba001224a18fa12792696ef393e708e90092127eBrian Paul * \param valueSize is the size in bytes of each value (pixel) put into the
169167074332728acba86da7630353673b458713bb8aBrian Paul *                  values array.
169267074332728acba86da7630353673b458713bb8aBrian Paul */
169367074332728acba86da7630353673b458713bb8aBrian Paulvoid
169467074332728acba86da7630353673b458713bb8aBrian Paul_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
169567074332728acba86da7630353673b458713bb8aBrian Paul                   GLuint count, const GLint x[], const GLint y[],
169667074332728acba86da7630353673b458713bb8aBrian Paul                   void *values, GLuint valueSize)
169767074332728acba86da7630353673b458713bb8aBrian Paul{
169867074332728acba86da7630353673b458713bb8aBrian Paul   GLuint i, inCount = 0, inStart = 0;
169967074332728acba86da7630353673b458713bb8aBrian Paul
170067074332728acba86da7630353673b458713bb8aBrian Paul   for (i = 0; i < count; i++) {
170167074332728acba86da7630353673b458713bb8aBrian Paul      if (x[i] >= 0 && y[i] >= 0 && x[i] < rb->Width && y[i] < rb->Height) {
170267074332728acba86da7630353673b458713bb8aBrian Paul         /* inside */
170367074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount == 0)
170467074332728acba86da7630353673b458713bb8aBrian Paul            inStart = i;
170567074332728acba86da7630353673b458713bb8aBrian Paul         inCount++;
170667074332728acba86da7630353673b458713bb8aBrian Paul      }
170767074332728acba86da7630353673b458713bb8aBrian Paul      else {
170867074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount > 0) {
170967074332728acba86da7630353673b458713bb8aBrian Paul            /* read [inStart, inStart + inCount) */
171067074332728acba86da7630353673b458713bb8aBrian Paul            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
171167074332728acba86da7630353673b458713bb8aBrian Paul                          (GLubyte *) values + inStart * valueSize);
171267074332728acba86da7630353673b458713bb8aBrian Paul            inCount = 0;
171367074332728acba86da7630353673b458713bb8aBrian Paul         }
171467074332728acba86da7630353673b458713bb8aBrian Paul      }
171567074332728acba86da7630353673b458713bb8aBrian Paul   }
171667074332728acba86da7630353673b458713bb8aBrian Paul   if (inCount > 0) {
171767074332728acba86da7630353673b458713bb8aBrian Paul      /* read last values */
171867074332728acba86da7630353673b458713bb8aBrian Paul      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
171967074332728acba86da7630353673b458713bb8aBrian Paul                    (GLubyte *) values + inStart * valueSize);
172067074332728acba86da7630353673b458713bb8aBrian Paul   }
172167074332728acba86da7630353673b458713bb8aBrian Paul}
17223fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17233fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17243fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul/**
17253fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1726a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
17273fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul */
17283fd819aef8139761ce86cb8d763de83a11c81b33Brian Paulvoid
17293fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
17303fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                GLuint count, GLint x, GLint y,
17313fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                const GLvoid *values, GLuint valueSize)
17323fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul{
17333fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   GLint skip = 0;
17343fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17353fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (y < 0 || y >= rb->Height)
17363fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* above or below */
17373fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17383fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x + (GLint) count <= 0 || x >= rb->Width)
17393fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* entirely left or right */
17403fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17413fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x + count > rb->Width) {
17423fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* right clip */
17433fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      GLint clip = x + count - rb->Width;
17443fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= clip;
17453fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
17463fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17473fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x < 0) {
17483fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* left clip */
17493fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      skip = -x;
17503fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      x = 0;
17513fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= skip;
17523fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
17533fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17543fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   rb->PutRow(ctx, rb, count, x, y,
17553fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul              (const GLubyte *) values + skip * valueSize, NULL);
17563fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul}
1757f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1758f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1759f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul/**
1760f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1761a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
1762f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul */
1763f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paulvoid
1764f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1765f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLuint count, GLint x, GLint y,
1766f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLvoid *values, GLuint valueSize)
1767f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul{
1768f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   GLint skip = 0;
1769f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1770f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (y < 0 || y >= rb->Height)
1771f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* above or below */
1772f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1773f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + (GLint) count <= 0 || x >= rb->Width)
1774f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* entirely left or right */
1775f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1776f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + count > rb->Width) {
1777f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* right clip */
1778f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      GLint clip = x + count - rb->Width;
1779f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= clip;
1780f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1781f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1782f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x < 0) {
1783f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* left clip */
1784f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      skip = -x;
1785f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      x = 0;
1786f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= skip;
1787f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1788f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1789f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1790f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul}
1791a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1792a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1793a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul/**
1794a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Get RGBA pixels from the given renderbuffer.  Put the pixel colors into
1795a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * the span's specular color arrays.  The specular color arrays should no
1796a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * longer be needed by time this function is called.
1797a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Used by blending, logicop and masking functions.
1798a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \return pointer to the colors we read.
1799a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul */
1800a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paulvoid *
1801a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1802cdb27e8242215271364602995d85607cfc06d441Brian Paul                      SWspan *span)
1803a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul{
1804a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   GLuint pixelSize;
1805a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   void *rbPixels;
1806a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1807a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /*
1808a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    * Determine pixel size (in bytes).
1809a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    * Point rbPixels to a temporary space (use specular color arrays).
1810a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    */
1811a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1812a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      pixelSize = 4 * sizeof(GLubyte);
1813a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz1.spec;
1814a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1815a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1816a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      pixelSize = 4 * sizeof(GLushort);
1817a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz2.spec;
1818a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1819a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1820a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      pixelSize = 4 * sizeof(GLfloat);
1821a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz4.spec;
1822a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1823a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1824a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /* Get destination values from renderbuffer */
1825a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->arrayMask & SPAN_XY) {
1826a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1827a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                         rbPixels, pixelSize);
1828a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1829a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1830a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1831a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                      rbPixels, pixelSize);
1832a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1833a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1834a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   return rbPixels;
1835a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul}
1836