s_span.c revision e4f976b8b9d74a74b5816146cb11880c3a493929
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"
42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
43cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
44e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
48c968d3d410a1897ecbb41d3557adaef69a4c627aBrian#include "s_fragprog.h"
49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
5155187ea63e980b32c7a701855571332f4357d634Brian Paul#include "s_texcombine.h"
52e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
5479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's Z interpolation values to the RasterPos Z.
562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
59cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_z( GLcontext *ctx, SWspan *span )
602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
61e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
6231e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16)
63e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else
65e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      span->z = (GLint) (ctx->Current.RasterPos[2] * depthMax + 0.5F);
662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->zStep = 0;
672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_Z;
682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
7179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's fog interpolation values to the RasterPos fog.
732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
76cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_fog( GLcontext *ctx, SWspan *span )
772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
78e4f976b8b9d74a74b5816146cb11880c3a493929Brian   span->attrStart[FRAG_ATTRIB_FOGC][0]
79e4f976b8b9d74a74b5816146cb11880c3a493929Brian      = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
80462d8f5fafcc5ac69ea89cac1222abadded642e2Brian   span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
81462d8f5fafcc5ac69ea89cac1222abadded642e2Brian   span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_FOG;
832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
87a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Init span's rgba or index interpolation values to the RasterPos color.
882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
91cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_color( GLcontext *ctx, SWspan *span )
922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.rgbMode) {
942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan r, g, b, a;
952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red = r;
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = g;
1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue = b;
1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = a;
1042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
1052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red   = IntToFixed(r);
1062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = IntToFixed(g);
1072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue  = IntToFixed(b);
1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = IntToFixed(a);
1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
1102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->redStep = 0;
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->greenStep = 0;
1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blueStep = 0;
1132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alphaStep = 0;
1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_RGBA;
1152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1170f3cd3f894612d156de454178effa4c732f96da7Brian Paul      span->index = FloatToFixed(ctx->Current.RasterIndex);
1182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->indexStep = 0;
1192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_INDEX;
1202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1244753d60dd070bb08d0116076bcc08025c86ce857Brian Paul/**
1254753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Init span's texcoord interpolation values to the RasterPos texcoords.
1264753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Used during setup for glDraw/CopyPixels.
1274753d60dd070bb08d0116076bcc08025c86ce857Brian Paul */
1284753d60dd070bb08d0116076bcc08025c86ce857Brian Paulvoid
129cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_default_texcoords( GLcontext *ctx, SWspan *span )
1304753d60dd070bb08d0116076bcc08025c86ce857Brian Paul{
1314753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   GLuint i;
132ee4e75bd6f768b7210436feeb32b4545ed62e025Brian Paul   for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
1339ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian      const GLuint attr = FRAG_ATTRIB_TEX0 + i;
134e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      const GLfloat *tc = ctx->Current.RasterTexCoords[i];
13512ef1fbefcee964b715783d3ade6b69b2c699ed8Brian      if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
1369ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian         COPY_4V(span->attrStart[attr], tc);
137a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      }
138a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      else if (tc[3] > 0.0F) {
139e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul         /* use (s/q, t/q, r/q, 1) */
1409ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian         span->attrStart[attr][0] = tc[0] / tc[3];
1419ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian         span->attrStart[attr][1] = tc[1] / tc[3];
1429ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian         span->attrStart[attr][2] = tc[2] / tc[3];
1439ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian         span->attrStart[attr][3] = 1.0;
144e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
145e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      else {
1469ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian         ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
147e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
1489ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian      ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
1499ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian      ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
1504753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   }
1514753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   span->interpMask |= SPAN_TEXTURE;
1524753d60dd070bb08d0116076bcc08025c86ce857Brian Paul}
1534753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
1544753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
155d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
156e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul * Interpolate primary colors to fill in the span->array->color array.
157d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
158f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
159e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paulinterpolate_colors(SWspan *span)
1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
1622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
1632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
164e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   ASSERT((span->interpMask & SPAN_RGBA)  &&
165e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul          !(span->arrayMask & SPAN_RGBA));
1662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
167e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   switch (span->array->ChanType) {
1681e3223c02a2f6155beb5784cadbea1f46703829aBrian Paul#if CHAN_BITS != 32
169e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_BYTE:
170e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
171e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
172e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
173d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLubyte color[4];
174e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
175e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
176e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
177e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
178d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
179d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4UBV(rgba[i], color);
180d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
181d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
182e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
183e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = span->red;
184e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = span->green;
185e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = span->blue;
186e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed a = span->alpha;
187e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = span->redStep;
188e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = span->greenStep;
189e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = span->blueStep;
190e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint da = span->alphaStep;
191d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
192e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][RCOMP] = FixedToChan(r);
193e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][GCOMP] = FixedToChan(g);
194e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][BCOMP] = FixedToChan(b);
195e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][ACOMP] = FixedToChan(a);
196e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               r += dr;
197e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               g += dg;
198e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               b += db;
199e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               a += da;
200d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
201d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
202e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
203e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
204e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_SHORT:
205e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
206e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
207e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
208e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort color[4];
209e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
210e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
211e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
212e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
213d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
214d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4V(rgba[i], color);
215d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
216d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
217e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
218e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort (*rgba)[4] = span->array->color.sz2.rgba;
219d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfixed r, g, b, a;
220d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint dr, dg, db, da;
221e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            r = span->red;
222e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            g = span->green;
223e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            b = span->blue;
224e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            a = span->alpha;
225e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = span->redStep;
226e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dg = span->greenStep;
227e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            db = span->blueStep;
228e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            da = span->alphaStep;
229d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
230d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][RCOMP] = FixedToChan(r);
231d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][GCOMP] = FixedToChan(g);
232d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][BCOMP] = FixedToChan(b);
233d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][ACOMP] = FixedToChan(a);
234d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
235d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
236d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
237d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a += da;
238d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
239d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
240e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
241e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
242e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul#endif
243e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_FLOAT:
244e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
245f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
246e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLfloat r, g, b, a, dr, dg, db, da;
247e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         r = span->red;
248e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         g = span->green;
249e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         b = span->blue;
250e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         a = span->alpha;
251e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
252e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = dg = db = da = 0.0;
253e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
254e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
255e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = span->redStep;
256e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dg = span->greenStep;
257e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            db = span->blueStep;
258e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            da = span->alphaStep;
259e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
260e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         for (i = 0; i < n; i++) {
261e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][RCOMP] = r;
262e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][GCOMP] = g;
263e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][BCOMP] = b;
264e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            rgba[i][ACOMP] = a;
265e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            r += dr;
266e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            g += dg;
267e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            b += db;
268e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            a += da;
269e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
270e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
271e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
272e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   default:
273e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      _mesa_problem(NULL, "bad datatype in interpolate_colors");
274e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   }
275e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   span->arrayMask |= SPAN_RGBA;
276e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul}
277e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
278e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
279e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul/**
280e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul * Interpolate specular/secondary colors.
281e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul */
282f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
283e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paulinterpolate_specular(SWspan *span)
284e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul{
285e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   const GLuint n = span->end;
286e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   GLuint i;
287e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
288e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   switch (span->array->ChanType) {
289c351858de8e51fa4a6425cf176cc43689189f3ffBrian Paul#if CHAN_BITS != 32
290e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_BYTE:
291e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
292e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLubyte (*spec)[4] = span->array->color.sz1.spec;
293e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
294e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLubyte color[4];
295e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->specRed);
296e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->specGreen);
297e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->specBlue);
298e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = 0;
299e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            for (i = 0; i < n; i++) {
300e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               COPY_4UBV(spec[i], color);
301d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
302e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
303e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
304e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = span->specRed;
305e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = span->specGreen;
306e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = span->specBlue;
307e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = span->specRedStep;
308e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = span->specGreenStep;
309e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = span->specBlueStep;
310d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
311e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][RCOMP] = CLAMP(FixedToChan(r), 0, 255);
312e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][GCOMP] = CLAMP(FixedToChan(g), 0, 255);
313e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][BCOMP] = CLAMP(FixedToChan(b), 0, 255);
314e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][ACOMP] = 0;
315d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
316d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
317d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
318d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
319d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
320e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
321e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
322e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_SHORT:
323e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
324e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         GLushort (*spec)[4] = span->array->color.sz2.spec;
325e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
326e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort color[4];
327e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->specRed);
328e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->specGreen);
329e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->specBlue);
330e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = 0;
331e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            for (i = 0; i < n; i++) {
332e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               COPY_4V(spec[i], color);
333d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
334e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
335e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
336e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = FloatToFixed(span->specRed);
337e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = FloatToFixed(span->specGreen);
338e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = FloatToFixed(span->specBlue);
339e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = FloatToFixed(span->specRedStep);
340e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = FloatToFixed(span->specGreenStep);
341e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = FloatToFixed(span->specBlueStep);
342e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            for (i = 0; i < n; i++) {
343e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][RCOMP] = FixedToInt(r);
344e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][GCOMP] = FixedToInt(g);
345e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][BCOMP] = FixedToInt(b);
346e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               spec[i][ACOMP] = 0;
347e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               r += dr;
348e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               g += dg;
349e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               b += db;
350d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
351e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
352e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
353e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
354c351858de8e51fa4a6425cf176cc43689189f3ffBrian Paul#endif
355e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_FLOAT:
356e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
357f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
358e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul#if CHAN_BITS <= 16
359e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         GLfloat r = CHAN_TO_FLOAT(FixedToChan(span->specRed));
360e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         GLfloat g = CHAN_TO_FLOAT(FixedToChan(span->specGreen));
361e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         GLfloat b = CHAN_TO_FLOAT(FixedToChan(span->specBlue));
362e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul#else
363e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         GLfloat r = span->specRed;
364e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         GLfloat g = span->specGreen;
365e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         GLfloat b = span->specBlue;
366e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul#endif
367e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         GLfloat dr, dg, db;
368e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
369e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            dr = dg = db = 0.0;
370e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
371e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
372e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul#if CHAN_BITS <= 16
373e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            dr = CHAN_TO_FLOAT(FixedToChan(span->specRedStep));
374e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            dg = CHAN_TO_FLOAT(FixedToChan(span->specGreenStep));
375e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            db = CHAN_TO_FLOAT(FixedToChan(span->specBlueStep));
376e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul#else
377e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            dr = span->specRedStep;
378e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            dg = span->specGreenStep;
379e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            db = span->specBlueStep;
380e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul#endif
381e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         }
382e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         for (i = 0; i < n; i++) {
383e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            spec[i][RCOMP] = r;
384e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            spec[i][GCOMP] = g;
385e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            spec[i][BCOMP] = b;
386e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            spec[i][ACOMP] = 0.0F;
387e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            r += dr;
388e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            g += dg;
389e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            b += db;
390d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
3912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
392e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
393e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   default:
394e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      _mesa_problem(NULL, "bad datatype in interpolate_specular");
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
396e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   span->arrayMask |= SPAN_SPEC;
3972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
3982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
401f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
402cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_indexes(GLcontext *ctx, SWspan *span)
4032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
4042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
4052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
4062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
40777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLuint *indexes = span->array->index;
4082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
409a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
410b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_INDEX)  &&
411b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_INDEX));
4122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
4142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
4152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
4162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
4172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
4182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
4212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
4222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
4232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
4242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
4252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
428e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   span->interpMask &= ~SPAN_INDEX;
4292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
432d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul/* Fill in the span.array.fog values from the interpolation values */
433f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
434cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_fog(const GLcontext *ctx, SWspan *span)
435d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul{
436f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*fog)[4] = span->array->attribs[FRAG_ATTRIB_FOGC];
437462d8f5fafcc5ac69ea89cac1222abadded642e2Brian   const GLfloat fogStep = span->attrStepX[FRAG_ATTRIB_FOGC][0];
438462d8f5fafcc5ac69ea89cac1222abadded642e2Brian   GLfloat fogCoord = span->attrStart[FRAG_ATTRIB_FOGC][0];
439d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   const GLuint haveW = (span->interpMask & SPAN_W);
4409ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian   const GLfloat wStep = haveW ? span->attrStepX[FRAG_ATTRIB_WPOS][3] : 0.0F;
4419ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian   GLfloat w = haveW ? span->attrStart[FRAG_ATTRIB_WPOS][3] : 1.0F;
442d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   GLuint i;
443d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   for (i = 0; i < span->end; i++) {
444f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      fog[i][0] = fogCoord / w;
445d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      fogCoord += fogStep;
446d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul      w += wStep;
447d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   }
448d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul   span->arrayMask |= SPAN_FOG;
449d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul}
450d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
451d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
4522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */
453711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
454cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
4552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
4562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
4572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
4582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
459b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_Z)  &&
460b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_Z));
4612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
46231e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16) {
4632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
4643e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
465ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      for (i = 0; i < n; i++) {
46677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = FixedToInt(zval);
4672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
4712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
4727265556b9aa0367e9b5031e7cb15ed2a5d73866dBrian Paul      GLuint zval = span->z;
4733e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
4742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
47577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = zval;
4762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
47932340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   span->interpMask &= ~SPAN_Z;
4802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
4812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
484c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
48531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
486c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
487c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
48831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
48931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
49031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
49131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
492c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
49331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
49431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
49531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
49631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
497f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
498f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
49931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
50031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
50131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
502c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
503c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
504c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
50531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
50631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/*
50731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This is a faster approximation
508c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
509350353adcd75f94fda63c787c86961716114e0bfBrian PaulGLfloat
51045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
511350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
512350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
513c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
51431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
51531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
51631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
51731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
51831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
51931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
52031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
52131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
52231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
52331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
52431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
52531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
52631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
52731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
528c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
529c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
530d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
531d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul/**
532c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Fill in the span.texcoords array from the interpolation values.
533d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * Note: in the places where we divide by Q (or mult by invQ) we're
534d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * really doing two things: perspective correction and texcoord
535d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * projection.  Remember, for texcoord (s,t,r,q) we need to index
536d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * texels with (s/q, t/q, r/q).
537d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * If we're using a fragment program, we never do the division
538d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * for texcoord projection.  That's done by the TXP instruction
539d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * or user-written code.
540c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
5412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
542cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_texcoords(GLcontext *ctx, SWspan *span)
5432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
544e4f976b8b9d74a74b5816146cb11880c3a493929Brian   const GLuint maxUnit
545e4f976b8b9d74a74b5816146cb11880c3a493929Brian      = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
546e4f976b8b9d74a74b5816146cb11880c3a493929Brian   GLuint u;
547e4f976b8b9d74a74b5816146cb11880c3a493929Brian
5482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_TEXTURE);
549b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(!(span->arrayMask & SPAN_TEXTURE));
5502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
551e4f976b8b9d74a74b5816146cb11880c3a493929Brian   span->arrayMask |= SPAN_TEXTURE;
552e4f976b8b9d74a74b5816146cb11880c3a493929Brian
553e4f976b8b9d74a74b5816146cb11880c3a493929Brian   /* XXX CoordUnits vs. ImageUnits */
554e4f976b8b9d74a74b5816146cb11880c3a493929Brian   for (u = 0; u < maxUnit; u++) {
555e4f976b8b9d74a74b5816146cb11880c3a493929Brian      if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
556e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLuint attr = FRAG_ATTRIB_TEX0 + u;
557e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
558e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat texW, texH;
559e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLboolean needLambda;
560e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat (*texcoord)[4] = span->array->attribs[attr];
561e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat *lambda = span->array->lambda[u];
562e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dsdx = span->attrStepX[attr][0];
563e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dsdy = span->attrStepY[attr][0];
564e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dtdx = span->attrStepX[attr][1];
565e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dtdy = span->attrStepY[attr][1];
566e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat drdx = span->attrStepX[attr][2];
567e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dqdx = span->attrStepX[attr][3];
568e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dqdy = span->attrStepY[attr][3];
569e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat s = span->attrStart[attr][0];
570e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat t = span->attrStart[attr][1];
571e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat r = span->attrStart[attr][2];
572e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat q = span->attrStart[attr][3];
573e4f976b8b9d74a74b5816146cb11880c3a493929Brian
574e4f976b8b9d74a74b5816146cb11880c3a493929Brian         if (obj) {
575e4f976b8b9d74a74b5816146cb11880c3a493929Brian            const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
576e4f976b8b9d74a74b5816146cb11880c3a493929Brian            needLambda = (obj->MinFilter != obj->MagFilter)
577e4f976b8b9d74a74b5816146cb11880c3a493929Brian               || ctx->FragmentProgram._Current;
578e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texW = img->WidthScale;
579e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texH = img->HeightScale;
580e4f976b8b9d74a74b5816146cb11880c3a493929Brian         }
581e4f976b8b9d74a74b5816146cb11880c3a493929Brian         else {
582e4f976b8b9d74a74b5816146cb11880c3a493929Brian            /* using a fragment program */
583e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texW = 1.0;
584e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texH = 1.0;
585e4f976b8b9d74a74b5816146cb11880c3a493929Brian            needLambda = GL_FALSE;
586e4f976b8b9d74a74b5816146cb11880c3a493929Brian         }
587e4f976b8b9d74a74b5816146cb11880c3a493929Brian
588e4f976b8b9d74a74b5816146cb11880c3a493929Brian         if (needLambda) {
589e4f976b8b9d74a74b5816146cb11880c3a493929Brian            GLuint i;
590e4f976b8b9d74a74b5816146cb11880c3a493929Brian            if (ctx->FragmentProgram._Current
591e4f976b8b9d74a74b5816146cb11880c3a493929Brian                || ctx->ATIFragmentShader._Enabled) {
592e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* do perspective correction but don't divide s, t, r by q */
593e4f976b8b9d74a74b5816146cb11880c3a493929Brian               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
594e4f976b8b9d74a74b5816146cb11880c3a493929Brian               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
595e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
596e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invW = 1.0F / w;
597e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invW;
598e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invW;
599e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invW;
600e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q * invW;
601e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
602e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     dqdx, dqdy, texW, texH,
603e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     s, t, q, invW);
604e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
605e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
606e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
607e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
608e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  w += dwdx;
6092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
6102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
61131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
612e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
6132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
614e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
615e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
616e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
617e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
618e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
619e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     dqdx, dqdy, texW, texH,
620e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     s, t, q, invQ);
621e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
622e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
623e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
624e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
6252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
626d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
627e4f976b8b9d74a74b5816146cb11880c3a493929Brian            span->arrayMask |= SPAN_LAMBDA;
628d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
629d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else {
630e4f976b8b9d74a74b5816146cb11880c3a493929Brian            GLuint i;
631e4f976b8b9d74a74b5816146cb11880c3a493929Brian            if (ctx->FragmentProgram._Current ||
632e4f976b8b9d74a74b5816146cb11880c3a493929Brian                ctx->ATIFragmentShader._Enabled) {
633e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* do perspective correction but don't divide s, t, r by q */
634e4f976b8b9d74a74b5816146cb11880c3a493929Brian               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
635e4f976b8b9d74a74b5816146cb11880c3a493929Brian               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
636e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
637e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invW = 1.0F / w;
638e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invW;
639e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invW;
640e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invW;
641e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q * invW;
642e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
643e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
644e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
645e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
646e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
647e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  w += dwdx;
648e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
649c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
650e4f976b8b9d74a74b5816146cb11880c3a493929Brian            else if (dqdx == 0.0F) {
651e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* Ortho projection or polygon's parallel to window X axis */
652c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
653e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
654e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
655e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
656e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
657e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
658e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
659e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
660e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
661e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
662e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
663c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
664e4f976b8b9d74a74b5816146cb11880c3a493929Brian            else {
665e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
666e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
667e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
668e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
669e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
670e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
671e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
672e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
673e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
674e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
675e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
676e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
677e4f976b8b9d74a74b5816146cb11880c3a493929Brian            }
678e4f976b8b9d74a74b5816146cb11880c3a493929Brian         } /* lambda */
679e4f976b8b9d74a74b5816146cb11880c3a493929Brian      } /* if */
680e4f976b8b9d74a74b5816146cb11880c3a493929Brian   } /* for */
68110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
682e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
683e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
684e4f976b8b9d74a74b5816146cb11880c3a493929Brian
68579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
686abeca8d17d0728e68ec0c7cb9d9ca91b06b560d0Brian * Fill in the arrays->attribs[FRAG_ATTRIB_VARx] arrays from the
687abeca8d17d0728e68ec0c7cb9d9ca91b06b560d0Brian * interpolation values.
688abeca8d17d0728e68ec0c7cb9d9ca91b06b560d0Brian * XXX since interpolants/arrays are getting uniformed, we might merge
689abeca8d17d0728e68ec0c7cb9d9ca91b06b560d0Brian * this with interpolate_texcoords(), interpolate_Fog(), etc. someday.
690bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol */
691f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
692cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_varying(GLcontext *ctx, SWspan *span)
693bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol{
694ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   GLuint var;
695ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   const GLbitfield inputsUsed = ctx->FragmentProgram._Current->Base.InputsRead;
696bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
697bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(span->interpMask & SPAN_VARYING);
698bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   ASSERT(!(span->arrayMask & SPAN_VARYING));
699bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
700bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   span->arrayMask |= SPAN_VARYING;
701bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
702ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   for (var = 0; var < MAX_VARYING; var++) {
703ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      if (inputsUsed & FRAG_BIT_VAR(var)) {
704462d8f5fafcc5ac69ea89cac1222abadded642e2Brian         const GLuint attr = FRAG_ATTRIB_VAR0 + var;
705ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         GLuint j;
706ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         for (j = 0; j < 4; j++) {
707462d8f5fafcc5ac69ea89cac1222abadded642e2Brian            const GLfloat dvdx = span->attrStepX[attr][j];
708462d8f5fafcc5ac69ea89cac1222abadded642e2Brian            GLfloat v = span->attrStart[attr][j];
7099ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian            const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
7109ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian            GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
711ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            GLuint k;
712ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            for (k = 0; k < span->end; k++) {
713ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian               GLfloat invW = 1.0f / w;
714462d8f5fafcc5ac69ea89cac1222abadded642e2Brian               span->array->attribs[attr][k][j] = v * invW;
715ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian               v += dvdx;
716ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian               w += dwdx;
717ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            }
718bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol         }
719bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol      }
720bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol   }
721bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol}
722bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
723bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol
724bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol/**
725f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
726f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian */
727f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brianstatic INLINE void
728f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brianinterpolate_wpos(GLcontext *ctx, SWspan *span)
729f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian{
730f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
731f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLuint i;
732f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   if (span->arrayMask & SPAN_XY) {
733f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      for (i = 0; i < span->end; i++) {
734f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][0] = (GLfloat) span->array->x[i];
735f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][1] = (GLfloat) span->array->y[i];
736f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      }
737f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
738f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   else {
739f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      for (i = 0; i < span->end; i++) {
740f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][0] = (GLfloat) span->x + i;
741f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][1] = (GLfloat) span->y;
742f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      }
743f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
744f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   for (i = 0; i < span->end; i++) {
745f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      wpos[i][2] = (GLfloat) span->array->z[i] / ctx->DrawBuffer->_DepthMaxF;
7469ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian      wpos[i][3] = span->attrStart[FRAG_ATTRIB_WPOS][3]
7479ab512ad8cf3a12f4f7f8494fa99bc9389f217dbBrian                 + i * span->attrStepX[FRAG_ATTRIB_WPOS][3];
748f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
749f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian}
750f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
751f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
752f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian/**
753e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
754e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
755f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
756ea8b68e0f7e7a4025ce662d36380157273ce10a3Brianstipple_polygon_span(GLcontext *ctx, SWspan *span)
75710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
75877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLubyte *mask = span->array->mask;
759733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
760733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
76110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
762ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (span->arrayMask & SPAN_XY) {
763ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      /* arrays of x/y pixel coords */
764ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      GLuint i;
765ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      for (i = 0; i < span->end; i++) {
766ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLint col = span->array->x[i] % 32;
767ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLint row = span->array->y[i] % 32;
768ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLuint stipple = ctx->PolygonStipple[row];
769ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if (((1 << col) & stipple) == 0) {
770ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            mask[i] = 0;
771ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
77210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
773ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   }
774ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   else {
775ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      /* horizontal span of pixels */
776ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      const GLuint highBit = 1 << 31;
777ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      const GLuint stipple = ctx->PolygonStipple[span->y % 32];
778ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      GLuint i, m = highBit >> (GLuint) (span->x % 32);
779ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      for (i = 0; i < span->end; i++) {
780ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if ((m & stipple) == 0) {
781ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            mask[i] = 0;
782ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
783ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         m = m >> 1;
784ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if (m == 0) {
785ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            m = highBit;
786ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
78710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
78810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
7892ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
79010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
79110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
792e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
79379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
794733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
795733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
796733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
797733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
79810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
79910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
800f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE GLuint
801cdb27e8242215271364602995d85607cfc06d441Brian Paulclip_span( GLcontext *ctx, SWspan *span )
80210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
803733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
804733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
805733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
806733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
807733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
808733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
809733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
81077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *x = span->array->x;
81177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *y = span->array->y;
812733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
81377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLubyte *mask = span->array->mask;
814733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
815b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
816b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
817b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
818b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
819b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
820b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
821b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
822b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
823b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
824b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
825b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
826b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
827b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
82810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
829733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
83010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
831733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
832733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
833733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
834733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
835733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
836733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
837733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
838733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
839733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
840733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
841733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
84210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
843733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
844733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
845733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
846733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
8476ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul         _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
84810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
849733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
850733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
851733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
852733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
853733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
85410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
85510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
856733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
857733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
85810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
85910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
86010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
86179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
862e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Apply all the per-fragment opertions to a span of color index fragments
863e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * and write them to the enabled color drawbuffers.
864e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * The 'span' parameter can be considered to be const.  Note that
8657956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
8667956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
86710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
86810f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
869cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_index_span( GLcontext *ctx, SWspan *span)
87010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
871e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
872e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
873e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
87410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
875733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
876b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
877b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
878733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
8797956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
8807956292a765910077f50352d7cd0174e1e66d26cBrian Paul
881733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
882733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
883733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
884733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
885733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
886a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
887733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
88810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
88910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
890733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
891b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
892733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
89386ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
894e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
895e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
896e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
897e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   /* Depth bounds test */
89831e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) {
899e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      if (!_swrast_depth_bounds_test(ctx, span)) {
900e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul         return;
901e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      }
902e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   }
903e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul
904b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
905a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
906b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
907a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
908b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
90977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
91077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
91177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
91277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
91377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
914b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
915b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
916b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
917b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
918b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
919e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
920b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
92110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
922e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
923e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
924e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   /* Stencil and Z testing */
9257956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
9267956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (span->interpMask & SPAN_Z)
92745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
92810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
9297956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
93045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
9317956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
9327956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
9337956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
9342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
9357956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
9367956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
93745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
938e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            span->interpMask = origInterpMask;
9397956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
9407956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
9417956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
9422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
94310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
94410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
945b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
94623ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
947939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
94823ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
949b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
950b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
95123ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
952b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
953b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
954b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
9557956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
9567956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
95710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
9582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
95910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
96010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
96110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
9627956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
963dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled ||
964e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexLogicOpEnabled ||
965e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexMask != 0xffffffff ||
966e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       (span->arrayMask & SPAN_COVERAGE)) {
967e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (span->interpMask & SPAN_INDEX) {
968e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         interpolate_indexes(ctx, span);
969e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
9707956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
97110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
9727956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
973dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled) {
97445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_ci_span(ctx, span);
975e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
976e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
9782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
979e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      const GLfloat *coverage = span->array->coverage;
98077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLuint *index = span->array->index;
981e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLuint i;
98210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
98377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         ASSERT(coverage[i] < 16);
98477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
9855071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
9862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
9875071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
988ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
989ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
990ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
991ba001224a18fa12792696ef393e708e90092127eBrian Paul   {
992ba001224a18fa12792696ef393e708e90092127eBrian Paul      struct gl_framebuffer *fb = ctx->DrawBuffer;
993a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      const GLuint output = 0; /* only frag progs can write to other outputs */
994ba001224a18fa12792696ef393e708e90092127eBrian Paul      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
995ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint indexSave[MAX_WIDTH];
996ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint buf;
997e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
998ba001224a18fa12792696ef393e708e90092127eBrian Paul      if (numDrawBuffers > 1) {
999ba001224a18fa12792696ef393e708e90092127eBrian Paul         /* save indexes for second, third renderbuffer writes */
1000ba001224a18fa12792696ef393e708e90092127eBrian Paul         _mesa_memcpy(indexSave, span->array->index,
1001ba001224a18fa12792696ef393e708e90092127eBrian Paul                      span->end * sizeof(indexSave[0]));
1002ba001224a18fa12792696ef393e708e90092127eBrian Paul      }
1003e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1004ba001224a18fa12792696ef393e708e90092127eBrian Paul      for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) {
1005ba001224a18fa12792696ef393e708e90092127eBrian Paul         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1006ba001224a18fa12792696ef393e708e90092127eBrian Paul         ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
10072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1008e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexLogicOpEnabled) {
1009f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_logicop_ci_span(ctx, rb, span);
1010e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1011e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1012e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
1013f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_mask_ci_span(ctx, rb, span);
1014e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
10152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1016ba001224a18fa12792696ef393e708e90092127eBrian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
1017ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* all fragments have same color index */
1018ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8;
1019ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16;
1020ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLuint index32;
1021ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *value;
1022e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1023ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
1024ba001224a18fa12792696ef393e708e90092127eBrian Paul               index8 = FixedToInt(span->index);
1025ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index8;
1026ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1027ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1028ba001224a18fa12792696ef393e708e90092127eBrian Paul               index16 = FixedToInt(span->index);
1029ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index16;
1030ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1031ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1032ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1033ba001224a18fa12792696ef393e708e90092127eBrian Paul               index32 = FixedToInt(span->index);
1034ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index32;
1035ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1036e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1037ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
1038ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoValues(ctx, rb, span->end, span->array->x,
1039ba001224a18fa12792696ef393e708e90092127eBrian Paul                                 span->array->y, value, span->array->mask);
1040e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
1041ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1042ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
1043ba001224a18fa12792696ef393e708e90092127eBrian Paul                              value, span->array->mask);
1044e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
1045733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1046733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
1047ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* each fragment is a different color */
1048ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8[MAX_WIDTH];
1049ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16[MAX_WIDTH];
1050ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *values;
1051ba001224a18fa12792696ef393e708e90092127eBrian Paul
1052ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
1053ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
1054ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
1055ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index8[k] = (GLubyte) span->array->index[k];
1056ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
1057ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index8;
1058ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1059ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
1060ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
1061ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
1062ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index16[k] = (GLushort) span->array->index[k];
1063ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
1064ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index16;
1065ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1066ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1067ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
1068ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = span->array->index;
1069ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1070e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1071ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
1072ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutValues(ctx, rb, span->end,
1073ba001224a18fa12792696ef393e708e90092127eBrian Paul                             span->array->x, span->array->y,
1074ba001224a18fa12792696ef393e708e90092127eBrian Paul                             values, span->array->mask);
1075ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1076ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1077ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutRow(ctx, rb, span->end, span->x, span->y,
1078e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                          values, span->array->mask);
1079ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1080e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1081ba001224a18fa12792696ef393e708e90092127eBrian Paul
1082ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (buf + 1 < numDrawBuffers) {
1083ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* restore original span values */
1084ba001224a18fa12792696ef393e708e90092127eBrian Paul            _mesa_memcpy(span->array->index, indexSave,
1085ba001224a18fa12792696ef393e708e90092127eBrian Paul                         span->end * sizeof(indexSave[0]));
1086733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1087ba001224a18fa12792696ef393e708e90092127eBrian Paul      } /* for buf */
1088e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
10892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
10907956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
10912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
1092e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1093e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1094e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
109579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1096e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color.  This is used only when
1097f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1098e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
1099f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1100cdb27e8242215271364602995d85607cfc06d441Brian Pauladd_specular(GLcontext *ctx, SWspan *span)
1101e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1102d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   switch (span->array->ChanType) {
1103d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_UNSIGNED_BYTE:
1104d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1105d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1106d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLubyte (*spec)[4] = span->array->color.sz1.spec;
1107d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1108d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1109d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1110d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1111d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1112d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1113d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] = MIN2(r, 255);
1114d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] = MIN2(g, 255);
1115d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] = MIN2(b, 255);
1116d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] = MIN2(a, 255);
1117d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1118d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1119d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1120d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_UNSIGNED_SHORT:
1121d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1122d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1123d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLushort (*spec)[4] = span->array->color.sz2.spec;
1124d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1125d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1126d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint r = rgba[i][RCOMP] + spec[i][RCOMP];
1127d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint g = rgba[i][GCOMP] + spec[i][GCOMP];
1128d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint b = rgba[i][BCOMP] + spec[i][BCOMP];
1129d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint a = rgba[i][ACOMP] + spec[i][ACOMP];
1130d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] = MIN2(r, 65535);
1131d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] = MIN2(g, 65535);
1132d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] = MIN2(b, 65535);
1133d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] = MIN2(a, 65535);
1134d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1135d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1136d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1137d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   case GL_FLOAT:
1138d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      {
1139f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1140f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
1141d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         GLuint i;
1142d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         for (i = 0; i < span->end; i++) {
1143d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][RCOMP] += spec[i][RCOMP];
1144d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][GCOMP] += spec[i][GCOMP];
1145d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][BCOMP] += spec[i][BCOMP];
1146d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            rgba[i][ACOMP] += spec[i][ACOMP];
1147d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1148d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1149d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      break;
1150d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   default:
1151d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      _mesa_problem(ctx, "Invalid datatype in add_specular");
1152e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1153e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1154e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1155e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
115679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1157b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul * Apply antialiasing coverage value to alpha values.
1158b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul */
1159f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1160b88af5b4681d2085cd784b930dc259b66a55347eBrian Paulapply_aa_coverage(SWspan *span)
1161b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul{
1162b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   const GLfloat *coverage = span->array->coverage;
1163b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   GLuint i;
1164b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1165b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
1166b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1167e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1168e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
1169b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] >= 0.0);
1170b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] <= 1.0);
1171b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1172b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1173b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1174b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      GLushort (*rgba)[4] = span->array->color.sz2.rgba;
1175b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1176e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1177e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
1178b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1179b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1180b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else {
1181f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1182b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1183b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
1184b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1185b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1186b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul}
1187b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
1188b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
1189b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul/**
119031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul * Clamp span's float colors to [0,1]
119131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul */
1192f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
119331293910b4e982f2ef54d79aff78f2f854121da1Brian Paulclamp_colors(SWspan *span)
119431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul{
1195f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
119631293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   GLuint i;
119731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->array->ChanType == GL_FLOAT);
119831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   for (i = 0; i < span->end; i++) {
119931293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
120031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
120131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
120231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
120331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   }
120431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul}
120531293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
120631293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
120731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul/**
1208d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul * Convert the span's color arrays to the given type.
1209d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
1210f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1211ea8b68e0f7e7a4025ce662d36380157273ce10a3Brianconvert_color_type(SWspan *span, GLenum newType)
1212d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul{
1213f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   GLvoid *src, *dst;
1214f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1215f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz1.rgba;
1216f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1217f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1218f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      src = span->array->color.sz2.rgba;
1219f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1220f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
1221f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      src = span->array->attribs[FRAG_ATTRIB_COL0];
1222f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1223f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (newType == GL_UNSIGNED_BYTE) {
1224f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz1.rgba;
1225f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1226f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (newType == GL_UNSIGNED_BYTE) {
1227f971e24cf0341dd2779196a0836327b74fc82336Brian Paul      dst = span->array->color.sz2.rgba;
1228f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1229f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
1230f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      dst = span->array->attribs[FRAG_ATTRIB_COL0];
1231f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1232d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1233f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   _mesa_convert_colors(span->array->ChanType, src,
1234f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        newType, dst,
1235f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        span->end, span->array->mask);
1236d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1237d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   span->array->ChanType = newType;
1238d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul}
1239d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1240d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1241d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1242d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
124361c89be3135cedc795e48d36283769298e250837Brian Paul * Apply fragment shader, fragment program or normal texturing to span.
124461c89be3135cedc795e48d36283769298e250837Brian Paul */
1245f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
124661c89be3135cedc795e48d36283769298e250837Brian Paulshade_texture_span(GLcontext *ctx, SWspan *span)
124761c89be3135cedc795e48d36283769298e250837Brian Paul{
124861c89be3135cedc795e48d36283769298e250837Brian Paul   /* Now we need the rgba array, fill it in if needed */
124961c89be3135cedc795e48d36283769298e250837Brian Paul   if (span->interpMask & SPAN_RGBA)
125061c89be3135cedc795e48d36283769298e250837Brian Paul      interpolate_colors(span);
125161c89be3135cedc795e48d36283769298e250837Brian Paul
1252f614a6190562e550257afca0d04e3846648942e8Brian Paul   if (ctx->Texture._EnabledCoordUnits && (span->interpMask & SPAN_TEXTURE))
1253f614a6190562e550257afca0d04e3846648942e8Brian Paul      interpolate_texcoords(ctx, span);
1254f614a6190562e550257afca0d04e3846648942e8Brian Paul
125512ef1fbefcee964b715783d3ade6b69b2c699ed8Brian   if (ctx->FragmentProgram._Current ||
125661c89be3135cedc795e48d36283769298e250837Brian Paul       ctx->ATIFragmentShader._Enabled) {
125761c89be3135cedc795e48d36283769298e250837Brian Paul
125861c89be3135cedc795e48d36283769298e250837Brian Paul      /* use float colors if running a fragment program or shader */
125961c89be3135cedc795e48d36283769298e250837Brian Paul      const GLenum oldType = span->array->ChanType;
126061c89be3135cedc795e48d36283769298e250837Brian Paul      const GLenum newType = GL_FLOAT;
126161c89be3135cedc795e48d36283769298e250837Brian Paul      if (oldType != newType) {
126261c89be3135cedc795e48d36283769298e250837Brian Paul         GLvoid *src = (oldType == GL_UNSIGNED_BYTE)
126361c89be3135cedc795e48d36283769298e250837Brian Paul            ? (GLvoid *) span->array->color.sz1.rgba
126461c89be3135cedc795e48d36283769298e250837Brian Paul            : (GLvoid *) span->array->color.sz2.rgba;
126561c89be3135cedc795e48d36283769298e250837Brian Paul         _mesa_convert_colors(oldType, src,
1266f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian                              newType, span->array->attribs[FRAG_ATTRIB_COL0],
126761c89be3135cedc795e48d36283769298e250837Brian Paul                              span->end, span->array->mask);
126861c89be3135cedc795e48d36283769298e250837Brian Paul         span->array->ChanType = newType;
126961c89be3135cedc795e48d36283769298e250837Brian Paul      }
127061c89be3135cedc795e48d36283769298e250837Brian Paul
127161c89be3135cedc795e48d36283769298e250837Brian Paul      /* fragment programs/shaders may need specular, fog and Z coords */
127261c89be3135cedc795e48d36283769298e250837Brian Paul      if (span->interpMask & SPAN_SPEC)
127361c89be3135cedc795e48d36283769298e250837Brian Paul         interpolate_specular(span);
127461c89be3135cedc795e48d36283769298e250837Brian Paul
127561c89be3135cedc795e48d36283769298e250837Brian Paul      if (span->interpMask & SPAN_FOG)
127661c89be3135cedc795e48d36283769298e250837Brian Paul         interpolate_fog(ctx, span);
127761c89be3135cedc795e48d36283769298e250837Brian Paul
127861c89be3135cedc795e48d36283769298e250837Brian Paul      if (span->interpMask & SPAN_Z)
127961c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_span_interpolate_z (ctx, span);
128061c89be3135cedc795e48d36283769298e250837Brian Paul
12810bf5dbe002a64e198f55724cc1542602c012490fBrian      if (ctx->Shader.CurrentProgram && span->interpMask & SPAN_VARYING)
1282828d15a6e0907fe4bb7c564d453a2b1a05f109bcBrian Paul         interpolate_varying(ctx, span);
128312ef1fbefcee964b715783d3ade6b69b2c699ed8Brian
1284f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      if (ctx->FragmentProgram._Current &&
1285f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian          (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_WPOS))
1286f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         interpolate_wpos(ctx, span);
1287f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
128812ef1fbefcee964b715783d3ade6b69b2c699ed8Brian      /* Run fragment program/shader now */
128912ef1fbefcee964b715783d3ade6b69b2c699ed8Brian      if (ctx->FragmentProgram._Current) {
129061c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_program(ctx, span);
129161c89be3135cedc795e48d36283769298e250837Brian Paul      }
129261c89be3135cedc795e48d36283769298e250837Brian Paul      else {
129361c89be3135cedc795e48d36283769298e250837Brian Paul         ASSERT(ctx->ATIFragmentShader._Enabled);
129461c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_shader(ctx, span);
129561c89be3135cedc795e48d36283769298e250837Brian Paul      }
129661c89be3135cedc795e48d36283769298e250837Brian Paul   }
129761c89be3135cedc795e48d36283769298e250837Brian Paul   else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE)) {
129861c89be3135cedc795e48d36283769298e250837Brian Paul      /* conventional texturing */
129961c89be3135cedc795e48d36283769298e250837Brian Paul      _swrast_texture_span(ctx, span);
130061c89be3135cedc795e48d36283769298e250837Brian Paul   }
130161c89be3135cedc795e48d36283769298e250837Brian Paul}
130261c89be3135cedc795e48d36283769298e250837Brian Paul
130361c89be3135cedc795e48d36283769298e250837Brian Paul
130461c89be3135cedc795e48d36283769298e250837Brian Paul
130561c89be3135cedc795e48d36283769298e250837Brian Paul/**
1306a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Apply all the per-fragment operations to a span.
1307a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * This now includes texturing (_swrast_write_texture_span() is history).
1308f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
13097956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
13107956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
131178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
131278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
1313cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
131478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
131561c89be3135cedc795e48d36283769298e250837Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
131678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1317e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
1318e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
1319c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul   const GLenum chanType = span->array->ChanType;
132012ef1fbefcee964b715783d3ade6b69b2c699ed8Brian   const GLboolean shader = (ctx->FragmentProgram._Current
132112ef1fbefcee964b715783d3ade6b69b2c699ed8Brian                             || ctx->ATIFragmentShader._Enabled);
132261c89be3135cedc795e48d36283769298e250837Brian Paul   const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
1323bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   GLboolean deferredTexture;
132461c89be3135cedc795e48d36283769298e250837Brian Paul
1325bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /*
1326bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1327bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul          span->interpMask, span->arrayMask);
1328bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   */
1329f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
133031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->primitive == GL_POINT ||
133131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_LINE ||
133231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul	  span->primitive == GL_POLYGON ||
133331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_BITMAP);
1334733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
13357956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
133631293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT((span->interpMask & SPAN_RGBA) ^ (span->arrayMask & SPAN_RGBA));
133778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1338bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /* check for conditions that prevent deferred shading */
1339bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   if (ctx->Color.AlphaEnabled) {
1340bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      /* alpha test depends on post-texture/shader colors */
1341bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      deferredTexture = GL_FALSE;
1342bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   }
1343bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   else if (shaderOrTexture) {
134412ef1fbefcee964b715783d3ade6b69b2c699ed8Brian      if (ctx->FragmentProgram._Current) {
1345ed324db249d068f14646eced55d106b5fe6b889cBrian Paul         if (ctx->FragmentProgram.Current->Base.OutputsWritten
1346ed324db249d068f14646eced55d106b5fe6b889cBrian Paul             & (1 << FRAG_RESULT_DEPR)) {
134712ef1fbefcee964b715783d3ade6b69b2c699ed8Brian            /* Z comes from fragment program/shader */
1348ed324db249d068f14646eced55d106b5fe6b889cBrian Paul            deferredTexture = GL_FALSE;
1349ed324db249d068f14646eced55d106b5fe6b889cBrian Paul         }
1350ed324db249d068f14646eced55d106b5fe6b889cBrian Paul         else {
1351ed324db249d068f14646eced55d106b5fe6b889cBrian Paul            deferredTexture = GL_TRUE;
1352ed324db249d068f14646eced55d106b5fe6b889cBrian Paul         }
1353bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      }
1354bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      else {
1355bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         /* ATI frag shader or conventional texturing */
1356bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul         deferredTexture = GL_TRUE;
1357bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      }
1358bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   }
1359bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   else {
1360bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      /* no texturing or shadering */
1361bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul      deferredTexture = GL_FALSE;
1362bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   }
1363ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1364bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /* Fragment write masks */
1365733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1366733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1367733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1368733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1369733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
1370a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
1371733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
137278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
137378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1374a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Clip to window/scissor box */
1375b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1376733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1377733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
137878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
137978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
138078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1381b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1382a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
1383b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1384a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
1385b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
138677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
138777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
138877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
138977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
139077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1391b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1392b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1393b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1394b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1395b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
139678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1397b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1398733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
139978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
140078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
140132340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* This is the normal place to compute the resulting fragment color/Z.
140232340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * As an optimization, we try to defer this until after Z/stencil
140332340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * testing in order to try to avoid computing colors that we won't
140432340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * actually need.
1405a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
140661c89be3135cedc795e48d36283769298e250837Brian Paul   if (shaderOrTexture && !deferredTexture) {
140761c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
140861c89be3135cedc795e48d36283769298e250837Brian Paul   }
1409c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul
141061c89be3135cedc795e48d36283769298e250837Brian Paul   /* Do the alpha test */
141161c89be3135cedc795e48d36283769298e250837Brian Paul   if (ctx->Color.AlphaEnabled) {
141261c89be3135cedc795e48d36283769298e250837Brian Paul      if (!_swrast_alpha_test(ctx, span)) {
141361c89be3135cedc795e48d36283769298e250837Brian Paul         goto end;
141478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
141578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
141678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1417f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1418f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1419f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
142045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
142178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1422e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
1423a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Combined Z/stencil tests */
142445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1425c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1426f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
142771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1428e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (ctx->DrawBuffer->Visual.depthBits > 0) {
1429a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Just regular depth testing */
1430f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1431f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
143245bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
1433c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1434f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
143571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
143671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
143771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1438b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
143923ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1440939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
144123ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1442b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1443b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
144423ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1445b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1446b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
1447b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
1448a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1449f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1450f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1451f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1452c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul      goto end;
145371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
145471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
145532340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* If we were able to defer fragment color computation to now, there's
145632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * a good chance that many fragments will have already been killed by
145732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * Z/stencil testing.
1458a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
145932340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   if (deferredTexture) {
146061c89be3135cedc795e48d36283769298e250837Brian Paul      ASSERT(shaderOrTexture);
146161c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
146261c89be3135cedc795e48d36283769298e250837Brian Paul   }
1463d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
146461c89be3135cedc795e48d36283769298e250837Brian Paul   if ((span->arrayMask & SPAN_RGBA) == 0) {
146561c89be3135cedc795e48d36283769298e250837Brian Paul      interpolate_colors(span);
146671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
146771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1468f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
14692ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
147061c89be3135cedc795e48d36283769298e250837Brian Paul   if (!shader) {
1471dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      /* Add base and specular colors */
1472dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      if (ctx->Fog.ColorSumEnabled ||
1473dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul          (ctx->Light.Enabled &&
1474dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1475dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         if (span->interpMask & SPAN_SPEC) {
1476e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            interpolate_specular(span);
1477dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul         }
1478a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         if (span->arrayMask & SPAN_SPEC) {
1479d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            add_specular(ctx, span);
1480a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
1481a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         else {
1482a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul            /* We probably added the base/specular colors during the
1483a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             * vertex stage!
1484a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul             */
1485a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         }
148671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
148771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
148871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
14896e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
149009da0b8e6621a831e3eeb9381430f2bed18a22adBrian Paul   if (swrast->_FogEnabled) {
149145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_rgba_span(ctx, span);
149271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1493f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
149471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
14952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1496b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      apply_aa_coverage(span);
149771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
149871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1499ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
15000b26e826bda0da7aeec9a79ee07fe21d54bb1263Brian Paul   if (ctx->Color.ClampFragmentColor == GL_TRUE &&
150131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul       span->array->ChanType == GL_FLOAT) {
150231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      clamp_colors(span);
1503ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   }
1504ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul
1505ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
1506ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
1507ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
1508ba001224a18fa12792696ef393e708e90092127eBrian Paul   {
1509ba001224a18fa12792696ef393e708e90092127eBrian Paul      struct gl_framebuffer *fb = ctx->DrawBuffer;
1510a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      const GLuint output = 0; /* only frag progs can write to other outputs */
1511ba001224a18fa12792696ef393e708e90092127eBrian Paul      const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
1512ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLchan rgbaSave[MAX_WIDTH][4];
1513ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint buf;
1514e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1515d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      if (numDrawBuffers > 0) {
1516d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         if (fb->_ColorDrawBuffers[output][0]->DataType
1517d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul             != span->array->ChanType) {
1518ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            convert_color_type(span,
1519d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul                               fb->_ColorDrawBuffers[output][0]->DataType);
1520d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
1521d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1522d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1523ba001224a18fa12792696ef393e708e90092127eBrian Paul      if (numDrawBuffers > 1) {
1524ba001224a18fa12792696ef393e708e90092127eBrian Paul         /* save colors for second, third renderbuffer writes */
1525ba001224a18fa12792696ef393e708e90092127eBrian Paul         _mesa_memcpy(rgbaSave, span->array->rgba,
1526ba001224a18fa12792696ef393e708e90092127eBrian Paul                      4 * span->end * sizeof(GLchan));
152771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
152871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1529ba001224a18fa12792696ef393e708e90092127eBrian Paul      for (buf = 0; buf < numDrawBuffers; buf++) {
1530ba001224a18fa12792696ef393e708e90092127eBrian Paul         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
1531f971e24cf0341dd2779196a0836327b74fc82336Brian Paul         ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
153271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1533ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (ctx->Color._LogicOpEnabled) {
1534f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_logicop_rgba_span(ctx, rb, span);
1535ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1536ba001224a18fa12792696ef393e708e90092127eBrian Paul         else if (ctx->Color.BlendEnabled) {
1537f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_blend_span(ctx, rb, span);
1538ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1539ba001224a18fa12792696ef393e708e90092127eBrian Paul
1540ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (colorMask != 0xffffffff) {
1541f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_mask_rgba_span(ctx, rb, span);
1542ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1543ba001224a18fa12792696ef393e708e90092127eBrian Paul
1544ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (span->arrayMask & SPAN_XY) {
1545ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* array of pixel coords */
1546ba001224a18fa12792696ef393e708e90092127eBrian Paul            ASSERT(rb->PutValues);
1547ba001224a18fa12792696ef393e708e90092127eBrian Paul            rb->PutValues(ctx, rb, span->end,
1548ba001224a18fa12792696ef393e708e90092127eBrian Paul                          span->array->x, span->array->y,
1549ba001224a18fa12792696ef393e708e90092127eBrian Paul                          span->array->rgba, span->array->mask);
1550ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1551ba001224a18fa12792696ef393e708e90092127eBrian Paul         else {
1552ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* horizontal run of pixels */
1553ba001224a18fa12792696ef393e708e90092127eBrian Paul            ASSERT(rb->PutRow);
1554ba001224a18fa12792696ef393e708e90092127eBrian Paul            rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba,
1555ba001224a18fa12792696ef393e708e90092127eBrian Paul                       span->writeAll ? NULL: span->array->mask);
1556ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1557ba001224a18fa12792696ef393e708e90092127eBrian Paul
1558ba001224a18fa12792696ef393e708e90092127eBrian Paul         if (buf + 1 < numDrawBuffers) {
1559ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* restore original span values */
1560ba001224a18fa12792696ef393e708e90092127eBrian Paul            _mesa_memcpy(span->array->rgba, rgbaSave,
1561ba001224a18fa12792696ef393e708e90092127eBrian Paul                         4 * span->end * sizeof(GLchan));
1562ba001224a18fa12792696ef393e708e90092127eBrian Paul         }
1563ba001224a18fa12792696ef393e708e90092127eBrian Paul      } /* for buf */
15641e3223c02a2f6155beb5784cadbea1f46703829aBrian Paul
156571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
156671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1567c3caaa3dd45809e672177ab322445fe51d03af25Brian Paulend:
156861c89be3135cedc795e48d36283769298e250837Brian Paul   /* restore these values before returning */
1569e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   span->interpMask = origInterpMask;
1570f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
157161c89be3135cedc795e48d36283769298e250837Brian Paul   span->array->ChanType = chanType;
157210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
157310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1574e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
157579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1576ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian * Read RGBA pixels from a renderbuffer.  Clipping will be done to prevent
1577e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1578ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian * \param dstType  datatype for returned colors
157976e778dce59aa6f290db50242df945943fc47b05Brian Paul * \param rgba  the returned colors
1580e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
15815071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1582e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
158376e778dce59aa6f290db50242df945943fc47b05Brian Paul                        GLuint n, GLint x, GLint y, GLenum dstType,
158476e778dce59aa6f290db50242df945943fc47b05Brian Paul                        GLvoid *rgba)
1585e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1586e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1587e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1588a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1589a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1590e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1591e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* XXX maybe leave rgba values undefined? */
15926ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul      _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1593e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1594e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1595e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1596e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
15977e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1598e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1599e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1600e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1601e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1602e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1603e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1604a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1605a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1606e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1607e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1608a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1609e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1610e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1611a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1612e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1613e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1614e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1615e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1616e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1617e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1618e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1619e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1620e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1621e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1622e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1623bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb);
1624bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->GetRow);
1625bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
162676e778dce59aa6f290db50242df945943fc47b05Brian Paul
162776e778dce59aa6f290db50242df945943fc47b05Brian Paul      if (rb->DataType == dstType) {
162876e778dce59aa6f290db50242df945943fc47b05Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y,
162976e778dce59aa6f290db50242df945943fc47b05Brian Paul                    (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
163076e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
163176e778dce59aa6f290db50242df945943fc47b05Brian Paul      else {
163276e778dce59aa6f290db50242df945943fc47b05Brian Paul         GLuint temp[MAX_WIDTH * 4];
163376e778dce59aa6f290db50242df945943fc47b05Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, temp);
163476e778dce59aa6f290db50242df945943fc47b05Brian Paul         _mesa_convert_colors(rb->DataType, temp,
163576e778dce59aa6f290db50242df945943fc47b05Brian Paul                   dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
163676e778dce59aa6f290db50242df945943fc47b05Brian Paul                   length, NULL);
163776e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
1638e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1639e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1640e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1641e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
164279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1643ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian * Read CI pixels from a renderbuffer.  Clipping will be done to prevent
1644e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1645e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
16465071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1647e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1648e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                         GLuint n, GLint x, GLint y, GLuint index[] )
1649e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1650e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1651e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1652a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1653a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1654e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1655e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      _mesa_bzero(index, n * sizeof(GLuint));
1656e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1657e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1658e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1659e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
16607e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1661e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1662e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1663e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1664e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1665e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1666e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1667a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1668a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1669e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1670e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1671a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1672e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1673e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1674a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1675e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1676e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1677e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1678e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1679e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1680e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1681e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1682e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1683e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1684e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1685e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1686e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->GetRow);
1687e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1688e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1689e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (rb->DataType == GL_UNSIGNED_BYTE) {
1690e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLubyte index8[MAX_WIDTH];
1691e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1692e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index8);
1693e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1694e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index8[i];
1695e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1696e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_SHORT) {
1697e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLushort index16[MAX_WIDTH];
1698e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1699e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index16);
1700e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1701e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index16[i];
1702e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1703e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_INT) {
1704e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1705e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1706e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1707e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
170867074332728acba86da7630353673b458713bb8aBrian Paul
170967074332728acba86da7630353673b458713bb8aBrian Paul
171067074332728acba86da7630353673b458713bb8aBrian Paul/**
171167074332728acba86da7630353673b458713bb8aBrian Paul * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
171267074332728acba86da7630353673b458713bb8aBrian Paul * reading values outside the buffer bounds.
171367074332728acba86da7630353673b458713bb8aBrian Paul * We can use this for reading any format/type of renderbuffer.
1714ba001224a18fa12792696ef393e708e90092127eBrian Paul * \param valueSize is the size in bytes of each value (pixel) put into the
171567074332728acba86da7630353673b458713bb8aBrian Paul *                  values array.
171667074332728acba86da7630353673b458713bb8aBrian Paul */
171767074332728acba86da7630353673b458713bb8aBrian Paulvoid
171867074332728acba86da7630353673b458713bb8aBrian Paul_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
171967074332728acba86da7630353673b458713bb8aBrian Paul                   GLuint count, const GLint x[], const GLint y[],
172067074332728acba86da7630353673b458713bb8aBrian Paul                   void *values, GLuint valueSize)
172167074332728acba86da7630353673b458713bb8aBrian Paul{
172267074332728acba86da7630353673b458713bb8aBrian Paul   GLuint i, inCount = 0, inStart = 0;
172367074332728acba86da7630353673b458713bb8aBrian Paul
172467074332728acba86da7630353673b458713bb8aBrian Paul   for (i = 0; i < count; i++) {
1725ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      if (x[i] >= 0 && y[i] >= 0 &&
1726ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian	  x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
172767074332728acba86da7630353673b458713bb8aBrian Paul         /* inside */
172867074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount == 0)
172967074332728acba86da7630353673b458713bb8aBrian Paul            inStart = i;
173067074332728acba86da7630353673b458713bb8aBrian Paul         inCount++;
173167074332728acba86da7630353673b458713bb8aBrian Paul      }
173267074332728acba86da7630353673b458713bb8aBrian Paul      else {
173367074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount > 0) {
173467074332728acba86da7630353673b458713bb8aBrian Paul            /* read [inStart, inStart + inCount) */
173567074332728acba86da7630353673b458713bb8aBrian Paul            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
173667074332728acba86da7630353673b458713bb8aBrian Paul                          (GLubyte *) values + inStart * valueSize);
173767074332728acba86da7630353673b458713bb8aBrian Paul            inCount = 0;
173867074332728acba86da7630353673b458713bb8aBrian Paul         }
173967074332728acba86da7630353673b458713bb8aBrian Paul      }
174067074332728acba86da7630353673b458713bb8aBrian Paul   }
174167074332728acba86da7630353673b458713bb8aBrian Paul   if (inCount > 0) {
174267074332728acba86da7630353673b458713bb8aBrian Paul      /* read last values */
174367074332728acba86da7630353673b458713bb8aBrian Paul      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
174467074332728acba86da7630353673b458713bb8aBrian Paul                    (GLubyte *) values + inStart * valueSize);
174567074332728acba86da7630353673b458713bb8aBrian Paul   }
174667074332728acba86da7630353673b458713bb8aBrian Paul}
17473fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17483fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17493fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul/**
17503fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1751a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
17523fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul */
17533fd819aef8139761ce86cb8d763de83a11c81b33Brian Paulvoid
17543fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
17553fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                GLuint count, GLint x, GLint y,
17563fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                const GLvoid *values, GLuint valueSize)
17573fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul{
17583fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   GLint skip = 0;
17593fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
1760ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (y < 0 || y >= (GLint) rb->Height)
17613fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* above or below */
17623fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
1763ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
17643fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* entirely left or right */
17653fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
1766ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if ((GLint) (x + count) > (GLint) rb->Width) {
17673fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* right clip */
17683fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      GLint clip = x + count - rb->Width;
17693fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= clip;
17703fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
17713fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17723fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x < 0) {
17733fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* left clip */
17743fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      skip = -x;
17753fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      x = 0;
17763fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= skip;
17773fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
17783fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
17793fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   rb->PutRow(ctx, rb, count, x, y,
17803fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul              (const GLubyte *) values + skip * valueSize, NULL);
17813fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul}
1782f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1783f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1784f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul/**
1785f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1786a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
1787f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul */
1788f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paulvoid
1789f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1790f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLuint count, GLint x, GLint y,
1791f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLvoid *values, GLuint valueSize)
1792f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul{
1793f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   GLint skip = 0;
1794f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1795ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (y < 0 || y >= (GLint) rb->Height)
1796f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* above or below */
1797f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1798ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1799f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* entirely left or right */
1800f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1801f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + count > rb->Width) {
1802f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* right clip */
1803f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      GLint clip = x + count - rb->Width;
1804f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= clip;
1805f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1806f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1807f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x < 0) {
1808f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* left clip */
1809f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      skip = -x;
1810f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      x = 0;
1811f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= skip;
1812f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1813f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1814f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1815f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul}
1816a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1817a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1818a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul/**
1819a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Get RGBA pixels from the given renderbuffer.  Put the pixel colors into
1820a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * the span's specular color arrays.  The specular color arrays should no
1821a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * longer be needed by time this function is called.
1822a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Used by blending, logicop and masking functions.
1823a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \return pointer to the colors we read.
1824a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul */
1825a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paulvoid *
1826a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1827cdb27e8242215271364602995d85607cfc06d441Brian Paul                      SWspan *span)
1828a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul{
182976e778dce59aa6f290db50242df945943fc47b05Brian Paul   const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1830a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   void *rbPixels;
1831a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1832a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /*
1833a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    * Determine pixel size (in bytes).
1834a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    * Point rbPixels to a temporary space (use specular color arrays).
1835a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    */
1836a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1837a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz1.spec;
1838a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1839a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
1840a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      rbPixels = span->array->color.sz2.spec;
1841a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1842a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1843f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      rbPixels = span->array->attribs[FRAG_ATTRIB_COL1];
1844a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1845a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1846a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /* Get destination values from renderbuffer */
1847a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->arrayMask & SPAN_XY) {
1848a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1849a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                         rbPixels, pixelSize);
1850a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1851a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1852a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1853a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                      rbPixels, pixelSize);
1854a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1855a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1856a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   return rbPixels;
1857a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul}
1858