s_span.c revision ad8cd6111e022c90c93df106c0fde6f64d205816
1ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul/* $Id: s_span.c,v 1.52 2002/11/09 21:28:41 brianp Exp $ */
2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
3e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
4e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library
5ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul * Version:  5.0
622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
79927f1978da8530416f699d084dda099720e43e6Brian Paul * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
822144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * copy of this software and associated documentation files (the "Software"),
11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to deal in the Software without restriction, including without limitation
12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
14e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Software is furnished to do so, subject to the following conditions:
1522144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
16e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice shall be included
17e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in all copies or substantial portions of the Software.
1822144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
26e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
27e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
2879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
29bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul * \file swrast/s_span.c
3079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \brief Span processing functions used by all rasterization functions.
3179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * This is where all the per-fragment tests are performed
3279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \author Brian Paul
33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
34e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
35e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "glheader.h"
36e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "colormac.h"
3771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul#include "context.h"
38e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "macros.h"
3931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul#include "mmath.h"
403c63452e64df7e10aa073c6c3b9492b1d7dabbb8Brian Paul#include "imports.h"
41e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alpha.h"
43e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alphabuf.h"
44e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
45cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
48e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
51e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
52e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_texture.h"
53e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
5579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's Z interpolation values to the RasterPos Z.
572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_z( GLcontext *ctx, struct sw_span *span )
612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.depthBits <= 16)
63ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F);
642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else
65ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->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
762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_fog( GLcontext *ctx, struct sw_span *span )
772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
78c9ceef41fe89f5ba6e16ec51c1f9b7bfd8119c64Brian Paul   span->fog = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->fogStep = 0;
802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->interpMask |= SPAN_FOG;
812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's color or index interpolation values to the RasterPos color.
862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels.
872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul_mesa_span_default_color( GLcontext *ctx, struct sw_span *span )
902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.rgbMode) {
922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan r, g, b, a;
932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red = r;
992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = g;
1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue = b;
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = a;
1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red   = IntToFixed(r);
1042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = IntToFixed(g);
1052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue  = IntToFixed(b);
1062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = IntToFixed(a);
1072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->redStep = 0;
1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->greenStep = 0;
1102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blueStep = 0;
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alphaStep = 0;
1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_RGBA;
1132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->index = IntToFixed(ctx->Current.RasterIndex);
1162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->indexStep = 0;
1172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_INDEX;
1182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1224753d60dd070bb08d0116076bcc08025c86ce857Brian Paul/**
1234753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Init span's texcoord interpolation values to the RasterPos texcoords.
1244753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Used during setup for glDraw/CopyPixels.
1254753d60dd070bb08d0116076bcc08025c86ce857Brian Paul */
1264753d60dd070bb08d0116076bcc08025c86ce857Brian Paulvoid
1274753d60dd070bb08d0116076bcc08025c86ce857Brian Paul_mesa_span_default_texcoords( GLcontext *ctx, struct sw_span *span )
1284753d60dd070bb08d0116076bcc08025c86ce857Brian Paul{
1294753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   GLuint i;
1304753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1315f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul      COPY_4V(span->tex[i], ctx->Current.RasterTexCoords[i]);
1325f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul      ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
1335f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul      ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
1344753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   }
1354753d60dd070bb08d0116076bcc08025c86ce857Brian Paul   span->interpMask |= SPAN_TEXTURE;
1364753d60dd070bb08d0116076bcc08025c86ce857Brian Paul}
1374753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
1384753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
1392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.rgba array from the interpolation values */
1402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_colors(GLcontext *ctx, struct sw_span *span)
1422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed r = span->red;
1442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed g = span->green;
1452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed b = span->blue;
1462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed a = span->alpha;
1472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint dr = span->redStep;
1482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint dg = span->greenStep;
1492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint db = span->blueStep;
1502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint da = span->alphaStep;
1512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
15277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLchan (*rgba)[4] = span->array->rgba;
1532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
1542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
155b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_RGBA)  &&
156b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_RGBA));
1572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
1592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan color[4];
1612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[RCOMP] = FixedToChan(r);
1622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[GCOMP] = FixedToChan(g);
1632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[BCOMP] = FixedToChan(b);
1642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      color[ACOMP] = FixedToChan(a);
1652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
16677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         COPY_CHAN4(span->array->rgba[i], color);
1672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
1712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
1722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][RCOMP] = FixedToChan(r);
1732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][GCOMP] = FixedToChan(g);
1742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][BCOMP] = FixedToChan(b);
1752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         rgba[i][ACOMP] = FixedToChan(a);
1762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += dr;
1772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += dg;
1782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += db;
1792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         a += da;
1802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
1812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_RGBA;
1832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
1842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
1872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
1882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_indexes(GLcontext *ctx, struct sw_span *span)
1892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
1902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
1912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
1922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
19377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLuint *indexes = span->array->index;
1942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
195b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_INDEX)  &&
196b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_INDEX));
1972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
1992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
2002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
2012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
2032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
2072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
2082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
2092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
2102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
2132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
21677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul/* Fill in the span.->array->spec array from the interpolation values */
2172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
2182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_specular(GLcontext *ctx, struct sw_span *span)
2192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->interpMask & SPAN_FLAT) {
2212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
2222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan r = FixedToChan(span->specRed);
2232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan g = FixedToChan(span->specGreen);
2242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      const GLchan b = FixedToChan(span->specBlue);
2252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
22777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][RCOMP] = r;
22877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][GCOMP] = g;
22977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][BCOMP] = b;
2302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
2342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
2352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat r = span->specRed;
2362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat g = span->specGreen;
2372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfloat b = span->specBlue;
2382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
2392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed r = span->specRed;
2402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed g = span->specGreen;
2412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed b = span->specBlue;
2422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
2432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
2442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < span->end; i++) {
24577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][RCOMP] = FixedToChan(r);
24677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][GCOMP] = FixedToChan(g);
24777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         span->array->spec[i][BCOMP] = FixedToChan(b);
2482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         r += span->specRedStep;
2492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         g += span->specGreenStep;
2502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         b += span->specBlueStep;
2512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_SPEC;
2542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */
258711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
259711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul_mesa_span_interpolate_z( const GLcontext *ctx, struct sw_span *span )
2602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
2622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
2632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
264b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT((span->interpMask & SPAN_Z)  &&
265b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  !(span->arrayMask & SPAN_Z));
2662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.depthBits <= 16) {
2682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
26977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLdepth *z = span->array->z;
270ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      for (i = 0; i < n; i++) {
27177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = FixedToInt(zval);
2722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
2732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
2762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
2772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
27877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLdepth *z = span->array->z;
2792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
28077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = zval;
2812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
2822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
2832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
2842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
2852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
2862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
288c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
28931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
290c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
291c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
29231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
29331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
29431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
29531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
296c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
29731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
29831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
29931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
30031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
30131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat x = sqrt(dudx * dudx + dvdx * dvdx);
30231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat y = sqrt(dudy * dudy + dvdy * dvdy);
30331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
30431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
30531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
306c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
307c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
308c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
30931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
31031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/*
31131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This is a faster approximation
312c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
31331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
31431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
31531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
31631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
317c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
31831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
31931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
32031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
32131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
32231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
32331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
32431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
32531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
32631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
32731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
32831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
32931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
33031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
33131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
332c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
333c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
334c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/*
335c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Fill in the span.texcoords array from the interpolation values.
336c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * XXX We could optimize here for the case when dq = 0.  That would
337c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * usually be the case when using an orthographic projection.
338c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
3392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
3402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_texcoords(GLcontext *ctx, struct sw_span *span)
3412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   ASSERT(span->interpMask & SPAN_TEXTURE);
343b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(!(span->arrayMask & SPAN_TEXTURE));
3442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3458afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   if (ctx->Texture._EnabledUnits > 1) {
34631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* multitexture */
34731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      GLuint u;
348b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
34931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
35031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         if (ctx->Texture.Unit[u]._ReallyEnabled) {
35131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current;
35231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
35331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
35431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            if (needLambda) {
35577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
35677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
3578afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul               const GLfloat texW = (GLfloat) img->WidthScale;
3588afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul               const GLfloat texH = (GLfloat) img->HeightScale;
35931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
36031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdy = span->texStepY[u][0];
36131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
36231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdy = span->texStepY[u][1];
36331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
36431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
36531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdy = span->texStepY[u][3];
3662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
3672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
3682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
3692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
3702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
37131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               for (i = 0; i < span->end; i++) {
3722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
37377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                  texcoord[i][0] = s * invQ;
37477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                  texcoord[i][1] = t * invQ;
37577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                  texcoord[i][2] = r * invQ;
37677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                  lambda[i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
37777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                             dqdx, dqdy, texW, texH,
37877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                             s, t, q, invQ);
37931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  s += dsdx;
38031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  t += dtdx;
38131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  r += drdx;
38231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                  q += dqdx;
3832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
38431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               span->arrayMask |= SPAN_LAMBDA;
3852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
38631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
38777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat (*texcoord)[4] = span->array->texcoords[u];
38877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               GLfloat *lambda = span->array->lambda[u];
38931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dsdx = span->texStepX[u][0];
39031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dtdx = span->texStepX[u][1];
39131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat drdx = span->texStepX[u][2];
39231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               const GLfloat dqdx = span->texStepX[u][3];
3932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat s = span->tex[u][0];
3942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat t = span->tex[u][1];
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat r = span->tex[u][2];
3962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLfloat q = span->tex[u][3];
3972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               GLuint i;
39831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               if (dqdx == 0.0) {
399c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  /* Ortho projection or polygon's parallel to window X axis */
4002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
401c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
40277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
40377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
40477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
40577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
40631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
40731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
40831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
409c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
410c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               }
411c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               else {
412c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  for (i = 0; i < span->end; i++) {
413c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
41477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][0] = s * invQ;
41577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][1] = t * invQ;
41677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     texcoord[i][2] = r * invQ;
41777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                     lambda[i] = 0.0;
41831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     s += dsdx;
41931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     t += dtdx;
42031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     r += drdx;
42131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul                     q += dqdx;
422c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul                  }
4232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
42431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            } /* lambda */
42531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         } /* if */
42631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      } /* for */
4272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
42931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      /* single texture */
43031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
43131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      const struct gl_texture_image *img = obj->Image[obj->BaseLevel];
43231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      GLboolean needLambda = (obj->MinFilter != obj->MagFilter);
433b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul      span->arrayMask |= SPAN_TEXTURE;
43431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul      if (needLambda) {
4352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         /* just texture unit 0, with lambda */
43677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
43777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat *lambda = span->array->lambda[0];
4388afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul         const GLfloat texW = (GLfloat) img->WidthScale;
4398afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul         const GLfloat texH = (GLfloat) img->HeightScale;
44031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
44131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdy = span->texStepY[0][0];
44231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
44331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdy = span->texStepY[0][1];
44431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
44531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
44631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdy = span->texStepY[0][3];
4472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
4482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
4492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
4502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
4512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
45231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         for (i = 0; i < span->end; i++) {
4532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
45477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            lambda[i] = compute_lambda(dsdx, dsdy, dtdx, dtdy,
45577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                       dqdx, dqdy, texW, texH,
45677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                       s, t, q, invQ);
45777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            texcoord[i][0] = s * invQ;
45877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            texcoord[i][1] = t * invQ;
45977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            texcoord[i][2] = r * invQ;
46031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            s += dsdx;
46131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            t += dtdx;
46231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            r += drdx;
46331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            q += dqdx;
4642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
4652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask |= SPAN_LAMBDA;
4662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      else {
468733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* just texture 0, without lambda */
46977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         GLfloat (*texcoord)[4] = span->array->texcoords[0];
47031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dsdx = span->texStepX[0][0];
47131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dtdx = span->texStepX[0][1];
47231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat drdx = span->texStepX[0][2];
47331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         const GLfloat dqdx = span->texStepX[0][3];
4742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat s = span->tex[0][0];
4752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat t = span->tex[0][1];
4762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat r = span->tex[0][2];
4772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLfloat q = span->tex[0][3];
4782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         GLuint i;
47931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul         if (dqdx == 0.0) {
480c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            /* Ortho projection or polygon's parallel to window X axis */
4812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
482c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
48377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
48477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
48577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
48631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
48731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
48831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
489c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
490c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         }
491c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul         else {
492c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            for (i = 0; i < span->end; i++) {
493c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
49477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][0] = s * invQ;
49577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][1] = t * invQ;
49677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul               texcoord[i][2] = r * invQ;
49731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               s += dsdx;
49831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               t += dtdx;
49931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               r += drdx;
50031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               q += dqdx;
501c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
5022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         }
5032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
5042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
50510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
506e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
507e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
50879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
509e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
510e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
5115071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
512733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulstipple_polygon_span( GLcontext *ctx, struct sw_span *span )
51310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
51410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint highbit = 0x80000000;
515733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLuint stipple = ctx->PolygonStipple[span->y % 32];
51677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLubyte *mask = span->array->mask;
517733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   GLuint i, m;
518733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
519733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
520733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->arrayMask & SPAN_XY) == 0);
52110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
52210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   m = highbit >> (GLuint) (span->x % 32);
52310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
52410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   for (i = 0; i < span->end; i++) {
52510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if ((m & stipple) == 0) {
52677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul	 mask[i] = 0;
52710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
52810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      m = m >> 1;
52910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      if (m == 0) {
53010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         m = highbit;
53110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
53210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
5332ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
53410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
53510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
536e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
53779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
538733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
539733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
540733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
541733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
54210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
54310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
54410f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic GLuint
545733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulclip_span( GLcontext *ctx, struct sw_span *span )
54610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
547733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
548733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
549733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
550733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
551733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
552733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
553733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
55477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *x = span->array->x;
55577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *y = span->array->y;
556733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
55777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLubyte *mask = span->array->mask;
558733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
559b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
560b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
561b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
562b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
563b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
564b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
565b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
566b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
567b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
568b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
569b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
570b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
571b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
57210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
573733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
57410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
575733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
576733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
577733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
578733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
579733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
580733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
581733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
582733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
583733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
584733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
585733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
58610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
587733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
588733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
589733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
590733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
5916ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul         _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
59210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
593733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
594733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
595733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
596733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
597733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
59810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
59910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
600733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
601733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
60210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
60310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
60410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
605e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
60679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
607e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Draw to more than one color buffer (or none).
608e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
6095071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
610733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_index_span( GLcontext *ctx, struct sw_span *span )
611e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
612709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
613e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   GLuint bufferBit;
614e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
615e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* loop over four possible dest color buffers */
6163b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul   for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
6173b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul      if (bufferBit & ctx->Color._DrawDestMask) {
618e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         GLuint indexTmp[MAX_WIDTH];
619733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(span->end < MAX_WIDTH);
620e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
6218ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul         /* Set the current read/draw buffer */
6228ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul         swrast->CurrentBuffer = bufferBit;
6238ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul         (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
624e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
625e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* make copy of incoming indexes */
62677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) );
627733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
628e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (ctx->Color.IndexLogicOpEnabled) {
629733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_logicop_ci_span(ctx, span, indexTmp);
630e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
631733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
6327956292a765910077f50352d7cd0174e1e66d26cBrian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
633733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_mask_index_span(ctx, span, indexTmp);
634733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
635733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
636733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (span->arrayMask & SPAN_XY) {
637733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* array of pixel coords */
638733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Pixels)(ctx, span->end,
63977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                              span->array->x, span->array->y,
64077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                              indexTmp, span->array->mask);
641733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
642733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
643733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* horizontal run of pixels */
644733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
64577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                            indexTmp, span->array->mask);
646e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
647e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
648e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
649e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
650e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* restore default dest buffer */
6513b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul   _swrast_use_draw_buffer(ctx);
652e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
653e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
654e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
65579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
65610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul * Draw to more than one RGBA color buffer (or none).
657f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * All fragment operations, up to (but not) blending/logicop should
658f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * have been done first.
65910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
66010f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic void
661733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_rgba_span( GLcontext *ctx, struct sw_span *span )
66210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
66310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
66410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   GLuint bufferBit;
66510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
66610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
667733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(colorMask != 0x0);
668733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
66910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   if (ctx->Color.DrawBuffer == GL_NONE)
67010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
67110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
67210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* loop over four possible dest color buffers */
6733b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul   for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) {
6743b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul      if (bufferBit & ctx->Color._DrawDestMask) {
67510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         GLchan rgbaTmp[MAX_WIDTH][4];
676733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(span->end < MAX_WIDTH);
67710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
6788ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul         /* Set the current read/draw buffer */
6798ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul         swrast->CurrentBuffer = bufferBit;
6808ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul         (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
68110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
68210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         /* make copy of incoming colors */
68377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) );
68410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
68510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         if (ctx->Color.ColorLogicOpEnabled) {
686733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_logicop_rgba_span(ctx, span, rgbaTmp);
68710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
68810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         else if (ctx->Color.BlendEnabled) {
689733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_blend_span(ctx, span, rgbaTmp);
69010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
691733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
692733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (colorMask != 0xffffffff) {
693733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_mask_rgba_span(ctx, span, rgbaTmp);
69410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
69510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
696733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (span->arrayMask & SPAN_XY) {
697733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* array of pixel coords */
698733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
69977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                              span->array->x, span->array->y,
700733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              (const GLchan (*)[4]) rgbaTmp,
70177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                              span->array->mask);
702733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
703733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_pixels(ctx, span->end,
70477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                        span->array->x, span->array->y,
705733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                        (const GLchan (*)[4]) rgbaTmp,
70677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                        span->array->mask);
707733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
708733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
709733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
710733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* horizontal run of pixels */
711733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
712733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                            (const GLchan (*)[4]) rgbaTmp,
71377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                            span->array->mask);
714733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (swrast->_RasterMask & ALPHABUF_BIT) {
715733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
716733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                      (const GLchan (*)[4]) rgbaTmp,
71777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                      span->array->mask);
718733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
71910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
72010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
72110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
72210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
72310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* restore default dest buffer */
7243b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul   _swrast_use_draw_buffer(ctx);
72510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
72610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
72710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
728e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
72979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
7307956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span.
7317956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
7327956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
73310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
73410f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
735b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul_mesa_write_index_span( GLcontext *ctx, struct sw_span *span)
73610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
73710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
7387956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint origInterpMask = span->interpMask;
7392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint origArrayMask = span->arrayMask;
74010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
741733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
742b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
743b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
744733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
7457956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
7467956292a765910077f50352d7cd0174e1e66d26cBrian Paul
747733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
748733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
749733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
750733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
751733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
75277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      MEMSET(span->array->mask, 1, span->end);
753733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
75410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
75510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
756733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
757b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
758733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
75986ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
760e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
761e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
762e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
763b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
764b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
765a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
766b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
76777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
76877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
76977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
77077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
77177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
772b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
773b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
774b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
775b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
776b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
777e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
778b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
77910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
780e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
781e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
7827956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Depth test and stencil */
7837956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
7847956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (span->interpMask & SPAN_Z)
785711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
78610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
7877956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
788be99e845bd7979fe46d38d9b294c1ba0a0aa95b8Brian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
7897956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
7907956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
7917956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
7922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
7937956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
7947956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
79579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul         if (!_mesa_depth_test_span(ctx, span)) {
7967956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
7977956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
7987956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
7992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
80010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
80110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
80210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   /* if we get here, something passed the depth test */
80310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   ctx->OcclusionResult = GL_TRUE;
80410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8057956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
8067956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) {
80710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
8082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
80910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
81010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
81110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8127956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
8137956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (span->interpMask & SPAN_INDEX) {
8142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      interpolate_indexes(ctx, span);
8157956292a765910077f50352d7cd0174e1e66d26cBrian Paul      /* clear the bit - this allows the WriteMonoCISpan optimization below */
8167956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->interpMask &= ~SPAN_INDEX;
8177956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
81810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8197956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
8202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Fog.Enabled) {
821711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_ci_span(ctx, span);
822e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
823e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
8242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
8252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
8262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLuint i;
82777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLuint *index = span->array->index;
82877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLfloat *coverage = span->array->coverage;
82910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
83077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         ASSERT(coverage[i] < 16);
83177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
8325071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
8332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
8345071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
8352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
8362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* draw to zero or two or more buffers */
837733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_index_span(ctx, span);
838e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
839e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
8402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* normal situation: draw to exactly one buffer */
8412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      if (ctx->Color.IndexLogicOpEnabled) {
84277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_logicop_ci_span(ctx, span, span->array->index);
84310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
8442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8457956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Color.IndexMask != 0xffffffff) {
84677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_mask_index_span(ctx, span, span->array->index);
847e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
8482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* write pixels */
850733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
851733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
852733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
853733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color index */
854733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end,
85577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                                span->array->x, span->array->y,
856733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                                FixedToInt(span->index),
85777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                                span->array->mask);
858733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
859733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
86077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x,
86177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                              span->array->y, span->array->index,
86277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                              span->array->mask );
863733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
8647956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
8657956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
866733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
867733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) {
868733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color index */
869733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y,
870733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul                                              FixedToInt(span->index),
87177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                              span->array->mask);
872733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
873733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
874733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y,
87577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                            span->array->index,
87677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                            span->array->mask);
877733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
8787956292a765910077f50352d7cd0174e1e66d26cBrian Paul      }
879e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
8802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
8817956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
8822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
883e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
884e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
885e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
88679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
8877956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span.
8887956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
8897956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
8905d2621928823a06006c1586efe78fe8bf65a7e1fBrian Paul */
8915071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
892b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul_mesa_write_rgba_span( GLcontext *ctx, struct sw_span *span)
893e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
894cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
8957956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
8967956292a765910077f50352d7cd0174e1e66d26cBrian Paul   const GLuint origInterpMask = span->interpMask;
8972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint origArrayMask = span->arrayMask;
8987956292a765910077f50352d7cd0174e1e66d26cBrian Paul   GLboolean monoColor;
8997956292a765910077f50352d7cd0174e1e66d26cBrian Paul
900733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
901b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
902b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
9037956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
904ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA);
905bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#ifdef DEBUG
906733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (ctx->Fog.Enabled)
907733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
908bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul   if (ctx->Depth.Test)
909bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul      ASSERT((span->interpMask | span->arrayMask) & SPAN_Z);
910bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#endif
911733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
912733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
913733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
914733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
915733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
916733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
91777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      MEMSET(span->array->mask, 1, span->end);
918733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
919733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
920e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9217956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Determine if we have mono-chromatic colors */
9227956292a765910077f50352d7cd0174e1e66d26cBrian Paul   monoColor = (span->interpMask & SPAN_RGBA) &&
9237956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->redStep == 0 && span->greenStep == 0 &&
9247956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->blueStep == 0 && span->alphaStep == 0;
9257956292a765910077f50352d7cd0174e1e66d26cBrian Paul
926733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
927b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
928733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
92986ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
930e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
931e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
932e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
933b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
934b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
935a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
936b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
93777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
93877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
93977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
94077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
94177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
942b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
943b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
944b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
945b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
946b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
947e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
948b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
9497956292a765910077f50352d7cd0174e1e66d26cBrian Paul      stipple_polygon_span(ctx, span);
95010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
95110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
952e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Do the alpha test */
953e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (ctx->Color.AlphaEnabled) {
954ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      if (!_mesa_alpha_test(ctx, span)) {
9557956292a765910077f50352d7cd0174e1e66d26cBrian Paul         span->interpMask = origInterpMask;
9562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         span->arrayMask = origArrayMask;
957e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 return;
958e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
95910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
96010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
961f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
962f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
963f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
964711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
965f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
966f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (ctx->Stencil.Enabled) {
967be99e845bd7979fe46d38d9b294c1ba0a0aa95b8Brian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
9687956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->interpMask = origInterpMask;
969f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
970f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            return;
97110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
97210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
97310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      else {
974f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
975f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
976f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         /* regular depth testing */
977f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_depth_test_span(ctx, span)) {
9787956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->interpMask = origInterpMask;
979f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
980f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            return;
98110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         }
98210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
983e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
984e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
985e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* if we get here, something passed the depth test */
986e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   ctx->OcclusionResult = GL_TRUE;
987e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9887956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* can't abort span-writing until after occlusion testing */
9897956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (colorMask == 0x0) {
9907956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->interpMask = origInterpMask;
9917956292a765910077f50352d7cd0174e1e66d26cBrian Paul      span->arrayMask = origArrayMask;
9927956292a765910077f50352d7cd0174e1e66d26cBrian Paul      return;
9937956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
9947956292a765910077f50352d7cd0174e1e66d26cBrian Paul
995ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /* Now we may need to interpolate the colors */
996ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) {
997ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      interpolate_colors(ctx, span);
998ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      /* clear the bit - this allows the WriteMonoCISpan optimization below */
999ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      span->interpMask &= ~SPAN_RGBA;
1000ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   }
1001ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
10026e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
1003b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul   if (ctx->Fog.Enabled) {
1004711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_rgba_span(ctx, span);
10057956292a765910077f50352d7cd0174e1e66d26cBrian Paul      monoColor = GL_FALSE;
1006b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul   }
1007b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul
10085071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul   /* Antialias coverage application */
10092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
101077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLchan (*rgba)[4] = span->array->rgba;
101177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLfloat *coverage = span->array->coverage;
10125071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      GLuint i;
101310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
101477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
10155071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
10167956292a765910077f50352d7cd0174e1e66d26cBrian Paul      monoColor = GL_FALSE;
10175071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul   }
10185071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
1019cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1020733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_rgba_span(ctx, span);
1021e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1022e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1023e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* normal: write to exactly one buffer */
1024e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (ctx->Color.ColorLogicOpEnabled) {
102577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_logicop_rgba_span(ctx, span, span->array->rgba);
10267956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1027e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1028e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else if (ctx->Color.BlendEnabled) {
102977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_blend_span(ctx, span, span->array->rgba);
10307956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1031e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
103295e2c72fd52d87163eb543555345f115f050f3aaBrian Paul
1033e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* Color component masking */
10347956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (colorMask != 0xffffffff) {
103577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_mask_rgba_span(ctx, span, span->array->rgba);
10367956292a765910077f50352d7cd0174e1e66d26cBrian Paul         monoColor = GL_FALSE;
1037e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1038e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1039e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* write pixels */
1040733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
1041733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
1042733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* XXX test for mono color */
104377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
104477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul             span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1045733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1046733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_pixels(ctx, span->end,
104777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                     span->array->x, span->array->y,
104877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                     (const GLchan (*)[4]) span->array->rgba,
104977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                     span->array->mask);
1050733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1051e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1052e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1053733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
1054733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (monoColor) {
1055733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* all pixels have same color */
1056733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            GLchan color[4];
1057733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[RCOMP] = FixedToChan(span->red);
1058733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[GCOMP] = FixedToChan(span->green);
1059733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[BCOMP] = FixedToChan(span->blue);
1060733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            color[ACOMP] = FixedToChan(span->alpha);
1061733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
106277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                                span->y, color, span->array->mask);
1063733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* XXX software alpha buffer writes! */
1064733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1065733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
1066733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            /* each pixel is a different color */
1067733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
106877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                      (const GLchan (*)[4]) span->array->rgba,
106977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                      span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1070733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            if (swrast->_RasterMask & ALPHABUF_BIT) {
1071733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul               _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
107277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                      (const GLchan (*)[4]) span->array->rgba,
107377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                      span->writeAll ? ((const GLubyte *) NULL) : span->array->mask);
1074733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            }
1075733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1076e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1077e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1078e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
10797956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
10807956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->arrayMask = origArrayMask;
10817956292a765910077f50352d7cd0174e1e66d26cBrian Paul}
1082e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1083e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
108479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1085e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color.  This is used only when
1086f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
1087e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
10885071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void
1089f1e236987829393c81dc86ea19cb49eefe190317Brian Pauladd_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] )
1090e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1091e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   GLuint i;
1092f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   for (i = 0; i < n; i++) {
10934fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#if CHAN_TYPE == GL_FLOAT
10944fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul      /* no clamping */
1095f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][RCOMP] += specular[i][RCOMP];
1096f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][GCOMP] += specular[i][GCOMP];
1097f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      rgba[i][BCOMP] += specular[i][BCOMP];
10984fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#else
1099f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
1100f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
1101f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
1102e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX);
1103e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX);
1104e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX);
11054fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#endif
1106e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1107e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1108e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1109e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
111079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1111f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
11127956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
11137956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
111478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
111578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
1116b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul_mesa_write_texture_span( GLcontext *ctx, struct sw_span *span)
111778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
111878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
111978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1120f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   const GLuint origArrayMask = span->arrayMask;
1121f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1122b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
1123b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
1124733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
11257956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
11268afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   ASSERT(ctx->Texture._EnabledUnits);
112778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1128ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   /*
1129ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
1130ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul   */
1131ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1132733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1133733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1134733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1135733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1136733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
113777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      MEMSET(span->array->mask, 1, span->end);
1138733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
113978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
114078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1141733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
1142b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1143733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1144733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
114578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
114678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
114778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1148b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1149b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1150a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
1151b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
115277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
115377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin);
115477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->x[i] < ctx->DrawBuffer->_Xmax);
115577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin);
115677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            assert(span->array->y[i] < ctx->DrawBuffer->_Ymax);
1157b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1158b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1159b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1160b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1161b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
116278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1163b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1164733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
116578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
116678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1167f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Need texture coordinates now */
1168f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if ((span->interpMask & SPAN_TEXTURE)
1169f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       && (span->arrayMask & SPAN_TEXTURE) == 0)
1170f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      interpolate_texcoords(ctx, span);
117178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
117278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Texture with alpha test */
117378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   if (ctx->Color.AlphaEnabled) {
1174f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
1175f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1176f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1177f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
1178f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
117978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Texturing without alpha is done after depth-testing which
1180f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       * gives a potential speed-up.
1181f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       */
1182f595212336ae63c981f0f39f4ea1dec67ff7fe25Brian Paul      _swrast_texture_span( ctx, span );
118378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
118478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      /* Do the alpha test */
1185ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul      if (!_mesa_alpha_test(ctx, span)) {
1186f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         span->arrayMask = origArrayMask;
1187ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul	 return;
118878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
118978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
119078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1191f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1192f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
1193f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_Z)
1194711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul         _mesa_span_interpolate_z(ctx, span);
119578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
119671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      if (ctx->Stencil.Enabled) {
1197be99e845bd7979fe46d38d9b294c1ba0a0aa95b8Brian Paul         if (!_mesa_stencil_and_ztest_span(ctx, span)) {
1198f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
119910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1200f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
120171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1202f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      else {
1203f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1204f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
120510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul         /* regular depth testing */
1206f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         if (!_mesa_depth_test_span(ctx, span)) {
1207f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            span->arrayMask = origArrayMask;
120810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul            return;
1209f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
121071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
121171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
121271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1213f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* if we get here, some fragments passed the depth test */
121471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   ctx->OcclusionResult = GL_TRUE;
121571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1216f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* We had to wait until now to check for glColorMask(F,F,F,F) because of
1217f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1218f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1219f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1220f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      span->arrayMask = origArrayMask;
1221f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      return;
122271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
122371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1224f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Texture without alpha test */
1225f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (!ctx->Color.AlphaEnabled) {
122671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1227f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      /* Now we need the rgba array, fill it in if needed */
1228f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0)
1229f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_colors(ctx, span);
123071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1231f595212336ae63c981f0f39f4ea1dec67ff7fe25Brian Paul      _swrast_texture_span( ctx, span );
123271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
123371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1234f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
12352ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
1236f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Add base and specular colors */
1237f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Fog.ColorSumEnabled ||
1238f1e236987829393c81dc86ea19cb49eefe190317Brian Paul       (ctx->Light.Enabled &&
1239f1e236987829393c81dc86ea19cb49eefe190317Brian Paul        ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
1240f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (span->interpMask & SPAN_SPEC) {
1241f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         interpolate_specular(ctx, span);
124271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
1243f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      ASSERT(span->arrayMask & SPAN_SPEC);
124477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      add_colors( span->end, span->array->rgba, span->array->spec );
124571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
124671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
12476e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
124871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   if (ctx->Fog.Enabled) {
1249711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paul      _mesa_fog_rgba_span(ctx, span);
125071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1251f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
125271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
12532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
125477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLchan (*rgba)[4] = span->array->rgba;
125577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLfloat *coverage = span->array->coverage;
125671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      GLuint i;
125710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
125877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]);
125971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
126071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
126171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
126271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   if (swrast->_RasterMask & MULTI_DRAW_BIT) {
1263733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      multi_write_rgba_span(ctx, span);
126471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
126571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   else {
126671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      /* normal: write to exactly one buffer */
126771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      if (ctx->Color.ColorLogicOpEnabled) {
126877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_logicop_rgba_span(ctx, span, span->array->rgba);
126971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
127095e2c72fd52d87163eb543555345f115f050f3aaBrian Paul      else if (ctx->Color.BlendEnabled) {
127177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_blend_span(ctx, span, span->array->rgba);
127271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
127371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1274f1e236987829393c81dc86ea19cb49eefe190317Brian Paul      if (colorMask != 0xffffffff) {
127577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         _mesa_mask_rgba_span(ctx, span, span->array->rgba);
127671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
127771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1278733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
1279733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (span->arrayMask & SPAN_XY) {
1280733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* array of pixel coords */
128177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
128277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul             span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
1283733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
1284733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_pixels(ctx, span->end,
128577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                     span->array->x, span->array->y,
128677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                     (const GLchan (*)[4]) span->array->rgba,
128777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                     span->array->mask);
1288733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1289733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
1290733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      else {
1291733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         /* horizontal run of pixels */
1292733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y,
129377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                       (const GLchan (*)[4]) span->array->rgba,
129477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                       span->writeAll ? NULL : span->array->mask);
1295733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         if (swrast->_RasterMask & ALPHABUF_BIT) {
1296733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul            _mesa_write_alpha_span(ctx, span->end, span->x, span->y,
129777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                   (const GLchan (*)[4]) span->array->rgba,
129877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul                                   span->writeAll ? NULL : span->array->mask);
1299733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
130071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
130171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
130271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1303f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
130410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
130510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1306e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1307e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
130879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1309e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
1310e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1311e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
13125071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
13135071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul_mesa_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer,
13145071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul                      GLuint n, GLint x, GLint y, GLchan rgba[][4] )
1315e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1316709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1317a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   const GLint bufWidth = (GLint) buffer->Width;
13181113e3266f1a9df3506fb80189bfe00d9681b55eBrian Paul   const GLint bufHeight = (GLint) buffer->Height;
1319a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1320a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1321e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1322e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* XXX maybe leave undefined? */
13236ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul      _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1324e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1325e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1326e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1327e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
1328e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* left edge clippping */
1329e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1330e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1331e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1332e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1333e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1334e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1335a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1336a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1337e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1338e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1339a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1340e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1341e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1342a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1343e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1344e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1345e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1346e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1347e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1348e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1349e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1350e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1351e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1352e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1353e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1354709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell      (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
1355e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (buffer->UseSoftwareAlphaBuffers) {
1356733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         _mesa_read_alpha_span(ctx, length, x + skip, y, rgba + skip);
1357e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1358e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1359e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1360e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1361e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
136279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1363e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read CI pixels from frame buffer.  Clipping will be done to prevent
1364e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1365e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
13665071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
13675071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul_mesa_read_index_span( GLcontext *ctx, GLframebuffer *buffer,
13685071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul                       GLuint n, GLint x, GLint y, GLuint indx[] )
1369e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1370709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1371a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   const GLint bufWidth = (GLint) buffer->Width;
13721113e3266f1a9df3506fb80189bfe00d9681b55eBrian Paul   const GLint bufHeight = (GLint) buffer->Height;
1373a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1374a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1375e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
13766ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul      _mesa_bzero(indx, n * sizeof(GLuint));
1377e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1378e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1379e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1380e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
1381e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* left edge clippping */
1382e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1383e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1384e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1385e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1386e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1387e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1388a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1389a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1390e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1391e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1392a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1393e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1394e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1395a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1396e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1397e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1398e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1399e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1400e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1401e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1402e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1403e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1404e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1405e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1406e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1407709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell      (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
1408e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1409e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1410