s_span.c revision 18fa367ac6e035341f5eb86ecc4231124b2921e3
1e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/* 2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library 327558a160a9fe91745728d7626995cd88f8fe339Brian Paul * Version: 5.1 422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * 56a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * 7e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a 8e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * copy of this software and associated documentation files (the "Software"), 9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to deal in the Software without restriction, including without limitation 10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the 12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Software is furnished to do so, subject to the following conditions: 1322144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * 14e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice shall be included 15e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in all copies or substantial portions of the Software. 1622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * 17e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 2679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 27bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul * \file swrast/s_span.c 2879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \brief Span processing functions used by all rasterization functions. 2979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * This is where all the per-fragment tests are performed 3079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \author Brian Paul 31e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 32e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "glheader.h" 34e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "colormac.h" 3571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul#include "context.h" 36e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "macros.h" 373c63452e64df7e10aa073c6c3b9492b1d7dabbb8Brian Paul#include "imports.h" 38e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 39e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alpha.h" 40e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_alphabuf.h" 41e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h" 42cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h" 43e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h" 44e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h" 45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h" 46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h" 47610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul#include "s_nvfragprog.h" 48e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h" 49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h" 50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_texture.h" 51e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 5379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 542a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's Z interpolation values to the RasterPos Z. 552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels. 562a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */ 572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid 5845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_z( GLcontext *ctx, struct sw_span *span ) 592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (ctx->Visual.depthBits <= 16) 61ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F); 622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else 63ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F); 642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->zStep = 0; 652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->interpMask |= SPAN_Z; 662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul} 672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 6979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's fog interpolation values to the RasterPos fog. 712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels. 722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */ 732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid 7445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_fog( GLcontext *ctx, struct sw_span *span ) 752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 7645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul span->fog = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance); 7754e92e8420a028f07b0971ee8aa93be9b4214579Brian Paul span->fogStep = span->dfogdx = span->dfogdy = 0.0F; 782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->interpMask |= SPAN_FOG; 792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul} 802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 8279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Init span's color or index interpolation values to the RasterPos color. 842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul * Used during setup for glDraw/CopyPixels. 852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */ 862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid 8745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_color( GLcontext *ctx, struct sw_span *span ) 882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (ctx->Visual.rgbMode) { 902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLchan r, g, b, a; 912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]); 922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]); 932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]); 942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]); 952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT 962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->red = r; 972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->green = g; 982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->blue = b; 992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->alpha = a; 1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else 1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->red = IntToFixed(r); 1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->green = IntToFixed(g); 1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->blue = IntToFixed(b); 1042a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->alpha = IntToFixed(a); 1052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif 1062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->redStep = 0; 1072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->greenStep = 0; 1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->blueStep = 0; 1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->alphaStep = 0; 1102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->interpMask |= SPAN_RGBA; 1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else { 1130f3cd3f894612d156de454178effa4c732f96da7Brian Paul span->index = FloatToFixed(ctx->Current.RasterIndex); 1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->indexStep = 0; 1152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->interpMask |= SPAN_INDEX; 1162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 1172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul} 1182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 1192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 1204753d60dd070bb08d0116076bcc08025c86ce857Brian Paul/** 1214753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Init span's texcoord interpolation values to the RasterPos texcoords. 1224753d60dd070bb08d0116076bcc08025c86ce857Brian Paul * Used during setup for glDraw/CopyPixels. 1234753d60dd070bb08d0116076bcc08025c86ce857Brian Paul */ 1244753d60dd070bb08d0116076bcc08025c86ce857Brian Paulvoid 12545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span ) 1264753d60dd070bb08d0116076bcc08025c86ce857Brian Paul{ 1274753d60dd070bb08d0116076bcc08025c86ce857Brian Paul GLuint i; 1284753d60dd070bb08d0116076bcc08025c86ce857Brian Paul for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 1295f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul COPY_4V(span->tex[i], ctx->Current.RasterTexCoords[i]); 1305f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F); 1315f60a0b50ada1865d4fc6a724366e8ea0cc9a72fBrian Paul ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F); 1324753d60dd070bb08d0116076bcc08025c86ce857Brian Paul } 1334753d60dd070bb08d0116076bcc08025c86ce857Brian Paul span->interpMask |= SPAN_TEXTURE; 1344753d60dd070bb08d0116076bcc08025c86ce857Brian Paul} 1354753d60dd070bb08d0116076bcc08025c86ce857Brian Paul 1364753d60dd070bb08d0116076bcc08025c86ce857Brian Paul 1372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.rgba array from the interpolation values */ 1382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void 1392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_colors(GLcontext *ctx, struct sw_span *span) 1402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 1412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLuint n = span->end; 14277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLchan (*rgba)[4] = span->array->rgba; 1432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 1442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 145b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul ASSERT((span->interpMask & SPAN_RGBA) && 146b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul !(span->arrayMask & SPAN_RGBA)); 1472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 1482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (span->interpMask & SPAN_FLAT) { 1492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* constant color */ 1502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLchan color[4]; 1516a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul color[RCOMP] = FixedToChan(span->red); 1526a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul color[GCOMP] = FixedToChan(span->green); 1536a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul color[BCOMP] = FixedToChan(span->blue); 1546a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul color[ACOMP] = FixedToChan(span->alpha); 1552a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul for (i = 0; i < n; i++) { 15677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul COPY_CHAN4(span->array->rgba[i], color); 1572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 1582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 1592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else { 1602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* interpolate */ 1616a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul#if CHAN_TYPE == GL_FLOAT 1626a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfloat r = span->red; 1636a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfloat g = span->green; 1646a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfloat b = span->blue; 1656a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfloat a = span->alpha; 1666a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLfloat dr = span->redStep; 1676a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLfloat dg = span->greenStep; 1686a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLfloat db = span->blueStep; 1696a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLfloat da = span->alphaStep; 1706a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul#else 1716a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfixed r = span->red; 1726a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfixed g = span->green; 1736a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfixed b = span->blue; 1746a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul GLfixed a = span->alpha; 1756a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLint dr = span->redStep; 1766a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLint dg = span->greenStep; 1776a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLint db = span->blueStep; 1786a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul const GLint da = span->alphaStep; 1796a98bef96189fbacc326ad9e407c1d4423aa8572Brian Paul#endif 1802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul for (i = 0; i < n; i++) { 1812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul rgba[i][RCOMP] = FixedToChan(r); 1822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul rgba[i][GCOMP] = FixedToChan(g); 1832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul rgba[i][BCOMP] = FixedToChan(b); 1842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul rgba[i][ACOMP] = FixedToChan(a); 1852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul r += dr; 1862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul g += dg; 1872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul b += db; 1882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul a += da; 1892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 1902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 1912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask |= SPAN_RGBA; 1922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul} 1932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 1942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 1952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */ 1962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void 1972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_indexes(GLcontext *ctx, struct sw_span *span) 1982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 1992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfixed index = span->index; 2002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLint indexStep = span->indexStep; 2012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLuint n = span->end; 20277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLuint *indexes = span->array->index; 2032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 204b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul ASSERT((span->interpMask & SPAN_INDEX) && 205b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul !(span->arrayMask & SPAN_INDEX)); 2062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 2072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) { 2082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* constant color */ 2092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul index = FixedToInt(index); 2102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul for (i = 0; i < n; i++) { 2112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul indexes[i] = index; 2122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else { 2152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* interpolate */ 2162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul for (i = 0; i < n; i++) { 2172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul indexes[i] = FixedToInt(index); 2182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul index += indexStep; 2192a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask |= SPAN_INDEX; 2222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul} 2232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 2242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 22577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul/* Fill in the span.->array->spec array from the interpolation values */ 2262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void 2272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_specular(GLcontext *ctx, struct sw_span *span) 2282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 2292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (span->interpMask & SPAN_FLAT) { 2302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* constant color */ 2312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLchan r = FixedToChan(span->specRed); 2322a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLchan g = FixedToChan(span->specGreen); 2332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLchan b = FixedToChan(span->specBlue); 2342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 2352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul for (i = 0; i < span->end; i++) { 23677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->spec[i][RCOMP] = r; 23777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->spec[i][GCOMP] = g; 23877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->spec[i][BCOMP] = b; 2392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2412a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else { 2422a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* interpolate */ 2432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT 2442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat r = span->specRed; 2452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat g = span->specGreen; 2462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat b = span->specBlue; 2472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else 2482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfixed r = span->specRed; 2492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfixed g = span->specGreen; 2502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfixed b = span->specBlue; 2512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif 2522a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 2532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul for (i = 0; i < span->end; i++) { 25477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->spec[i][RCOMP] = FixedToChan(r); 25577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->spec[i][GCOMP] = FixedToChan(g); 25677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->spec[i][BCOMP] = FixedToChan(b); 2572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul r += span->specRedStep; 2582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul g += span->specGreenStep; 2592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul b += span->specBlueStep; 2602a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask |= SPAN_SPEC; 2632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul} 2642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 2652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 2662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.zArray array from the interpolation values */ 267711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid 26845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_span_interpolate_z( const GLcontext *ctx, struct sw_span *span ) 2692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 2702a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLuint n = span->end; 2712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 2722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 273b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul ASSERT((span->interpMask & SPAN_Z) && 274b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul !(span->arrayMask & SPAN_Z)); 2752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 2762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (ctx->Visual.depthBits <= 16) { 2772a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfixed zval = span->z; 27877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLdepth *z = span->array->z; 279ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul for (i = 0; i < n; i++) { 28077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul z[i] = FixedToInt(zval); 2812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul zval += span->zStep; 2822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else { 2852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* Deep Z buffer, no fixed->int shift */ 2862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfixed zval = span->z; 28777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLdepth *z = span->array->z; 2882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul for (i = 0; i < n; i++) { 28977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul z[i] = zval; 2902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul zval += span->zStep; 2912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 2932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask |= SPAN_Z; 2942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul} 2952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 2962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 297c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/* 29831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec. 299c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */ 300c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0 30131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat 30231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 30331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 30431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 305c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{ 30631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); 30731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); 30831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); 30931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); 310f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx); 311f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy); 31231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat rho = MAX2(x, y); 31331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat lambda = LOG2(rho); 31431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul return lambda; 315c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul} 316c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif 317c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul 31831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul 31931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul/* 32031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This is a faster approximation 321c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */ 322350353adcd75f94fda63c787c86961716114e0bfBrian PaulGLfloat 32345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 324350353adcd75f94fda63c787c86961716114e0bfBrian Paul GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 325350353adcd75f94fda63c787c86961716114e0bfBrian Paul GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 326c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{ 32731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ; 32831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ; 32931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ; 33031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ; 33131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLfloat maxU, maxV, rho, lambda; 33231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul dsdx2 = FABSF(dsdx2); 33331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul dsdy2 = FABSF(dsdy2); 33431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul dtdx2 = FABSF(dtdx2); 33531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul dtdy2 = FABSF(dtdy2); 33631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul maxU = MAX2(dsdx2, dsdy2) * texW; 33731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul maxV = MAX2(dtdx2, dtdy2) * texH; 33831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul rho = MAX2(maxU, maxV); 33931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul lambda = LOG2(rho); 34031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul return lambda; 341c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul} 342c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul 343c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul/* 344c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * Fill in the span.texcoords array from the interpolation values. 345c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * XXX We could optimize here for the case when dq = 0. That would 346c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul * usually be the case when using an orthographic projection. 347c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */ 3482a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void 3492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulinterpolate_texcoords(GLcontext *ctx, struct sw_span *span) 3502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{ 3512a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul ASSERT(span->interpMask & SPAN_TEXTURE); 352b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul ASSERT(!(span->arrayMask & SPAN_TEXTURE)); 3532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 35436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul if (ctx->Texture._EnabledCoordUnits > 1) { 35531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul /* multitexture */ 35631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul GLuint u; 357b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul span->arrayMask |= SPAN_TEXTURE; 35831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 35936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul if (ctx->Texture._EnabledCoordUnits & (1 << u)) { 36031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current; 36136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul GLfloat texW, texH; 36236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul GLboolean needLambda; 36336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul if (obj) { 36418fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; 36536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul needLambda = (obj->MinFilter != obj->MagFilter) 36636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul || ctx->FragmentProgram.Enabled; 36736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texW = img->WidthScale; 36836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texH = img->HeightScale; 36936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul } 37036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul else { 37136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texW = 1.0; 37236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texH = 1.0; 37336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul needLambda = GL_FALSE; 37436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul } 37531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul if (needLambda) { 37677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat (*texcoord)[4] = span->array->texcoords[u]; 37777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat *lambda = span->array->lambda[u]; 37831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dsdx = span->texStepX[u][0]; 37931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dsdy = span->texStepY[u][0]; 38031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dtdx = span->texStepX[u][1]; 38131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dtdy = span->texStepY[u][1]; 38231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat drdx = span->texStepX[u][2]; 38331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dqdx = span->texStepX[u][3]; 38431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dqdy = span->texStepY[u][3]; 3852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat s = span->tex[u][0]; 3862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat t = span->tex[u][1]; 3872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat r = span->tex[u][2]; 3882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat q = span->tex[u][3]; 3892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 39031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul for (i = 0; i < span->end; i++) { 3912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 39277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][0] = s * invQ; 39377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][1] = t * invQ; 39477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][2] = r * invQ; 395350353adcd75f94fda63c787c86961716114e0bfBrian Paul texcoord[i][3] = q; 39645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 397350353adcd75f94fda63c787c86961716114e0bfBrian Paul dqdx, dqdy, texW, texH, 398350353adcd75f94fda63c787c86961716114e0bfBrian Paul s, t, q, invQ); 39931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul s += dsdx; 40031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul t += dtdx; 40131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul r += drdx; 40231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul q += dqdx; 4032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 40431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul span->arrayMask |= SPAN_LAMBDA; 4052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 40631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul else { 40777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat (*texcoord)[4] = span->array->texcoords[u]; 40877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat *lambda = span->array->lambda[u]; 40931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dsdx = span->texStepX[u][0]; 41031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dtdx = span->texStepX[u][1]; 41131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat drdx = span->texStepX[u][2]; 41231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dqdx = span->texStepX[u][3]; 4132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat s = span->tex[u][0]; 4142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat t = span->tex[u][1]; 4152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat r = span->tex[u][2]; 4162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat q = span->tex[u][3]; 4172a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 41831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul if (dqdx == 0.0) { 419c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul /* Ortho projection or polygon's parallel to window X axis */ 4202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 421c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul for (i = 0; i < span->end; i++) { 42277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][0] = s * invQ; 42377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][1] = t * invQ; 42477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][2] = r * invQ; 42536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texcoord[i][3] = q; 42677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul lambda[i] = 0.0; 42731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul s += dsdx; 42831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul t += dtdx; 42931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul r += drdx; 430c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul } 431c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul } 432c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul else { 433c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul for (i = 0; i < span->end; i++) { 434c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 43577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][0] = s * invQ; 43677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][1] = t * invQ; 43777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][2] = r * invQ; 43836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texcoord[i][3] = q; 43977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul lambda[i] = 0.0; 44031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul s += dsdx; 44131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul t += dtdx; 44231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul r += drdx; 44331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul q += dqdx; 444c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul } 4452a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 44631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul } /* lambda */ 44731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul } /* if */ 44831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul } /* for */ 4492a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 4502a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else { 45131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul /* single texture */ 45231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 45336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul GLfloat texW, texH; 45436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul GLboolean needLambda; 45536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul if (obj) { 45618fa367ac6e035341f5eb86ecc4231124b2921e3Keith Whitwell const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; 45736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul needLambda = (obj->MinFilter != obj->MagFilter) 45836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul || ctx->FragmentProgram.Enabled; 45936a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texW = (GLfloat) img->WidthScale; 46036a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texH = (GLfloat) img->HeightScale; 46136a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul } 46236a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul else { 46336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul needLambda = GL_FALSE; 46436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul texW = texH = 1.0; 46536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul } 466b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul span->arrayMask |= SPAN_TEXTURE; 46731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul if (needLambda) { 4682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* just texture unit 0, with lambda */ 46977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat (*texcoord)[4] = span->array->texcoords[0]; 47077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat *lambda = span->array->lambda[0]; 47131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dsdx = span->texStepX[0][0]; 47231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dsdy = span->texStepY[0][0]; 47331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dtdx = span->texStepX[0][1]; 47431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dtdy = span->texStepY[0][1]; 47531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat drdx = span->texStepX[0][2]; 47631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dqdx = span->texStepX[0][3]; 47731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dqdy = span->texStepY[0][3]; 4782a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat s = span->tex[0][0]; 4792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat t = span->tex[0][1]; 4802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat r = span->tex[0][2]; 4812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat q = span->tex[0][3]; 4822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 48331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul for (i = 0; i < span->end; i++) { 4842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 48545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 486350353adcd75f94fda63c787c86961716114e0bfBrian Paul dqdx, dqdy, texW, texH, 487350353adcd75f94fda63c787c86961716114e0bfBrian Paul s, t, q, invQ); 48877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][0] = s * invQ; 48977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][1] = t * invQ; 49077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][2] = r * invQ; 491350353adcd75f94fda63c787c86961716114e0bfBrian Paul texcoord[i][3] = q; 49231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul s += dsdx; 49331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul t += dtdx; 49431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul r += drdx; 49531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul q += dqdx; 4962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 4972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask |= SPAN_LAMBDA; 4982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 4992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul else { 500733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* just texture 0, without lambda */ 50177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat (*texcoord)[4] = span->array->texcoords[0]; 50231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dsdx = span->texStepX[0][0]; 50331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dtdx = span->texStepX[0][1]; 50431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat drdx = span->texStepX[0][2]; 50531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul const GLfloat dqdx = span->texStepX[0][3]; 5062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat s = span->tex[0][0]; 5072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat t = span->tex[0][1]; 5082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat r = span->tex[0][2]; 5092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLfloat q = span->tex[0][3]; 5102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 51131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul if (dqdx == 0.0) { 512c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul /* Ortho projection or polygon's parallel to window X axis */ 5132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 514c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul for (i = 0; i < span->end; i++) { 51577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][0] = s * invQ; 51677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][1] = t * invQ; 51777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][2] = r * invQ; 5182b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul texcoord[i][3] = q; 51931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul s += dsdx; 52031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul t += dtdx; 52131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul r += drdx; 522c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul } 523c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul } 524c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul else { 525c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul for (i = 0; i < span->end; i++) { 526c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 52777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][0] = s * invQ; 52877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][1] = t * invQ; 52977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul texcoord[i][2] = r * invQ; 5302b7a01a39ba5257407dddde38ef049856c34aa01Brian Paul texcoord[i][3] = q; 53131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul s += dsdx; 53231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul t += dtdx; 53331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul r += drdx; 53431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul q += dqdx; 535c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul } 5362a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 5372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 5382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 53910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul} 540e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 541e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 54279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 543e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels. 544e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 5455071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void 546733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulstipple_polygon_span( GLcontext *ctx, struct sw_span *span ) 54710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{ 54810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul const GLuint highbit = 0x80000000; 549733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLuint stipple = ctx->PolygonStipple[span->y % 32]; 55077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLubyte *mask = span->array->mask; 551733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul GLuint i, m; 552733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 553733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(ctx->Polygon.StippleFlag); 554733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT((span->arrayMask & SPAN_XY) == 0); 55510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 55610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul m = highbit >> (GLuint) (span->x % 32); 55710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 55810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul for (i = 0; i < span->end; i++) { 55910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul if ((m & stipple) == 0) { 56077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul mask[i] = 0; 56110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 56210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul m = m >> 1; 56310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul if (m == 0) { 56410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul m = highbit; 56510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 56610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 5672ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul span->writeAll = GL_FALSE; 56810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul} 56910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 570e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 57179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 572733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries: 573733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish 574733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring. 575733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return: GL_TRUE some pixels still visible 57610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul * GL_FALSE nothing visible 57710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */ 57810f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic GLuint 579733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulclip_span( GLcontext *ctx, struct sw_span *span ) 58010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{ 581733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint xmin = ctx->DrawBuffer->_Xmin; 582733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint xmax = ctx->DrawBuffer->_Xmax; 583733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint ymin = ctx->DrawBuffer->_Ymin; 584733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint ymax = ctx->DrawBuffer->_Ymax; 585733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 586733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_XY) { 587733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* arrays of x/y pixel coords */ 58877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul const GLint *x = span->array->x; 58977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul const GLint *y = span->array->y; 590733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint n = span->end; 59177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLubyte *mask = span->array->mask; 592733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul GLint i; 593b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul if (span->arrayMask & SPAN_MASK) { 594b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul /* note: using & intead of && to reduce branches */ 595b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul for (i = 0; i < n; i++) { 596b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul mask[i] &= (x[i] >= xmin) & (x[i] < xmax) 597b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul & (y[i] >= ymin) & (y[i] < ymax); 598b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 599b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 600b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul else { 601b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul /* note: using & intead of && to reduce branches */ 602b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul for (i = 0; i < n; i++) { 603b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul mask[i] = (x[i] >= xmin) & (x[i] < xmax) 604b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul & (y[i] >= ymin) & (y[i] < ymax); 605b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 60610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 607733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul return GL_TRUE; /* some pixels visible */ 60810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 609733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 610733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* horizontal span of pixels */ 611733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint x = span->x; 612733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint y = span->y; 613733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul const GLint n = span->end; 614733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 615733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* Trivial rejection tests */ 616733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) { 617733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->end = 0; 618733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul return GL_FALSE; /* all pixels clipped */ 619733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 62010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 621733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* Clip to the left */ 622733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (x < xmin) { 623733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(x + n > xmin); 624733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->writeAll = GL_FALSE; 6256ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte)); 62610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 627733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 628733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* Clip to right */ 629733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (x + n > xmax) { 630733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(x < xmax); 631733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->end = xmax - x; 63210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 63310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 634733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul return GL_TRUE; /* some pixels visible */ 635733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 63610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul} 63710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 63810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 639e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 64079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 641e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Draw to more than one color buffer (or none). 642e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 6435071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void 644733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_index_span( GLcontext *ctx, struct sw_span *span ) 645e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 646709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell SWcontext *swrast = SWRAST_CONTEXT(ctx); 647e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint bufferBit; 648e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 649e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* loop over four possible dest color buffers */ 6503b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) { 6513b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul if (bufferBit & ctx->Color._DrawDestMask) { 652e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint indexTmp[MAX_WIDTH]; 653733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(span->end < MAX_WIDTH); 654e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 6558ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul /* Set the current read/draw buffer */ 6568ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul swrast->CurrentBuffer = bufferBit; 6578ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); 658e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 659e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* make copy of incoming indexes */ 66077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) ); 661733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 662e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (ctx->Color.IndexLogicOpEnabled) { 66345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_logicop_ci_span(ctx, span, indexTmp); 664e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 665733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 6667956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (ctx->Color.IndexMask != 0xffffffff) { 66745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_mask_index_span(ctx, span, indexTmp); 668733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 669733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 670733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_XY) { 671733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* array of pixel coords */ 672733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, 67377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->x, span->array->y, 67477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul indexTmp, span->array->mask); 675733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 676733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 677733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* horizontal run of pixels */ 678733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y, 67977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul indexTmp, span->array->mask); 680e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 681e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 682e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 683e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 684e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* restore default dest buffer */ 6853b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul _swrast_use_draw_buffer(ctx); 686e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 687e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 688e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 68979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 69010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul * Draw to more than one RGBA color buffer (or none). 691f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * All fragment operations, up to (but not) blending/logicop should 692f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * have been done first. 69310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */ 69410f30eb43835c57c00783390a02d72daf4f78e26Brian Paulstatic void 695733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paulmulti_write_rgba_span( GLcontext *ctx, struct sw_span *span ) 69610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{ 69710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); 69810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul GLuint bufferBit; 69910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul SWcontext *swrast = SWRAST_CONTEXT(ctx); 70010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 701733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(colorMask != 0x0); 702733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 70310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul if (ctx->Color.DrawBuffer == GL_NONE) 70410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul return; 70510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 70610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul /* loop over four possible dest color buffers */ 7073b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) { 7083b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul if (bufferBit & ctx->Color._DrawDestMask) { 70910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul GLchan rgbaTmp[MAX_WIDTH][4]; 710733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(span->end < MAX_WIDTH); 71110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 7128ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul /* Set the current read/draw buffer */ 7138ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul swrast->CurrentBuffer = bufferBit; 7148ad1076dc2afda8ed37e5a9f6a757583eba90375Brian Paul (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); 71510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 71610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul /* make copy of incoming colors */ 71777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) ); 71810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 71957857ca0925116d6d254fef7e705cfe0b650d77fBrian Paul if (ctx->Color._LogicOpEnabled) { 72045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_logicop_rgba_span(ctx, span, rgbaTmp); 72110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 72210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul else if (ctx->Color.BlendEnabled) { 72345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_blend_span(ctx, span, rgbaTmp); 72410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 725733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 726733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (colorMask != 0xffffffff) { 72745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_mask_rgba_span(ctx, span, rgbaTmp); 72810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 72910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 730733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_XY) { 731733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* array of pixel coords */ 732733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, 73377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->x, span->array->y, 734733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (const GLchan (*)[4]) rgbaTmp, 73577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 736733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { 73745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_write_alpha_pixels(ctx, span->end, 73877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->x, span->array->y, 739733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (const GLchan (*)[4]) rgbaTmp, 74077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 741733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 742733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 743733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 744733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* horizontal run of pixels */ 745733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y, 746733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (const GLchan (*)[4]) rgbaTmp, 74777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 748733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (swrast->_RasterMask & ALPHABUF_BIT) { 74945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_write_alpha_span(ctx, span->end, span->x, span->y, 750733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (const GLchan (*)[4]) rgbaTmp, 75177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 752733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 75310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 75410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 75510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 75610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 75710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul /* restore default dest buffer */ 7583b4fbbc129c711a5aec8d653d5c6eb2e195f947cBrian Paul _swrast_use_draw_buffer(ctx); 75910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul} 76010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 76110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 762e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 76379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 7647956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span. 7657956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored 7667956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning. 76710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */ 76810f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid 76945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_write_index_span( GLcontext *ctx, struct sw_span *span) 77010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{ 77110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul SWcontext *swrast = SWRAST_CONTEXT(ctx); 7727956292a765910077f50352d7cd0174e1e66d26cBrian Paul const GLuint origInterpMask = span->interpMask; 7732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLuint origArrayMask = span->arrayMask; 77410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 775733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(span->end <= MAX_WIDTH); 776b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || 777b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); 778733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX); 7797956292a765910077f50352d7cd0174e1e66d26cBrian Paul ASSERT((span->interpMask & span->arrayMask) == 0); 7807956292a765910077f50352d7cd0174e1e66d26cBrian Paul 781733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_MASK) { 782733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* mask was initialized by caller, probably glBitmap */ 783733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->writeAll = GL_FALSE; 784733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 785733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 78677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul MEMSET(span->array->mask, 1, span->end); 787733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->writeAll = GL_TRUE; 78810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 78910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 790733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* Clipping */ 791b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 792733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (!clip_span(ctx, span)) { 79386ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul return; 794e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 795e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 796e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 797e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul /* Depth bounds test */ 798e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul if (ctx->Depth.BoundsTest && ctx->Visual.depthBits > 0) { 799e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul if (!_swrast_depth_bounds_test(ctx, span)) { 800e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul return; 801e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul } 802e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul } 803e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul 804b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG 805b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul if (span->arrayMask & SPAN_XY) { 806a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul GLuint i; 807b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul for (i = 0; i < span->end; i++) { 80877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul if (span->array->mask[i]) { 80977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); 81077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); 81177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); 81277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); 813b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 814b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 815b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 816b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif 817b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul 818e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Polygon Stippling */ 819b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 82010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul stipple_polygon_span(ctx, span); 821e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 822e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 8237956292a765910077f50352d7cd0174e1e66d26cBrian Paul /* Depth test and stencil */ 8247956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (ctx->Depth.Test || ctx->Stencil.Enabled) { 8257956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (span->interpMask & SPAN_Z) 82645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_span_interpolate_z(ctx, span); 82710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 8287956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (ctx->Stencil.Enabled) { 82945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_stencil_and_ztest_span(ctx, span)) { 8307956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->arrayMask = origArrayMask; 8317956292a765910077f50352d7cd0174e1e66d26cBrian Paul return; 8327956292a765910077f50352d7cd0174e1e66d26cBrian Paul } 8332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 8347956292a765910077f50352d7cd0174e1e66d26cBrian Paul else { 8357956292a765910077f50352d7cd0174e1e66d26cBrian Paul ASSERT(ctx->Depth.Test); 83645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_depth_test_span(ctx, span)) { 8377956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->arrayMask = origArrayMask; 8387956292a765910077f50352d7cd0174e1e66d26cBrian Paul return; 8397956292a765910077f50352d7cd0174e1e66d26cBrian Paul } 8402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 84110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 84210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 84310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul /* if we get here, something passed the depth test */ 84410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul ctx->OcclusionResult = GL_TRUE; 84510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 846b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query 847b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul if (ctx->Occlusion.Active) { 848b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul GLuint i; 849b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul for (i = 0; i < span->end; i++) 850b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul ctx->Occlusion.PassedCounter += span->array->mask[i]; 851b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul } 852b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif 853b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul 8547956292a765910077f50352d7cd0174e1e66d26cBrian Paul /* we have to wait until after occlusion to do this test */ 8557956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) { 85610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul /* write no pixels */ 8572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask = origArrayMask; 85810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul return; 85910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 86010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 8617956292a765910077f50352d7cd0174e1e66d26cBrian Paul /* Interpolate the color indexes if needed */ 8627956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (span->interpMask & SPAN_INDEX) { 8632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul interpolate_indexes(ctx, span); 8647956292a765910077f50352d7cd0174e1e66d26cBrian Paul /* clear the bit - this allows the WriteMonoCISpan optimization below */ 8657956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->interpMask &= ~SPAN_INDEX; 8667956292a765910077f50352d7cd0174e1e66d26cBrian Paul } 86710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 8687956292a765910077f50352d7cd0174e1e66d26cBrian Paul /* Fog */ 8692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (ctx->Fog.Enabled) { 87045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_fog_ci_span(ctx, span); 871e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 872e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 8732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* Antialias coverage application */ 8742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (span->arrayMask & SPAN_COVERAGE) { 8752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul GLuint i; 87677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLuint *index = span->array->index; 87777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat *coverage = span->array->coverage; 87810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul for (i = 0; i < span->end; i++) { 87977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul ASSERT(coverage[i] < 16); 88077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]); 8815071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul } 8822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul } 8835071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul 8842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (swrast->_RasterMask & MULTI_DRAW_BIT) { 8852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* draw to zero or two or more buffers */ 886733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul multi_write_index_span(ctx, span); 887e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 888e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 8892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* normal situation: draw to exactly one buffer */ 8902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (ctx->Color.IndexLogicOpEnabled) { 89145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_logicop_ci_span(ctx, span, span->array->index); 89210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 8932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 8947956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (ctx->Color.IndexMask != 0xffffffff) { 89545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_mask_index_span(ctx, span, span->array->index); 896e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 8972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 8982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul /* write pixels */ 899733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_XY) { 900733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* array of pixel coords */ 901733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) { 902733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* all pixels have same color index */ 903733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end, 90477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->x, span->array->y, 905733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul FixedToInt(span->index), 90677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 907733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 908733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 90977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x, 91077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->y, span->array->index, 91177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask ); 912733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 9137956292a765910077f50352d7cd0174e1e66d26cBrian Paul } 9147956292a765910077f50352d7cd0174e1e66d26cBrian Paul else { 915733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* horizontal run of pixels */ 916733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) { 917733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* all pixels have same color index */ 918733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y, 919733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul FixedToInt(span->index), 92077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 921733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 922733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 923733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y, 92477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->index, 92577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 926733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 9277956292a765910077f50352d7cd0174e1e66d26cBrian Paul } 928e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 9292a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul 9307956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->interpMask = origInterpMask; 9312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask = origArrayMask; 932e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 933e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 934e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 93579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 9367956292a765910077f50352d7cd0174e1e66d26cBrian Paul * This function may modify any of the array values in the span. 9377956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored 9387956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning. 9395d2621928823a06006c1586efe78fe8bf65a7e1fBrian Paul */ 9405071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid 94145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) 942e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 943cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell SWcontext *swrast = SWRAST_CONTEXT(ctx); 9447956292a765910077f50352d7cd0174e1e66d26cBrian Paul const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); 9457956292a765910077f50352d7cd0174e1e66d26cBrian Paul const GLuint origInterpMask = span->interpMask; 9462a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul const GLuint origArrayMask = span->arrayMask; 9477956292a765910077f50352d7cd0174e1e66d26cBrian Paul GLboolean monoColor; 9487956292a765910077f50352d7cd0174e1e66d26cBrian Paul 949733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(span->end <= MAX_WIDTH); 950b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || 951b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); 9527956292a765910077f50352d7cd0174e1e66d26cBrian Paul ASSERT((span->interpMask & span->arrayMask) == 0); 953ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul ASSERT((span->interpMask | span->arrayMask) & SPAN_RGBA); 954bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#ifdef DEBUG 955733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (ctx->Fog.Enabled) 956733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); 957bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul if (ctx->Depth.Test) 958bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul ASSERT((span->interpMask | span->arrayMask) & SPAN_Z); 959bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul#endif 960733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 961733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_MASK) { 962733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* mask was initialized by caller, probably glBitmap */ 963733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->writeAll = GL_FALSE; 964733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 965733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 96677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul MEMSET(span->array->mask, 1, span->end); 967733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->writeAll = GL_TRUE; 968733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 969e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 9707956292a765910077f50352d7cd0174e1e66d26cBrian Paul /* Determine if we have mono-chromatic colors */ 9717956292a765910077f50352d7cd0174e1e66d26cBrian Paul monoColor = (span->interpMask & SPAN_RGBA) && 9727956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->redStep == 0 && span->greenStep == 0 && 9737956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->blueStep == 0 && span->alphaStep == 0; 9747956292a765910077f50352d7cd0174e1e66d26cBrian Paul 975733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* Clipping */ 976b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 977733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (!clip_span(ctx, span)) { 97886ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul return; 979e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 980e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 981e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 982e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul /* Depth bounds test */ 983e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul if (ctx->Depth.BoundsTest && ctx->Visual.depthBits > 0) { 984e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul if (!_swrast_depth_bounds_test(ctx, span)) { 985e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul return; 986e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul } 987e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul } 988e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul 989b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG 990b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul if (span->arrayMask & SPAN_XY) { 991a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul GLuint i; 992b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul for (i = 0; i < span->end; i++) { 99377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul if (span->array->mask[i]) { 99477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); 99577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); 99677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); 99777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); 998b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 999b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 1000b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 1001b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif 1002b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul 1003e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Polygon Stippling */ 1004b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 10057956292a765910077f50352d7cd0174e1e66d26cBrian Paul stipple_polygon_span(ctx, span); 100610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 100710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 1008610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul /* Fragment program */ 1009610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul if (ctx->FragmentProgram.Enabled) { 1010610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul /* Now we may need to interpolate the colors */ 1011610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul if ((span->interpMask & SPAN_RGBA) && 1012610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul (span->arrayMask & SPAN_RGBA) == 0) { 1013610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul interpolate_colors(ctx, span); 1014610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul span->interpMask &= ~SPAN_RGBA; 1015610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul } 101636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul if (span->interpMask & SPAN_SPEC) { 101736a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul interpolate_specular(ctx, span); 101836a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul } 1019610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul _swrast_exec_nv_fragment_program(ctx, span); 1020610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul monoColor = GL_FALSE; 1021610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul } 1022610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul 1023e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Do the alpha test */ 1024e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (ctx->Color.AlphaEnabled) { 102545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_alpha_test(ctx, span)) { 10267956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->interpMask = origInterpMask; 10272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul span->arrayMask = origArrayMask; 1028e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return; 1029e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 103010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 103110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 1032f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* Stencil and Z testing */ 1033f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (ctx->Stencil.Enabled || ctx->Depth.Test) { 1034f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (span->interpMask & SPAN_Z) 103545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_span_interpolate_z(ctx, span); 1036f1e236987829393c81dc86ea19cb49eefe190317Brian Paul 1037f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (ctx->Stencil.Enabled) { 103845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_stencil_and_ztest_span(ctx, span)) { 10397956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->interpMask = origInterpMask; 1040f1e236987829393c81dc86ea19cb49eefe190317Brian Paul span->arrayMask = origArrayMask; 1041f1e236987829393c81dc86ea19cb49eefe190317Brian Paul return; 104210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 104310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 104410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul else { 1045f1e236987829393c81dc86ea19cb49eefe190317Brian Paul ASSERT(ctx->Depth.Test); 1046f1e236987829393c81dc86ea19cb49eefe190317Brian Paul ASSERT(span->arrayMask & SPAN_Z); 1047f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* regular depth testing */ 104845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_depth_test_span(ctx, span)) { 10497956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->interpMask = origInterpMask; 1050f1e236987829393c81dc86ea19cb49eefe190317Brian Paul span->arrayMask = origArrayMask; 1051f1e236987829393c81dc86ea19cb49eefe190317Brian Paul return; 105210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 105310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul } 1054e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1055e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1056e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* if we get here, something passed the depth test */ 1057e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell ctx->OcclusionResult = GL_TRUE; 1058e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1059b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query 1060b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul if (ctx->Occlusion.Active) { 1061b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul GLuint i; 1062b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul for (i = 0; i < span->end; i++) 1063b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul ctx->Occlusion.PassedCounter += span->array->mask[i]; 1064b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul } 1065b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif 1066b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul 10677956292a765910077f50352d7cd0174e1e66d26cBrian Paul /* can't abort span-writing until after occlusion testing */ 10687956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (colorMask == 0x0) { 10697956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->interpMask = origInterpMask; 10707956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->arrayMask = origArrayMask; 10717956292a765910077f50352d7cd0174e1e66d26cBrian Paul return; 10727956292a765910077f50352d7cd0174e1e66d26cBrian Paul } 10737956292a765910077f50352d7cd0174e1e66d26cBrian Paul 1074ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul /* Now we may need to interpolate the colors */ 1075ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) { 1076ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul interpolate_colors(ctx, span); 1077ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul /* clear the bit - this allows the WriteMonoCISpan optimization below */ 1078ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul span->interpMask &= ~SPAN_RGBA; 1079ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul } 1080ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul 10816e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul /* Fog */ 1082b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul if (ctx->Fog.Enabled) { 108345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_fog_rgba_span(ctx, span); 10847956292a765910077f50352d7cd0174e1e66d26cBrian Paul monoColor = GL_FALSE; 1085b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul } 1086b38ad54c41aec2d08fdd26a4a8ea4dcdca8b1dfdBrian Paul 10875071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul /* Antialias coverage application */ 10882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (span->arrayMask & SPAN_COVERAGE) { 108977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLchan (*rgba)[4] = span->array->rgba; 109077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat *coverage = span->array->coverage; 10915071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul GLuint i; 109210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul for (i = 0; i < span->end; i++) { 109377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); 10945071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul } 10957956292a765910077f50352d7cd0174e1e66d26cBrian Paul monoColor = GL_FALSE; 10965071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul } 10975071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul 1098cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell if (swrast->_RasterMask & MULTI_DRAW_BIT) { 1099733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul multi_write_rgba_span(ctx, span); 1100e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1101e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 1102e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* normal: write to exactly one buffer */ 110357857ca0925116d6d254fef7e705cfe0b650d77fBrian Paul if (ctx->Color._LogicOpEnabled) { 110445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_logicop_rgba_span(ctx, span, span->array->rgba); 11057956292a765910077f50352d7cd0174e1e66d26cBrian Paul monoColor = GL_FALSE; 1106e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1107e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else if (ctx->Color.BlendEnabled) { 110845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_blend_span(ctx, span, span->array->rgba); 11097956292a765910077f50352d7cd0174e1e66d26cBrian Paul monoColor = GL_FALSE; 1110e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 111195e2c72fd52d87163eb543555345f115f050f3aaBrian Paul 1112e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Color component masking */ 11137956292a765910077f50352d7cd0174e1e66d26cBrian Paul if (colorMask != 0xffffffff) { 111445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_mask_rgba_span(ctx, span, span->array->rgba); 11157956292a765910077f50352d7cd0174e1e66d26cBrian Paul monoColor = GL_FALSE; 1116e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1117e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1118e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* write pixels */ 1119733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_XY) { 1120733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* array of pixel coords */ 1121733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* XXX test for mono color */ 112277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x, 112377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask); 1124733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { 112545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_write_alpha_pixels(ctx, span->end, 112677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->x, span->array->y, 112777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (const GLchan (*)[4]) span->array->rgba, 112877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 1129733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 1130e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1131e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 1132733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* horizontal run of pixels */ 1133733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (monoColor) { 1134733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* all pixels have same color */ 1135733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul GLchan color[4]; 1136733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul color[RCOMP] = FixedToChan(span->red); 1137733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul color[GCOMP] = FixedToChan(span->green); 1138733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul color[BCOMP] = FixedToChan(span->blue); 1139733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul color[ACOMP] = FixedToChan(span->alpha); 1140733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x, 114177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->y, color, span->array->mask); 1142957a0cdb13d2564a17c1fc9f6600d6cd56cb48d7Brian Paul if (swrast->_RasterMask & ALPHABUF_BIT) { 114345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_write_mono_alpha_span(ctx, span->end, span->x, span->y, 1144957a0cdb13d2564a17c1fc9f6600d6cd56cb48d7Brian Paul color[ACOMP], 1145957a0cdb13d2564a17c1fc9f6600d6cd56cb48d7Brian Paul span->writeAll ? ((const GLubyte *) NULL) : span->array->mask); 1146957a0cdb13d2564a17c1fc9f6600d6cd56cb48d7Brian Paul } 1147733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 1148733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 1149733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* each pixel is a different color */ 1150733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y, 115177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (const GLchan (*)[4]) span->array->rgba, 115277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->writeAll ? ((const GLubyte *) NULL) : span->array->mask); 1153733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (swrast->_RasterMask & ALPHABUF_BIT) { 115445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_write_alpha_span(ctx, span->end, span->x, span->y, 115577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (const GLchan (*)[4]) span->array->rgba, 115677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->writeAll ? ((const GLubyte *) NULL) : span->array->mask); 1157733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 1158733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 1159e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1160e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1161e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 11627956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->interpMask = origInterpMask; 11637956292a765910077f50352d7cd0174e1e66d26cBrian Paul span->arrayMask = origArrayMask; 11647956292a765910077f50352d7cd0174e1e66d26cBrian Paul} 1165e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1166e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 116779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 1168e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Add specular color to base color. This is used only when 1169f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR. 1170e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 11715071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulstatic void 1172f1e236987829393c81dc86ea19cb49eefe190317Brian Pauladd_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] ) 1173e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 1174e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint i; 1175f1e236987829393c81dc86ea19cb49eefe190317Brian Paul for (i = 0; i < n; i++) { 11764fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#if CHAN_TYPE == GL_FLOAT 11774fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul /* no clamping */ 1178f1e236987829393c81dc86ea19cb49eefe190317Brian Paul rgba[i][RCOMP] += specular[i][RCOMP]; 1179f1e236987829393c81dc86ea19cb49eefe190317Brian Paul rgba[i][GCOMP] += specular[i][GCOMP]; 1180f1e236987829393c81dc86ea19cb49eefe190317Brian Paul rgba[i][BCOMP] += specular[i][BCOMP]; 11814fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#else 1182f1e236987829393c81dc86ea19cb49eefe190317Brian Paul GLint r = rgba[i][RCOMP] + specular[i][RCOMP]; 1183f1e236987829393c81dc86ea19cb49eefe190317Brian Paul GLint g = rgba[i][GCOMP] + specular[i][GCOMP]; 1184f1e236987829393c81dc86ea19cb49eefe190317Brian Paul GLint b = rgba[i][BCOMP] + specular[i][BCOMP]; 1185e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX); 1186e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX); 1187e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX); 11884fa5c1966a985f81c615a9f5ef2f64dd466b252aBrian Paul#endif 1189e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1190e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 1191e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1192e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 119379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 1194f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span. 11957956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored 11967956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning. 119778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */ 119878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid 119945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_write_texture_span( GLcontext *ctx, struct sw_span *span) 120078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{ 120178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); 120278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul SWcontext *swrast = SWRAST_CONTEXT(ctx); 1203e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul const GLuint origInterpMask = span->interpMask; 1204f1e236987829393c81dc86ea19cb49eefe190317Brian Paul const GLuint origArrayMask = span->arrayMask; 1205f1e236987829393c81dc86ea19cb49eefe190317Brian Paul 1206b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || 1207b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); 1208733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul ASSERT(span->end <= MAX_WIDTH); 12097956292a765910077f50352d7cd0174e1e66d26cBrian Paul ASSERT((span->interpMask & span->arrayMask) == 0); 1210853bda3e7c4dfa7d8cc462729f6a3dce89e44963Brian Paul ASSERT(ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram.Enabled); 121178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 1212ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul /* 1213ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask); 1214ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul */ 1215ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul 1216733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_MASK) { 1217733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* mask was initialized by caller, probably glBitmap */ 1218733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->writeAll = GL_FALSE; 1219733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 1220733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 122177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul MEMSET(span->array->mask, 1, span->end); 1222733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul span->writeAll = GL_TRUE; 122378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul } 122478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 1225733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* Clipping */ 1226b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 1227733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (!clip_span(ctx, span)) { 1228733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul return; 122978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul } 123078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul } 123178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 1232b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG 1233b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul if (span->arrayMask & SPAN_XY) { 1234a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul GLuint i; 1235b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul for (i = 0; i < span->end; i++) { 123677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul if (span->array->mask[i]) { 123777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); 123877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); 123977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); 124077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); 1241b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 1242b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 1243b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul } 1244b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif 1245b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul 124678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul /* Polygon Stippling */ 1247b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 1248733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul stipple_polygon_span(ctx, span); 124978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul } 125078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 1251f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* Need texture coordinates now */ 1252f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if ((span->interpMask & SPAN_TEXTURE) 1253f1e236987829393c81dc86ea19cb49eefe190317Brian Paul && (span->arrayMask & SPAN_TEXTURE) == 0) 1254f1e236987829393c81dc86ea19cb49eefe190317Brian Paul interpolate_texcoords(ctx, span); 125578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 125678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul /* Texture with alpha test */ 125778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul if (ctx->Color.AlphaEnabled) { 1258f1e236987829393c81dc86ea19cb49eefe190317Brian Paul 1259f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* Now we need the rgba array, fill it in if needed */ 1260f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) 1261f1e236987829393c81dc86ea19cb49eefe190317Brian Paul interpolate_colors(ctx, span); 1262f1e236987829393c81dc86ea19cb49eefe190317Brian Paul 126336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul if (span->interpMask & SPAN_SPEC) { 126436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul interpolate_specular(ctx, span); 126536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul } 126636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul 126778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul /* Texturing without alpha is done after depth-testing which 1268f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * gives a potential speed-up. 1269f1e236987829393c81dc86ea19cb49eefe190317Brian Paul */ 1270610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul if (ctx->FragmentProgram.Enabled) 1271610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul _swrast_exec_nv_fragment_program( ctx, span ); 1272610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul else 1273610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul _swrast_texture_span( ctx, span ); 127478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 127578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul /* Do the alpha test */ 127645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_alpha_test(ctx, span)) { 1277f1e236987829393c81dc86ea19cb49eefe190317Brian Paul span->arrayMask = origArrayMask; 1278ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul return; 127978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul } 128078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul } 128178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 1282f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* Stencil and Z testing */ 1283f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (ctx->Stencil.Enabled || ctx->Depth.Test) { 1284f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (span->interpMask & SPAN_Z) 128545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_span_interpolate_z(ctx, span); 128678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul 128771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul if (ctx->Stencil.Enabled) { 128845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_stencil_and_ztest_span(ctx, span)) { 1289e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul span->interpMask = origInterpMask; 1290f1e236987829393c81dc86ea19cb49eefe190317Brian Paul span->arrayMask = origArrayMask; 129110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul return; 1292f1e236987829393c81dc86ea19cb49eefe190317Brian Paul } 129371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 1294f1e236987829393c81dc86ea19cb49eefe190317Brian Paul else { 1295f1e236987829393c81dc86ea19cb49eefe190317Brian Paul ASSERT(ctx->Depth.Test); 1296f1e236987829393c81dc86ea19cb49eefe190317Brian Paul ASSERT(span->arrayMask & SPAN_Z); 129710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul /* regular depth testing */ 129845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul if (!_swrast_depth_test_span(ctx, span)) { 1299e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul span->interpMask = origInterpMask; 1300f1e236987829393c81dc86ea19cb49eefe190317Brian Paul span->arrayMask = origArrayMask; 130110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul return; 1302f1e236987829393c81dc86ea19cb49eefe190317Brian Paul } 130371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 130471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 130571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1306f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* if we get here, some fragments passed the depth test */ 130771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul ctx->OcclusionResult = GL_TRUE; 130871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1309b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query 1310b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul if (ctx->Occlusion.Active) { 1311b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul GLuint i; 1312b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul for (i = 0; i < span->end; i++) 1313b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul ctx->Occlusion.PassedCounter += span->array->mask[i]; 1314b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul } 1315b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif 1316b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul 1317f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* We had to wait until now to check for glColorMask(F,F,F,F) because of 1318f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * the occlusion test. 1319f1e236987829393c81dc86ea19cb49eefe190317Brian Paul */ 1320f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (colorMask == 0x0) { 1321e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul span->interpMask = origInterpMask; 1322f1e236987829393c81dc86ea19cb49eefe190317Brian Paul span->arrayMask = origArrayMask; 1323f1e236987829393c81dc86ea19cb49eefe190317Brian Paul return; 132471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 132571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1326f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* Texture without alpha test */ 1327f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (!ctx->Color.AlphaEnabled) { 132871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1329f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* Now we need the rgba array, fill it in if needed */ 1330f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) 1331f1e236987829393c81dc86ea19cb49eefe190317Brian Paul interpolate_colors(ctx, span); 133271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 133336a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul if (span->interpMask & SPAN_SPEC) { 133436a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul interpolate_specular(ctx, span); 133536a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul } 133636a0a3252e1e20df69b53f70ba93bc74c4a4bf0eBrian Paul 1337610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul if (ctx->FragmentProgram.Enabled) 1338610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul _swrast_exec_nv_fragment_program( ctx, span ); 1339610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul else 1340610d59981a9f43fefe29b34ef19c184d28e2bef5Brian Paul _swrast_texture_span( ctx, span ); 134171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 134271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1343f1e236987829393c81dc86ea19cb49eefe190317Brian Paul ASSERT(span->arrayMask & SPAN_RGBA); 13442ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul 1345f1e236987829393c81dc86ea19cb49eefe190317Brian Paul /* Add base and specular colors */ 1346f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (ctx->Fog.ColorSumEnabled || 1347f1e236987829393c81dc86ea19cb49eefe190317Brian Paul (ctx->Light.Enabled && 1348f1e236987829393c81dc86ea19cb49eefe190317Brian Paul ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { 1349f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (span->interpMask & SPAN_SPEC) { 1350f1e236987829393c81dc86ea19cb49eefe190317Brian Paul interpolate_specular(ctx, span); 135171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 1352f1e236987829393c81dc86ea19cb49eefe190317Brian Paul ASSERT(span->arrayMask & SPAN_SPEC); 135377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul add_colors( span->end, span->array->rgba, span->array->spec ); 135471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 135571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 13566e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul /* Fog */ 135771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul if (ctx->Fog.Enabled) { 135845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_fog_rgba_span(ctx, span); 135971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 1360f1e236987829393c81dc86ea19cb49eefe190317Brian Paul 136171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul /* Antialias coverage application */ 13622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul if (span->arrayMask & SPAN_COVERAGE) { 136377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLchan (*rgba)[4] = span->array->rgba; 136477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul GLfloat *coverage = span->array->coverage; 136571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul GLuint i; 136610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul for (i = 0; i < span->end; i++) { 136777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); 136871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 136971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 137071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 137171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul if (swrast->_RasterMask & MULTI_DRAW_BIT) { 1372733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul multi_write_rgba_span(ctx, span); 137371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 137471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul else { 137571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul /* normal: write to exactly one buffer */ 137657857ca0925116d6d254fef7e705cfe0b650d77fBrian Paul if (ctx->Color._LogicOpEnabled) { 137745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_logicop_rgba_span(ctx, span, span->array->rgba); 137871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 137995e2c72fd52d87163eb543555345f115f050f3aaBrian Paul else if (ctx->Color.BlendEnabled) { 138045bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_blend_span(ctx, span, span->array->rgba); 138171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 138271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1383e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul /* Color component masking */ 1384f1e236987829393c81dc86ea19cb49eefe190317Brian Paul if (colorMask != 0xffffffff) { 138545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_mask_rgba_span(ctx, span, span->array->rgba); 138671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 138771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1388e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul /* write pixels */ 1389733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (span->arrayMask & SPAN_XY) { 1390733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* array of pixel coords */ 139177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x, 139277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask); 1393733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { 139445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_write_alpha_pixels(ctx, span->end, 139577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->x, span->array->y, 139677df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (const GLchan (*)[4]) span->array->rgba, 139777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->array->mask); 1398733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 1399733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 1400733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul else { 1401733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* horizontal run of pixels */ 1402733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y, 140377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (const GLchan (*)[4]) span->array->rgba, 140477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->writeAll ? NULL : span->array->mask); 1405733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (swrast->_RasterMask & ALPHABUF_BIT) { 140645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_write_alpha_span(ctx, span->end, span->x, span->y, 140777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul (const GLchan (*)[4]) span->array->rgba, 140877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul span->writeAll ? NULL : span->array->mask); 1409733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 141071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 141171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul } 141271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul 1413e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul span->interpMask = origInterpMask; 1414f1e236987829393c81dc86ea19cb49eefe190317Brian Paul span->arrayMask = origArrayMask; 141510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul} 141610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul 1417e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1418e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 141979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 1420e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read RGBA pixels from frame buffer. Clipping will be done to prevent 1421e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries. 1422e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 14235071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid 142445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer, 14255071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul GLuint n, GLint x, GLint y, GLchan rgba[][4] ) 1426e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 1427709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell SWcontext *swrast = SWRAST_CONTEXT(ctx); 1428a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul const GLint bufWidth = (GLint) buffer->Width; 14291113e3266f1a9df3506fb80189bfe00d9681b55eBrian Paul const GLint bufHeight = (GLint) buffer->Height; 1430a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul 1431a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 1432e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* completely above, below, or right */ 1433e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* XXX maybe leave undefined? */ 14346ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul _mesa_bzero(rgba, 4 * n * sizeof(GLchan)); 1435e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1436e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 1437e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint skip, length; 1438e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (x < 0) { 1439e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* left edge clippping */ 1440e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell skip = -x; 1441e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell length = (GLint) n - skip; 1442e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (length < 0) { 1443e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* completely left of window */ 1444e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return; 1445e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1446a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul if (length > bufWidth) { 1447a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul length = bufWidth; 1448e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1449e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1450a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul else if ((GLint) (x + n) > bufWidth) { 1451e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* right edge clipping */ 1452e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell skip = 0; 1453a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul length = bufWidth - x; 1454e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (length < 0) { 1455e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* completely to right of window */ 1456e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return; 1457e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1458e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1459e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 1460e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* no clipping */ 1461e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell skip = 0; 1462e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell length = (GLint) n; 1463e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1464e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1465709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip ); 1466e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (buffer->UseSoftwareAlphaBuffers) { 146745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul _swrast_read_alpha_span(ctx, length, x + skip, y, rgba + skip); 1468e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1469e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1470e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 1471e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1472e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 147379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/** 1474e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Read CI pixels from frame buffer. Clipping will be done to prevent 1475e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries. 1476e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 14775071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid 147845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_read_index_span( GLcontext *ctx, GLframebuffer *buffer, 14795071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul GLuint n, GLint x, GLint y, GLuint indx[] ) 1480e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 1481709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell SWcontext *swrast = SWRAST_CONTEXT(ctx); 1482a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul const GLint bufWidth = (GLint) buffer->Width; 14831113e3266f1a9df3506fb80189bfe00d9681b55eBrian Paul const GLint bufHeight = (GLint) buffer->Height; 1484a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul 1485a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 1486e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* completely above, below, or right */ 14876ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul _mesa_bzero(indx, n * sizeof(GLuint)); 1488e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1489e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 1490e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint skip, length; 1491e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (x < 0) { 1492e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* left edge clippping */ 1493e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell skip = -x; 1494e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell length = (GLint) n - skip; 1495e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (length < 0) { 1496e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* completely left of window */ 1497e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return; 1498e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1499a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul if (length > bufWidth) { 1500a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul length = bufWidth; 1501e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1502e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1503a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul else if ((GLint) (x + n) > bufWidth) { 1504e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* right edge clipping */ 1505e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell skip = 0; 1506a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul length = bufWidth - x; 1507e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (length < 0) { 1508e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* completely to right of window */ 1509e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return; 1510e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1511e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1512e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 1513e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* no clipping */ 1514e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell skip = 0; 1515e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell length = (GLint) n; 1516e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1517e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 1518709892459922a32096fe9dd8261d0d92337bb02fKeith Whitwell (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip ); 1519e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 1520e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 1521