s_span.c revision 9d216be8cfe57f88cd2d890c2334df8ff5c30436
1e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library
31d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian * Version:  7.1
422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
5884af408644e3fa9aa0ffc544f84ec4a7f3a93b9Brian * Copyright (C) 1999-2007  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
33bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/glheader.h"
34bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/colormac.h"
35bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/context.h"
36bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/macros.h"
37bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/imports.h"
38bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/image.h"
39e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
407f752fed993e5e9423abac200dd59141edbada56Dave Airlie#include "s_atifragshader.h"
41bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol#include "s_alpha.h"
42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
43cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
44e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
48c968d3d410a1897ecbb41d3557adaef69a4c627aBrian#include "s_fragprog.h"
49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
5155187ea63e980b32c7a701855571332f4357d634Brian Paul#include "s_texcombine.h"
52e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
532a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
5479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Set default fragment attributes for the span using the
569e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * current raster values.  Used prior to glDraw/CopyPixels
579e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * and glBitmap.
582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian_swrast_span_default_attribs(GLcontext *ctx, SWspan *span)
612a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
629e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* Z*/
639e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   {
649e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (ctx->DrawBuffer->Visual.depthBits <= 16)
669e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
676254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao      else {
686254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao         GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax;
696254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao         tmpf = MIN2(tmpf, depthMax);
706254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao         span->z = (GLint)tmpf;
716254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao      }
729e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->zStep = 0;
739e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->interpMask |= SPAN_Z;
74884af408644e3fa9aa0ffc544f84ec4a7f3a93b9Brian   }
752a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
769e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* W (for perspective correction) */
779e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
789e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
799e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
819e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* primary color, or color index */
822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (ctx->Visual.rgbMode) {
832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLchan r, g, b, a;
842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
872a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red = r;
902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = g;
912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue = b;
922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = a;
932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->red   = IntToFixed(r);
952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->green = IntToFixed(g);
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blue  = IntToFixed(b);
972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alpha = IntToFixed(a);
982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->redStep = 0;
1002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->greenStep = 0;
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->blueStep = 0;
1022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->alphaStep = 0;
1032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_RGBA;
1049e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1059e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor);
1069e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
1079e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
1082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1092a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
1100f3cd3f894612d156de454178effa4c732f96da7Brian Paul      span->index = FloatToFixed(ctx->Current.RasterIndex);
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->indexStep = 0;
1122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->interpMask |= SPAN_INDEX;
1132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
1142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1159e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* Secondary color */
116f793e90e823a58c0408771c38f3a6209f78a3617Brian   if (ctx->Visual.rgbMode && (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled))
117f793e90e823a58c0408771c38f3a6209f78a3617Brian   {
1189e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor);
1199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
1209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
1219e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
1229e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1239e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* fog */
1249e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   {
1259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLfloat fogVal; /* a coord or a blend factor */
1279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (swrast->_PreferPixelFog) {
1289e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* fog blend factors will be computed from fog coordinates per pixel */
1299e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         fogVal = ctx->Current.RasterDistance;
1309e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
1319e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      else {
1329e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* fog blend factor should be computed from fogcoord now */
1339e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
1349e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
1359e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
1369e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
1379e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
1389e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
1399e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1409e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* texcoords */
1419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   {
1429e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLuint i;
1439e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
1449e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLuint attr = FRAG_ATTRIB_TEX0 + i;
1459e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat *tc = ctx->Current.RasterTexCoords[i];
1469e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) {
1479e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            COPY_4V(span->attrStart[attr], tc);
1489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
1499e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         else if (tc[3] > 0.0F) {
1509e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            /* use (s/q, t/q, r/q, 1) */
1519e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][0] = tc[0] / tc[3];
1529e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][1] = tc[1] / tc[3];
1539e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][2] = tc[2] / tc[3];
1549e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][3] = 1.0;
1559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
1569e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         else {
1579e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
1589e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
1599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
1609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
1619e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
16238a1c2b4959d35236933c14d3944cce94283ca30Brian   }
16338a1c2b4959d35236933c14d3944cce94283ca30Brian}
16438a1c2b4959d35236933c14d3944cce94283ca30Brian
16538a1c2b4959d35236933c14d3944cce94283ca30Brian
1664753d60dd070bb08d0116076bcc08025c86ce857Brian Paul/**
1679e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Interpolate the active attributes (and'd with attrMask) to
1689e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * fill in span->array->attribs[].
1699e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Perspective correction will be done.  The point/line/triangle function
1709e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]!
1714753d60dd070bb08d0116076bcc08025c86ce857Brian Paul */
1729e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrianstatic INLINE void
1739e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrianinterpolate_active_attribs(GLcontext *ctx, SWspan *span, GLbitfield attrMask)
1744753d60dd070bb08d0116076bcc08025c86ce857Brian Paul{
1759e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1769e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1779dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian   /*
1789dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian    * Don't overwrite existing array values, such as colors that may have
1799dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian    * been produced by glDraw/CopyPixels.
180171dcdfa27dda30916a7f9bfed89577feee5d350Brian    */
1819dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian   attrMask &= ~span->arrayAttribs;
182171dcdfa27dda30916a7f9bfed89577feee5d350Brian
1839e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ATTRIB_LOOP_BEGIN
1849e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (attrMask & (1 << attr)) {
1859e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
1869e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
1879e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv0dx = span->attrStepX[attr][0];
1889e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv1dx = span->attrStepX[attr][1];
1899e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv2dx = span->attrStepX[attr][2];
1909e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv3dx = span->attrStepX[attr][3];
1919e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat v0 = span->attrStart[attr][0];
1929e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat v1 = span->attrStart[attr][1];
1939e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat v2 = span->attrStart[attr][2];
1949e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat v3 = span->attrStart[attr][3];
1959e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLuint k;
1969e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         for (k = 0; k < span->end; k++) {
1979e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            const GLfloat invW = 1.0f / w;
1989e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][0] = v0 * invW;
1999e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][1] = v1 * invW;
2009e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][2] = v2 * invW;
2019e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][3] = v3 * invW;
2029e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v0 += dv0dx;
2039e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v1 += dv1dx;
2049e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v2 += dv2dx;
2059e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v3 += dv3dx;
2069e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            w += dwdx;
2079e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
2089dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian         ASSERT((span->arrayAttribs & (1 << attr)) == 0);
2099e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         span->arrayAttribs |= (1 << attr);
210e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
2119e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ATTRIB_LOOP_END
2124753d60dd070bb08d0116076bcc08025c86ce857Brian Paul}
2134753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
2144753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
215d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
2169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
2179e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * color array.
218d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
219f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
2209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrianinterpolate_int_colors(GLcontext *ctx, SWspan *span)
2212a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
2222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
2232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
2242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#if CHAN_BITS != 32
2269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(!(span->arrayMask & SPAN_RGBA));
2279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
2282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
229e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   switch (span->array->ChanType) {
2301e3223c02a2f6155beb5784cadbea1f46703829aBrian Paul#if CHAN_BITS != 32
231e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_BYTE:
232e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
2339e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLubyte (*rgba)[4] = span->array->rgba8;
234e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
235d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLubyte color[4];
236e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
237e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
238e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
239e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
240d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
241d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4UBV(rgba[i], color);
242d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
243d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
244e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
245e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = span->red;
246e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = span->green;
247e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = span->blue;
248e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed a = span->alpha;
249e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = span->redStep;
250e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = span->greenStep;
251e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = span->blueStep;
252e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint da = span->alphaStep;
253d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
254e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][RCOMP] = FixedToChan(r);
255e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][GCOMP] = FixedToChan(g);
256e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][BCOMP] = FixedToChan(b);
257e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][ACOMP] = FixedToChan(a);
258e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               r += dr;
259e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               g += dg;
260e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               b += db;
261e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               a += da;
262d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
263d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
264e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
265e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
266e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_SHORT:
267e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
2689e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLushort (*rgba)[4] = span->array->rgba16;
269e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
270e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort color[4];
271e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
272e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
273e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
274e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
275d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
276d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4V(rgba[i], color);
277d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
278d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
279e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
2809e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            GLushort (*rgba)[4] = span->array->rgba16;
281d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfixed r, g, b, a;
282d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint dr, dg, db, da;
283e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            r = span->red;
284e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            g = span->green;
285e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            b = span->blue;
286e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            a = span->alpha;
287e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = span->redStep;
288e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dg = span->greenStep;
289e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            db = span->blueStep;
290e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            da = span->alphaStep;
291d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
292d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][RCOMP] = FixedToChan(r);
293d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][GCOMP] = FixedToChan(g);
294d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][BCOMP] = FixedToChan(b);
295d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][ACOMP] = FixedToChan(a);
296d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
297d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
298d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
299d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a += da;
300d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
301d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
302e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
303e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
304e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul#endif
305e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_FLOAT:
3069e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
307e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
308e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   default:
3099e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      _mesa_problem(NULL, "bad datatype in interpolate_int_colors");
310e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   }
311e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   span->arrayMask |= SPAN_RGBA;
312e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul}
313e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
314e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
315e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul/**
3169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Populate the FRAG_ATTRIB_COL0 array.
317e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul */
318f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
3199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrianinterpolate_float_colors(SWspan *span)
320e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul{
3219e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
322e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   const GLuint n = span->end;
323e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   GLuint i;
324e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul
3259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   assert(!(span->arrayAttribs & FRAG_BIT_COL0));
3269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
3279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if (span->arrayMask & SPAN_RGBA) {
3289e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* convert array of int colors */
3299e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      for (i = 0; i < n; i++) {
3309e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][0] = UBYTE_TO_FLOAT(span->array->rgba8[i][0]);
3319e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][1] = UBYTE_TO_FLOAT(span->array->rgba8[i][1]);
3329e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][2] = UBYTE_TO_FLOAT(span->array->rgba8[i][2]);
3339e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][3] = UBYTE_TO_FLOAT(span->array->rgba8[i][3]);
334e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
3359e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
3369e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   else {
3379e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* interpolate red/green/blue/alpha to get float colors */
3389e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      ASSERT(span->interpMask & SPAN_RGBA);
3399e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (span->interpMask & SPAN_FLAT) {
3409e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat r = FixedToFloat(span->red);
3419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat g = FixedToFloat(span->green);
3429e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat b = FixedToFloat(span->blue);
3439e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat a = FixedToFloat(span->alpha);
3449e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         for (i = 0; i < n; i++) {
3459e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            ASSIGN_4V(col0[i], r, g, b, a);
346e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         }
347e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
3489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      else {
3499e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat r = FixedToFloat(span->red);
3509e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat g = FixedToFloat(span->green);
3519e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat b = FixedToFloat(span->blue);
3529e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat a = FixedToFloat(span->alpha);
3539e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat dr = FixedToFloat(span->redStep);
3549e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat dg = FixedToFloat(span->greenStep);
3559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat db = FixedToFloat(span->blueStep);
3569e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat da = FixedToFloat(span->alphaStep);
357e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul         for (i = 0; i < n; i++) {
3589e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            col0[i][0] = r;
3599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            col0[i][1] = g;
3609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            col0[i][2] = b;
3619e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            col0[i][3] = a;
362e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            r += dr;
363e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            g += dg;
364e6f47d1855354165c6eed5080d8a72024891f10fBrian Paul            b += db;
3659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            a += da;
366d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
3672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
3699e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
3709e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->arrayAttribs |= FRAG_BIT_COL0;
3719e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->array->ChanType = GL_FLOAT;
3722a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
3732a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3742a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3759e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
3762a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul/* Fill in the span.color.index array from the interpolation values */
377f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
378cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_indexes(GLcontext *ctx, SWspan *span)
3792a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLfixed index = span->index;
3812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLint indexStep = span->indexStep;
3822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
38377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLuint *indexes = span->array->index;
3842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
385a6c423d95663cfd8601cf84e10e8e1b12fa6ef15Brian Paul   (void) ctx;
3869e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
3879e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(!(span->arrayMask & SPAN_INDEX));
3882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3892a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) {
3902a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* constant color */
3912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      index = FixedToInt(index);
3922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
3932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = index;
3942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
3962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
3972a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* interpolate */
3982a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
3992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         indexes[i] = FixedToInt(index);
4002a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         index += indexStep;
4012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_INDEX;
404e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   span->interpMask &= ~SPAN_INDEX;
4052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4089e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian/**
4099e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Fill in the span.zArray array from the span->z, zStep values.
4109e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian */
411711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
412cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span )
4132a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
4142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
4152a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
4162a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4179e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(!(span->arrayMask & SPAN_Z));
4182a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
41931e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16) {
4202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
4213e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
422ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      for (i = 0; i < n; i++) {
42377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = FixedToInt(zval);
4242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4252a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4262a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
4272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
4282a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
4297265556b9aa0367e9b5031e7cb15ed2a5d73866dBrian Paul      GLuint zval = span->z;
4303e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
4312a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
43277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = zval;
4332a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4342a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4352a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
43632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   span->interpMask &= ~SPAN_Z;
4372a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
4382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4392a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4402a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian/**
4429e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Compute mipmap LOD from partial derivatives.
44331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
444c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
445c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#if 0
44631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulstatic GLfloat
44731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paulcompute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
44831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
44931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul               GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
450c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
45131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
45231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
45331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
45431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
455f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
456f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
45731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
45831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
45931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
460c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
461c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul#endif
462c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
46331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
4649e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian/**
4659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Compute mipmap LOD from partial derivatives.
4669e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * This is a faster approximation than above function.
467c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
468350353adcd75f94fda63c787c86961716114e0bfBrian PaulGLfloat
46945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
470350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
471350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
472c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
47331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
47431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
47531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
47631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
47731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
47831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
47931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
48031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
48131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
48231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
48331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
48431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
48531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
48631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
487c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
488c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
489d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
490d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul/**
4919e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the
4929e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * using the attrStart/Step values.
4939e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian *
4949e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * This function only used during fixed-function fragment processing.
4959e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian *
496d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * Note: in the places where we divide by Q (or mult by invQ) we're
497d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * really doing two things: perspective correction and texcoord
498d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * projection.  Remember, for texcoord (s,t,r,q) we need to index
499d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * texels with (s/q, t/q, r/q).
500c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
5012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
502cdb27e8242215271364602995d85607cfc06d441Brian Paulinterpolate_texcoords(GLcontext *ctx, SWspan *span)
5032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
504e4f976b8b9d74a74b5816146cb11880c3a493929Brian   const GLuint maxUnit
505e4f976b8b9d74a74b5816146cb11880c3a493929Brian      = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
506e4f976b8b9d74a74b5816146cb11880c3a493929Brian   GLuint u;
507e4f976b8b9d74a74b5816146cb11880c3a493929Brian
508e4f976b8b9d74a74b5816146cb11880c3a493929Brian   /* XXX CoordUnits vs. ImageUnits */
509e4f976b8b9d74a74b5816146cb11880c3a493929Brian   for (u = 0; u < maxUnit; u++) {
510e4f976b8b9d74a74b5816146cb11880c3a493929Brian      if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
511e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLuint attr = FRAG_ATTRIB_TEX0 + u;
512c000843a14e73d593d87ff6674d0295d2cb64a12Brian         const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
513e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat texW, texH;
514e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLboolean needLambda;
515e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat (*texcoord)[4] = span->array->attribs[attr];
516e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat *lambda = span->array->lambda[u];
517e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dsdx = span->attrStepX[attr][0];
518e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dsdy = span->attrStepY[attr][0];
519e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dtdx = span->attrStepX[attr][1];
520e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dtdy = span->attrStepY[attr][1];
521e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat drdx = span->attrStepX[attr][2];
522e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dqdx = span->attrStepX[attr][3];
523e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dqdy = span->attrStepY[attr][3];
524e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat s = span->attrStart[attr][0];
525e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat t = span->attrStart[attr][1];
526e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat r = span->attrStart[attr][2];
527e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat q = span->attrStart[attr][3];
528e4f976b8b9d74a74b5816146cb11880c3a493929Brian
529e4f976b8b9d74a74b5816146cb11880c3a493929Brian         if (obj) {
530e4f976b8b9d74a74b5816146cb11880c3a493929Brian            const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
531e4f976b8b9d74a74b5816146cb11880c3a493929Brian            needLambda = (obj->MinFilter != obj->MagFilter)
532e4f976b8b9d74a74b5816146cb11880c3a493929Brian               || ctx->FragmentProgram._Current;
533e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texW = img->WidthScale;
534e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texH = img->HeightScale;
535e4f976b8b9d74a74b5816146cb11880c3a493929Brian         }
536e4f976b8b9d74a74b5816146cb11880c3a493929Brian         else {
537e4f976b8b9d74a74b5816146cb11880c3a493929Brian            /* using a fragment program */
538e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texW = 1.0;
539e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texH = 1.0;
540e4f976b8b9d74a74b5816146cb11880c3a493929Brian            needLambda = GL_FALSE;
541e4f976b8b9d74a74b5816146cb11880c3a493929Brian         }
542e4f976b8b9d74a74b5816146cb11880c3a493929Brian
543e4f976b8b9d74a74b5816146cb11880c3a493929Brian         if (needLambda) {
544e4f976b8b9d74a74b5816146cb11880c3a493929Brian            GLuint i;
545e4f976b8b9d74a74b5816146cb11880c3a493929Brian            if (ctx->FragmentProgram._Current
546e4f976b8b9d74a74b5816146cb11880c3a493929Brian                || ctx->ATIFragmentShader._Enabled) {
547e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* do perspective correction but don't divide s, t, r by q */
548e4f976b8b9d74a74b5816146cb11880c3a493929Brian               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
549e4f976b8b9d74a74b5816146cb11880c3a493929Brian               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
550e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
551e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invW = 1.0F / w;
552e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invW;
553e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invW;
554e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invW;
555e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q * invW;
556e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
557e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     dqdx, dqdy, texW, texH,
558e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     s, t, q, invW);
559e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
560e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
561e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
562e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
563e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  w += dwdx;
5642a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
5652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
56631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
567e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
5682a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
569e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
570e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
571e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
572e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
573e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
574e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     dqdx, dqdy, texW, texH,
575e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     s, t, q, invQ);
576e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
577e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
578e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
579e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
5802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
581d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
582e4f976b8b9d74a74b5816146cb11880c3a493929Brian            span->arrayMask |= SPAN_LAMBDA;
583d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
584d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else {
585e4f976b8b9d74a74b5816146cb11880c3a493929Brian            GLuint i;
586e4f976b8b9d74a74b5816146cb11880c3a493929Brian            if (ctx->FragmentProgram._Current ||
587e4f976b8b9d74a74b5816146cb11880c3a493929Brian                ctx->ATIFragmentShader._Enabled) {
588e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* do perspective correction but don't divide s, t, r by q */
589e4f976b8b9d74a74b5816146cb11880c3a493929Brian               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
590e4f976b8b9d74a74b5816146cb11880c3a493929Brian               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
591e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
592e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invW = 1.0F / w;
593e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invW;
594e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invW;
595e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invW;
596e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q * invW;
597e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
598e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
599e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
600e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
601e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
602e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  w += dwdx;
603e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
604c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
605e4f976b8b9d74a74b5816146cb11880c3a493929Brian            else if (dqdx == 0.0F) {
606e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* Ortho projection or polygon's parallel to window X axis */
607c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
608e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
609e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
610e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
611e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
612e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
613e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
614e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
615e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
616e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
617e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
618c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
619e4f976b8b9d74a74b5816146cb11880c3a493929Brian            else {
620e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
621e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
622e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
623e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
624e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
625e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
626e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
627e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
628e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
629e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
630e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
631e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
632e4f976b8b9d74a74b5816146cb11880c3a493929Brian            }
633e4f976b8b9d74a74b5816146cb11880c3a493929Brian         } /* lambda */
634e4f976b8b9d74a74b5816146cb11880c3a493929Brian      } /* if */
635e4f976b8b9d74a74b5816146cb11880c3a493929Brian   } /* for */
63610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
637e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
638e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
639bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol/**
640f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
641f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian */
642f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brianstatic INLINE void
643f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brianinterpolate_wpos(GLcontext *ctx, SWspan *span)
644f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian{
645f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
646f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLuint i;
6478e6207396c6314d07614c80670f4e3196e3a8551Brian   const GLfloat zScale = 1.0 / ctx->DrawBuffer->_DepthMaxF;
6488e6207396c6314d07614c80670f4e3196e3a8551Brian   GLfloat w, dw;
6498e6207396c6314d07614c80670f4e3196e3a8551Brian
650f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   if (span->arrayMask & SPAN_XY) {
651f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      for (i = 0; i < span->end; i++) {
652f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][0] = (GLfloat) span->array->x[i];
653f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][1] = (GLfloat) span->array->y[i];
654f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      }
655f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
656f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   else {
657f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      for (i = 0; i < span->end; i++) {
658f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][0] = (GLfloat) span->x + i;
659f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][1] = (GLfloat) span->y;
660f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      }
661f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
6628e6207396c6314d07614c80670f4e3196e3a8551Brian
6638e6207396c6314d07614c80670f4e3196e3a8551Brian   w = span->attrStart[FRAG_ATTRIB_WPOS][3];
6648e6207396c6314d07614c80670f4e3196e3a8551Brian   dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
665f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   for (i = 0; i < span->end; i++) {
6668e6207396c6314d07614c80670f4e3196e3a8551Brian      wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
6678e6207396c6314d07614c80670f4e3196e3a8551Brian      wpos[i][3] = w;
6688e6207396c6314d07614c80670f4e3196e3a8551Brian      w += dw;
669f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
670f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian}
671f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
672f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
673f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian/**
674e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
675e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
676f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
677ea8b68e0f7e7a4025ce662d36380157273ce10a3Brianstipple_polygon_span(GLcontext *ctx, SWspan *span)
67810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
67977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLubyte *mask = span->array->mask;
680733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
681733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
68210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
683ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (span->arrayMask & SPAN_XY) {
684ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      /* arrays of x/y pixel coords */
685ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      GLuint i;
686ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      for (i = 0; i < span->end; i++) {
687ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLint col = span->array->x[i] % 32;
688ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLint row = span->array->y[i] % 32;
689ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLuint stipple = ctx->PolygonStipple[row];
690ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if (((1 << col) & stipple) == 0) {
691ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            mask[i] = 0;
692ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
69310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
694ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   }
695ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   else {
696ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      /* horizontal span of pixels */
697ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      const GLuint highBit = 1 << 31;
698ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      const GLuint stipple = ctx->PolygonStipple[span->y % 32];
699ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      GLuint i, m = highBit >> (GLuint) (span->x % 32);
700ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      for (i = 0; i < span->end; i++) {
701ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if ((m & stipple) == 0) {
702ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            mask[i] = 0;
703ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
704ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         m = m >> 1;
705ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if (m == 0) {
706ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            m = highBit;
707ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
70810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
70910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
7102ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
71110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
71210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
713e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
71479c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
715733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
716733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
717733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
718733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
71910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
72010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
721f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE GLuint
722cdb27e8242215271364602995d85607cfc06d441Brian Paulclip_span( GLcontext *ctx, SWspan *span )
72310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
724733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
725733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
726733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
727733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
728733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
729733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
730733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
73177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *x = span->array->x;
73277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *y = span->array->y;
733733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
73477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLubyte *mask = span->array->mask;
735733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
736b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
737b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
738b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
739b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
740b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
741b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
742b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
743b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
744b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
745b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
746b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
747b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
748b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
74910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
750733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
75110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
752733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
753733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
754733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
755733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
756733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
757733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
758733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
759733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
760733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
761733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
762733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
76310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
764733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
765733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
766733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
767733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
7686ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul         _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte));
76910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
770733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
771733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to right */
772733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x + n > xmax) {
773733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x < xmax);
774733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = xmax - x;
77510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
77610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
777733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
778733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
77910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
78010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
78110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
78279c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
783e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Apply all the per-fragment opertions to a span of color index fragments
784e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * and write them to the enabled color drawbuffers.
785e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * The 'span' parameter can be considered to be const.  Note that
7867956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
7877956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
78810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
78910f30eb43835c57c00783390a02d72daf4f78e26Brian Paulvoid
790cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_index_span( GLcontext *ctx, SWspan *span)
79110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
792e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
793e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
794e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
795ff73c783cc47361ff0dd819c82d067b4b85870ddBrian   struct gl_framebuffer *fb = ctx->DrawBuffer;
79610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
797733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
798b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
799b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul	  span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
800733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX);
8019e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /*
8027956292a765910077f50352d7cd0174e1e66d26cBrian Paul   ASSERT((span->interpMask & span->arrayMask) == 0);
8039e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   */
8047956292a765910077f50352d7cd0174e1e66d26cBrian Paul
805733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
806733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
807733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
808733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
809733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
810a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
811733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
81210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
81310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
814733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   /* Clipping */
815b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
816733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
81786ca15ece74ccb5a8f4d566a4b2c8024b178d73bBrian Paul         return;
818e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
819e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
820e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
821e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   /* Depth bounds test */
822ff73c783cc47361ff0dd819c82d067b4b85870ddBrian   if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
823e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      if (!_swrast_depth_bounds_test(ctx, span)) {
824e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul         return;
825e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul      }
826e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   }
827e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul
828b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
829a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
830b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
831a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
832b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
83377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
834ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            assert(span->array->x[i] >= fb->_Xmin);
835ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            assert(span->array->x[i] < fb->_Xmax);
836ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            assert(span->array->y[i] >= fb->_Ymin);
837ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            assert(span->array->y[i] < fb->_Ymax);
838b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
839b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
840b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
841b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
842b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
843e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* Polygon Stippling */
844b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
84510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      stipple_polygon_span(ctx, span);
846e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
847e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
848e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   /* Stencil and Z testing */
8497956292a765910077f50352d7cd0174e1e66d26cBrian Paul   if (ctx->Depth.Test || ctx->Stencil.Enabled) {
8509e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_Z))
85145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
85210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8537956292a765910077f50352d7cd0174e1e66d26cBrian Paul      if (ctx->Stencil.Enabled) {
85445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
8557956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
8567956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
8577956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
8582a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
8597956292a765910077f50352d7cd0174e1e66d26cBrian Paul      else {
8607956292a765910077f50352d7cd0174e1e66d26cBrian Paul         ASSERT(ctx->Depth.Test);
86145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
862e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            span->interpMask = origInterpMask;
8637956292a765910077f50352d7cd0174e1e66d26cBrian Paul            span->arrayMask = origArrayMask;
8647956292a765910077f50352d7cd0174e1e66d26cBrian Paul            return;
8657956292a765910077f50352d7cd0174e1e66d26cBrian Paul         }
8662a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
86710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
86810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
869b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
87023ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
871939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
87223ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
873b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
874b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
87523ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
876b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
877b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
878b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
8797956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* we have to wait until after occlusion to do this test */
880c5a5d12743b4921ab9c01ee69fa6a06b6b4d716aBrian   if (ctx->Color.IndexMask == 0) {
88110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      /* write no pixels */
8822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      span->arrayMask = origArrayMask;
88310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      return;
88410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
88510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8867956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Interpolate the color indexes if needed */
887dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled ||
888e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexLogicOpEnabled ||
889e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       ctx->Color.IndexMask != 0xffffffff ||
890e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul       (span->arrayMask & SPAN_COVERAGE)) {
8919e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_INDEX) /*span->interpMask & SPAN_INDEX*/) {
892e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         interpolate_indexes(ctx, span);
893e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
8947956292a765910077f50352d7cd0174e1e66d26cBrian Paul   }
89510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
8967956292a765910077f50352d7cd0174e1e66d26cBrian Paul   /* Fog */
897dcf4c17fb1624af47181c63af4c3ad29f919c17aBrian Paul   if (swrast->_FogEnabled) {
89845bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_ci_span(ctx, span);
899e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
900e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
9012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   /* Antialias coverage application */
9022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
903e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      const GLfloat *coverage = span->array->coverage;
90477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLuint *index = span->array->index;
905e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      GLuint i;
90610f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      for (i = 0; i < span->end; i++) {
90777df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         ASSERT(coverage[i] < 16);
90877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]);
9095071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul      }
9102a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
9115071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paul
912ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
913ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
914ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
915ba001224a18fa12792696ef393e708e90092127eBrian Paul   {
916ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      const GLuint numBuffers = fb->_NumColorDrawBuffers;
917ba001224a18fa12792696ef393e708e90092127eBrian Paul      GLuint buf;
918e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
919ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      for (buf = 0; buf < numBuffers; buf++) {
920ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
921ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         GLuint indexSave[MAX_WIDTH];
922e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
923ba001224a18fa12792696ef393e708e90092127eBrian Paul         ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
9242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
925ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         if (numBuffers > 1) {
926ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            /* save indexes for second, third renderbuffer writes */
927ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            _mesa_memcpy(indexSave, span->array->index,
928ff73c783cc47361ff0dd819c82d067b4b85870ddBrian                         span->end * sizeof(indexSave[0]));
929ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         }
930ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
931e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexLogicOpEnabled) {
932f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_logicop_ci_span(ctx, rb, span);
933e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
934e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
935e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         if (ctx->Color.IndexMask != 0xffffffff) {
936f515c78a2320369ead087c4e0efd583f17b4b78bBrian Paul            _swrast_mask_ci_span(ctx, rb, span);
937e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
9382a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
9399e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         if (!(span->arrayMask & SPAN_INDEX) && span->indexStep == 0) {
940ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* all fragments have same color index */
941ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8;
942ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16;
943ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLuint index32;
944ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *value;
945e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
946ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
947ba001224a18fa12792696ef393e708e90092127eBrian Paul               index8 = FixedToInt(span->index);
948ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index8;
949ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
950ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
951ba001224a18fa12792696ef393e708e90092127eBrian Paul               index16 = FixedToInt(span->index);
952ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index16;
953ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
954ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
955ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
956ba001224a18fa12792696ef393e708e90092127eBrian Paul               index32 = FixedToInt(span->index);
957ba001224a18fa12792696ef393e708e90092127eBrian Paul               value = &index32;
958ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
959e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
960ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
961ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoValues(ctx, rb, span->end, span->array->x,
962ba001224a18fa12792696ef393e708e90092127eBrian Paul                                 span->array->y, value, span->array->mask);
963e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
964ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
965ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutMonoRow(ctx, rb, span->end, span->x, span->y,
966ba001224a18fa12792696ef393e708e90092127eBrian Paul                              value, span->array->mask);
967e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            }
968733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
969733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         else {
970ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* each fragment is a different color */
971ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLubyte index8[MAX_WIDTH];
972ba001224a18fa12792696ef393e708e90092127eBrian Paul            GLushort index16[MAX_WIDTH];
973ba001224a18fa12792696ef393e708e90092127eBrian Paul            void *values;
974ba001224a18fa12792696ef393e708e90092127eBrian Paul
975ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (rb->DataType == GL_UNSIGNED_BYTE) {
976ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
977ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
978ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index8[k] = (GLubyte) span->array->index[k];
979ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
980ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index8;
981ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
982ba001224a18fa12792696ef393e708e90092127eBrian Paul            else if (rb->DataType == GL_UNSIGNED_SHORT) {
983ba001224a18fa12792696ef393e708e90092127eBrian Paul               GLuint k;
984ba001224a18fa12792696ef393e708e90092127eBrian Paul               for (k = 0; k < span->end; k++) {
985ba001224a18fa12792696ef393e708e90092127eBrian Paul                  index16[k] = (GLushort) span->array->index[k];
986ba001224a18fa12792696ef393e708e90092127eBrian Paul               }
987ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = index16;
988ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
989ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
990ba001224a18fa12792696ef393e708e90092127eBrian Paul               ASSERT(rb->DataType == GL_UNSIGNED_INT);
991ba001224a18fa12792696ef393e708e90092127eBrian Paul               values = span->array->index;
992ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
993e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
994ba001224a18fa12792696ef393e708e90092127eBrian Paul            if (span->arrayMask & SPAN_XY) {
995ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutValues(ctx, rb, span->end,
996ba001224a18fa12792696ef393e708e90092127eBrian Paul                             span->array->x, span->array->y,
997ba001224a18fa12792696ef393e708e90092127eBrian Paul                             values, span->array->mask);
998ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
999ba001224a18fa12792696ef393e708e90092127eBrian Paul            else {
1000ba001224a18fa12792696ef393e708e90092127eBrian Paul               rb->PutRow(ctx, rb, span->end, span->x, span->y,
1001e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                          values, span->array->mask);
1002ba001224a18fa12792696ef393e708e90092127eBrian Paul            }
1003e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         }
1004ba001224a18fa12792696ef393e708e90092127eBrian Paul
1005ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         if (buf + 1 < numBuffers) {
1006ba001224a18fa12792696ef393e708e90092127eBrian Paul            /* restore original span values */
1007ba001224a18fa12792696ef393e708e90092127eBrian Paul            _mesa_memcpy(span->array->index, indexSave,
1008ba001224a18fa12792696ef393e708e90092127eBrian Paul                         span->end * sizeof(indexSave[0]));
1009733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         }
1010ba001224a18fa12792696ef393e708e90092127eBrian Paul      } /* for buf */
1011e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
10122a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
10137956292a765910077f50352d7cd0174e1e66d26cBrian Paul   span->interpMask = origInterpMask;
10142a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask = origArrayMask;
1015e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1016e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1017e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
101879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
10199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Add specular colors to primary colors.
10209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Only called during fixed-function operation.
10219e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Result is float color array (FRAG_ATTRIB_COL0).
1022e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
1023f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1024cdb27e8242215271364602995d85607cfc06d441Brian Pauladd_specular(GLcontext *ctx, SWspan *span)
1025e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
10269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
10279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const GLubyte *mask = span->array->mask;
10289e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
10299e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
10309e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLuint i;
10319e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
10329e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(!ctx->FragmentProgram._Current);
10339e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(span->arrayMask & SPAN_RGBA);
10349e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
10359d216be8cfe57f88cd2d890c2334df8ff5c30436Brian Paul   (void) swrast; /* silence warning */
10369e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
10379e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if (span->array->ChanType == GL_FLOAT) {
10389e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
10399e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
1040d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
10419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
10429e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   else {
10439e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* need float colors */
10449e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
10459e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_float_colors(span);
1046d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
10479e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
10489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
10499e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
10509e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* XXX could avoid this and interpolate COL1 in the loop below */
10519e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
10529e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
10539e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
10549e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
10559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
10569e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
10579e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   for (i = 0; i < span->end; i++) {
10589e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (mask[i]) {
10599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][0] += col1[i][0];
10609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][1] += col1[i][1];
10619e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][2] += col1[i][2];
1062d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
1063e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
10649e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
10659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->array->ChanType = GL_FLOAT;
1066e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1067e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1068e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
106979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1070b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul * Apply antialiasing coverage value to alpha values.
1071b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul */
1072f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
1073b88af5b4681d2085cd784b930dc259b66a55347eBrian Paulapply_aa_coverage(SWspan *span)
1074b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul{
1075b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   const GLfloat *coverage = span->array->coverage;
1076b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   GLuint i;
1077b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
10789e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLubyte (*rgba)[4] = span->array->rgba8;
1079b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1080e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1081e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
1082b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] >= 0.0);
1083b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] <= 1.0);
1084b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1085b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1086b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
10879e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLushort (*rgba)[4] = span->array->rgba16;
1088b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1089e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
1090e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
1091b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1092b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1093b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else {
1094f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
1095b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
1096b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
10979e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* clamp later */
1098b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
1099b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
1100b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul}
1101b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
1102b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
1103b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul/**
110431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul * Clamp span's float colors to [0,1]
110531293910b4e982f2ef54d79aff78f2f854121da1Brian Paul */
1106f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
110731293910b4e982f2ef54d79aff78f2f854121da1Brian Paulclamp_colors(SWspan *span)
110831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul{
1109f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
111031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   GLuint i;
111131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->array->ChanType == GL_FLOAT);
111231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   for (i = 0; i < span->end; i++) {
111331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
111431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
111531293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
111631293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
111731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   }
111831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul}
111931293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
112031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
112131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul/**
1122d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul * Convert the span's color arrays to the given type.
1123ff73c783cc47361ff0dd819c82d067b4b85870ddBrian * The only way 'output' can be greater than zero is when we have a fragment
11241c09bcfdda4083636a3ac27d804a34ef87875ce7Brian * program that writes to gl_FragData[1] or higher.
11251c09bcfdda4083636a3ac27d804a34ef87875ce7Brian * \param output  which fragment program color output is being processed
1126d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
1127f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
11281c09bcfdda4083636a3ac27d804a34ef87875ce7Brianconvert_color_type(SWspan *span, GLenum newType, GLuint output)
1129d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul{
1130f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   GLvoid *src, *dst;
11311c09bcfdda4083636a3ac27d804a34ef87875ce7Brian
11321c09bcfdda4083636a3ac27d804a34ef87875ce7Brian   if (output > 0 || span->array->ChanType == GL_FLOAT) {
11331c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
11341c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      span->array->ChanType = GL_FLOAT;
1135f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1136f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
11379e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      src = span->array->rgba8;
1138f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1139f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
11401c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT);
11419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      src = span->array->rgba16;
1142f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
11431c09bcfdda4083636a3ac27d804a34ef87875ce7Brian
1144f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (newType == GL_UNSIGNED_BYTE) {
11459e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      dst = span->array->rgba8;
1146f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
11471c09bcfdda4083636a3ac27d804a34ef87875ce7Brian   else if (newType == GL_UNSIGNED_SHORT) {
11489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      dst = span->array->rgba16;
1149f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1150f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
1151f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      dst = span->array->attribs[FRAG_ATTRIB_COL0];
1152f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
1153d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1154f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   _mesa_convert_colors(span->array->ChanType, src,
1155f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        newType, dst,
1156f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        span->end, span->array->mask);
1157d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1158d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   span->array->ChanType = newType;
115993becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   span->array->rgba = dst;
1160d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul}
1161d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1162d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1163d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
1164d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
116561c89be3135cedc795e48d36283769298e250837Brian Paul * Apply fragment shader, fragment program or normal texturing to span.
116661c89be3135cedc795e48d36283769298e250837Brian Paul */
1167f614a6190562e550257afca0d04e3846648942e8Brian Paulstatic INLINE void
116861c89be3135cedc795e48d36283769298e250837Brian Paulshade_texture_span(GLcontext *ctx, SWspan *span)
116961c89be3135cedc795e48d36283769298e250837Brian Paul{
1170c000843a14e73d593d87ff6674d0295d2cb64a12Brian   GLbitfield inputsRead;
1171c000843a14e73d593d87ff6674d0295d2cb64a12Brian
1172c000843a14e73d593d87ff6674d0295d2cb64a12Brian   /* Determine which fragment attributes are actually needed */
1173c000843a14e73d593d87ff6674d0295d2cb64a12Brian   if (ctx->FragmentProgram._Current) {
1174c000843a14e73d593d87ff6674d0295d2cb64a12Brian      inputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
1175c000843a14e73d593d87ff6674d0295d2cb64a12Brian   }
1176c000843a14e73d593d87ff6674d0295d2cb64a12Brian   else {
1177c000843a14e73d593d87ff6674d0295d2cb64a12Brian      /* XXX we could be a bit smarter about this */
1178c000843a14e73d593d87ff6674d0295d2cb64a12Brian      inputsRead = ~0;
1179c000843a14e73d593d87ff6674d0295d2cb64a12Brian   }
1180c000843a14e73d593d87ff6674d0295d2cb64a12Brian
118112ef1fbefcee964b715783d3ade6b69b2c699ed8Brian   if (ctx->FragmentProgram._Current ||
118261c89be3135cedc795e48d36283769298e250837Brian Paul       ctx->ATIFragmentShader._Enabled) {
11839e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* programmable shading */
1184171dcdfa27dda30916a7f9bfed89577feee5d350Brian      if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
1185171dcdfa27dda30916a7f9bfed89577feee5d350Brian         convert_color_type(span, GL_FLOAT, 0);
1186b9080dd5493eb23af6c5c494550c7b1cb481ca7bBrian      }
1187bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao      if (span->primitive != GL_POINT ||
1188bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao	  (span->interpMask & SPAN_RGBA) ||
1189bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao	  ctx->Point.PointSprite) {
1190bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao         /* for single-pixel points, we populated the arrays already */
11911d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian         interpolate_active_attribs(ctx, span, ~0);
11921d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian      }
11939e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->array->ChanType = GL_FLOAT;
119461c89be3135cedc795e48d36283769298e250837Brian Paul
11959e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_Z))
119661c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_span_interpolate_z (ctx, span);
119761c89be3135cedc795e48d36283769298e250837Brian Paul
119860d136f63c5a5a18b12952ec8e8532cbce086a4dBrian#if 0
1199c000843a14e73d593d87ff6674d0295d2cb64a12Brian      if (inputsRead & FRAG_BIT_WPOS)
120060d136f63c5a5a18b12952ec8e8532cbce086a4dBrian#else
120160d136f63c5a5a18b12952ec8e8532cbce086a4dBrian      /* XXX always interpolate wpos so that DDX/DDY work */
120260d136f63c5a5a18b12952ec8e8532cbce086a4dBrian#endif
1203f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         interpolate_wpos(ctx, span);
1204f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
120512ef1fbefcee964b715783d3ade6b69b2c699ed8Brian      /* Run fragment program/shader now */
120612ef1fbefcee964b715783d3ade6b69b2c699ed8Brian      if (ctx->FragmentProgram._Current) {
120761c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_program(ctx, span);
120861c89be3135cedc795e48d36283769298e250837Brian Paul      }
120961c89be3135cedc795e48d36283769298e250837Brian Paul      else {
121061c89be3135cedc795e48d36283769298e250837Brian Paul         ASSERT(ctx->ATIFragmentShader._Enabled);
121161c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_shader(ctx, span);
121261c89be3135cedc795e48d36283769298e250837Brian Paul      }
121361c89be3135cedc795e48d36283769298e250837Brian Paul   }
12149e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   else if (ctx->Texture._EnabledUnits) {
121561c89be3135cedc795e48d36283769298e250837Brian Paul      /* conventional texturing */
12169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
12179e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#if CHAN_BITS == 32
12189e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
12199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_int_colors(ctx, span);
12209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
12219e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#else
12229e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_RGBA))
12239e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_int_colors(ctx, span);
12249e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
12259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0)
12269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_texcoords(ctx, span);
12279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
122861c89be3135cedc795e48d36283769298e250837Brian Paul      _swrast_texture_span(ctx, span);
122961c89be3135cedc795e48d36283769298e250837Brian Paul   }
123061c89be3135cedc795e48d36283769298e250837Brian Paul}
123161c89be3135cedc795e48d36283769298e250837Brian Paul
123261c89be3135cedc795e48d36283769298e250837Brian Paul
123361c89be3135cedc795e48d36283769298e250837Brian Paul
123461c89be3135cedc795e48d36283769298e250837Brian Paul/**
1235a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Apply all the per-fragment operations to a span.
1236a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * This now includes texturing (_swrast_write_texture_span() is history).
1237f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
12387956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
12397956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
124078940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
124178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
1242cdb27e8242215271364602995d85607cfc06d441Brian Paul_swrast_write_rgba_span( GLcontext *ctx, SWspan *span)
124378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
124461c89be3135cedc795e48d36283769298e250837Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
124578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
1246e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
1247e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
12489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const GLbitfield origArrayAttribs = span->arrayAttribs;
124993becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   const GLenum origChanType = span->array->ChanType;
125093becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   void * const origRgba = span->array->rgba;
125112ef1fbefcee964b715783d3ade6b69b2c699ed8Brian   const GLboolean shader = (ctx->FragmentProgram._Current
125212ef1fbefcee964b715783d3ade6b69b2c699ed8Brian                             || ctx->ATIFragmentShader._Enabled);
125361c89be3135cedc795e48d36283769298e250837Brian Paul   const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits;
12541c09bcfdda4083636a3ac27d804a34ef87875ce7Brian   struct gl_framebuffer *fb = ctx->DrawBuffer;
125561c89be3135cedc795e48d36283769298e250837Brian Paul
1256bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /*
1257bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1258bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul          span->interpMask, span->arrayMask);
1259bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   */
1260f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
126131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->primitive == GL_POINT ||
126231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_LINE ||
126331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul	  span->primitive == GL_POLYGON ||
126431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_BITMAP);
1265733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(span->end <= MAX_WIDTH);
1266ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1267bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /* Fragment write masks */
1268733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1269733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1270733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1271733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1272733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
1273a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul      _mesa_memset(span->array->mask, 1, span->end);
1274733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
127578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
127678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1277a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Clip to window/scissor box */
1278b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) {
1279733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (!clip_span(ctx, span)) {
1280733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul	 return;
128178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
128278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
128378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1284b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1285a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
1286b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
1287a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
1288b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
128977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
12901c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->x[i] >= fb->_Xmin);
12911c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->x[i] < fb->_Xmax);
12921c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->y[i] >= fb->_Ymin);
12931c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->y[i] < fb->_Ymax);
1294b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1295b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1296b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1297b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1298b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
129978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1300b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1301733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
130278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
130378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
13049e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* This is the normal place to compute the fragment color/Z
13059e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian    * from texturing or shading.
1306a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
13079e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if (shaderOrTexture && !swrast->_DeferredTexture) {
130861c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
130961c89be3135cedc795e48d36283769298e250837Brian Paul   }
1310c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul
131161c89be3135cedc795e48d36283769298e250837Brian Paul   /* Do the alpha test */
131261c89be3135cedc795e48d36283769298e250837Brian Paul   if (ctx->Color.AlphaEnabled) {
131361c89be3135cedc795e48d36283769298e250837Brian Paul      if (!_swrast_alpha_test(ctx, span)) {
131461c89be3135cedc795e48d36283769298e250837Brian Paul         goto end;
131578940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
131678940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
131778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1318f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
1319f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (ctx->Stencil.Enabled || ctx->Depth.Test) {
13209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_Z))
132145bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
132278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
13231c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      if (ctx->Stencil.Enabled && fb->Visual.stencilBits > 0) {
1324a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Combined Z/stencil tests */
132545bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
1326c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1327f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
132871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
13291c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      else if (fb->Visual.depthBits > 0) {
1330a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Just regular depth testing */
1331f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1332f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
133345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
1334c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1335f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
133671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
133771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
133871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1339b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#if FEATURE_ARB_occlusion_query
134023ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1341939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
134223ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1343b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1344b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
134523ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1346b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1347b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul#endif
1348b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
1349a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1350f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1351f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1352f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   if (colorMask == 0x0) {
1353c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul      goto end;
135471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
135571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
135632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* If we were able to defer fragment color computation to now, there's
135732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * a good chance that many fragments will have already been killed by
135832340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * Z/stencil testing.
1359a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
13609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if (shaderOrTexture && swrast->_DeferredTexture) {
136161c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
136261c89be3135cedc795e48d36283769298e250837Brian Paul   }
1363d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
13649e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#if CHAN_BITS == 32
13659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
136651b728cf9aff383142a2a1e220a7d8963d1ca189Brian      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
13679e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
13689e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#else
136961c89be3135cedc795e48d36283769298e250837Brian Paul   if ((span->arrayMask & SPAN_RGBA) == 0) {
13709e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      interpolate_int_colors(ctx, span);
137171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
13729e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
137371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1374f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
13752ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
137661c89be3135cedc795e48d36283769298e250837Brian Paul   if (!shader) {
1377dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      /* Add base and specular colors */
1378dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul      if (ctx->Fog.ColorSumEnabled ||
1379dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul          (ctx->Light.Enabled &&
1380dfe508ca7af1a6d1099cd65e257512ed1e17d893Brian Paul           ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
13819e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         add_specular(ctx, span);
138271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
138371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
138471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
13856e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
138609da0b8e6621a831e3eeb9381430f2bed18a22adBrian Paul   if (swrast->_FogEnabled) {
138745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_rgba_span(ctx, span);
138871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1389f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
139071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
13912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1392b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      apply_aa_coverage(span);
139371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
139471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1395ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
13960b26e826bda0da7aeec9a79ee07fe21d54bb1263Brian Paul   if (ctx->Color.ClampFragmentColor == GL_TRUE &&
139731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul       span->array->ChanType == GL_FLOAT) {
139831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      clamp_colors(span);
1399ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   }
1400ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul
1401ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
1402ba001224a18fa12792696ef393e708e90092127eBrian Paul    * Write to renderbuffers
1403ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
1404ff73c783cc47361ff0dd819c82d067b4b85870ddBrian   {
1405ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      const GLuint numBuffers = fb->_NumColorDrawBuffers;
1406bbb042f0b809ebb754547397b8f22a5751c275daBrian      const GLboolean multiFragOutputs = numBuffers > 1;
1407ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      GLuint buf;
1408ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1409ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      for (buf = 0; buf < numBuffers; buf++) {
1410ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
1411ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1412ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         /* color[fragOutput] will be written to buffer[buf] */
1413ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1414ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         if (rb) {
1415ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            GLchan rgbaSave[MAX_WIDTH][4];
1416ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            const GLuint fragOutput = multiFragOutputs ? buf : 0;
1417ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1418ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (rb->DataType != span->array->ChanType || fragOutput > 0) {
1419ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               convert_color_type(span, rb->DataType, fragOutput);
1420ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1421ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1422ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (!multiFragOutputs && numBuffers > 1) {
1423ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* save colors for second, third renderbuffer writes */
1424ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               _mesa_memcpy(rgbaSave, span->array->rgba,
1425ff73c783cc47361ff0dd819c82d067b4b85870ddBrian                            4 * span->end * sizeof(GLchan));
1426ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1427ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1428ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB);
1429ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1430ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (ctx->Color._LogicOpEnabled) {
1431ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               _swrast_logicop_rgba_span(ctx, rb, span);
1432ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1433ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            else if (ctx->Color.BlendEnabled) {
1434ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               _swrast_blend_span(ctx, rb, span);
1435ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1436ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1437ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (colorMask != 0xffffffff) {
1438ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               _swrast_mask_rgba_span(ctx, rb, span);
1439ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1440ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1441ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (span->arrayMask & SPAN_XY) {
1442ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* array of pixel coords */
1443ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               ASSERT(rb->PutValues);
1444ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               rb->PutValues(ctx, rb, span->end,
1445ff73c783cc47361ff0dd819c82d067b4b85870ddBrian                             span->array->x, span->array->y,
1446ff73c783cc47361ff0dd819c82d067b4b85870ddBrian                             span->array->rgba, span->array->mask);
1447ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1448ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            else {
1449ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* horizontal run of pixels */
1450ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               ASSERT(rb->PutRow);
1451ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               rb->PutRow(ctx, rb, span->end, span->x, span->y,
1452ff73c783cc47361ff0dd819c82d067b4b85870ddBrian                          span->array->rgba,
1453ff73c783cc47361ff0dd819c82d067b4b85870ddBrian                          span->writeAll ? NULL: span->array->mask);
1454ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1455ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1456ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (!multiFragOutputs && numBuffers > 1) {
1457ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* restore original span values */
1458ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               _mesa_memcpy(span->array->rgba, rgbaSave,
1459ff73c783cc47361ff0dd819c82d067b4b85870ddBrian                            4 * span->end * sizeof(GLchan));
1460ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1461ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1462ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         } /* if rb */
1463ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      } /* for buf */
1464ff73c783cc47361ff0dd819c82d067b4b85870ddBrian   }
146571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1466c3caaa3dd45809e672177ab322445fe51d03af25Brian Paulend:
146761c89be3135cedc795e48d36283769298e250837Brian Paul   /* restore these values before returning */
1468e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   span->interpMask = origInterpMask;
1469f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
14709e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->arrayAttribs = origArrayAttribs;
147193becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   span->array->ChanType = origChanType;
147293becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   span->array->rgba = origRgba;
147310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
147410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1475e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
147679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1477ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian * Read RGBA pixels from a renderbuffer.  Clipping will be done to prevent
1478e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1479ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian * \param dstType  datatype for returned colors
148076e778dce59aa6f290db50242df945943fc47b05Brian Paul * \param rgba  the returned colors
1481e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
14825071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1483e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb,
148476e778dce59aa6f290db50242df945943fc47b05Brian Paul                        GLuint n, GLint x, GLint y, GLenum dstType,
148576e778dce59aa6f290db50242df945943fc47b05Brian Paul                        GLvoid *rgba)
1486e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1487e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1488e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1489a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1490a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1491e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1492e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* XXX maybe leave rgba values undefined? */
14936ec6b845fdf3c44436028ad6fff9471d18928719Brian Paul      _mesa_bzero(rgba, 4 * n * sizeof(GLchan));
1494e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1495e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1496e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1497e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
14987e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1499e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1500e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1501e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1502e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1503e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1504e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1505a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1506a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1507e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1508e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1509a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1510e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1511e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1512a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1513e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1514e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1515e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1516e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1517e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1518e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1519e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1520e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1521e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1522e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1523e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1524bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb);
1525bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->GetRow);
1526bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA);
152776e778dce59aa6f290db50242df945943fc47b05Brian Paul
152876e778dce59aa6f290db50242df945943fc47b05Brian Paul      if (rb->DataType == dstType) {
152976e778dce59aa6f290db50242df945943fc47b05Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y,
153076e778dce59aa6f290db50242df945943fc47b05Brian Paul                    (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType));
153176e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
153276e778dce59aa6f290db50242df945943fc47b05Brian Paul      else {
153376e778dce59aa6f290db50242df945943fc47b05Brian Paul         GLuint temp[MAX_WIDTH * 4];
153476e778dce59aa6f290db50242df945943fc47b05Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, temp);
153576e778dce59aa6f290db50242df945943fc47b05Brian Paul         _mesa_convert_colors(rb->DataType, temp,
153676e778dce59aa6f290db50242df945943fc47b05Brian Paul                   dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType),
153776e778dce59aa6f290db50242df945943fc47b05Brian Paul                   length, NULL);
153876e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
1539e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1540e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1541e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1542e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
154379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1544ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian * Read CI pixels from a renderbuffer.  Clipping will be done to prevent
1545e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * reading ouside the buffer's boundaries.
1546e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
15475071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1548e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb,
1549e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul                         GLuint n, GLint x, GLint y, GLuint index[] )
1550e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
1551e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1552e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1553a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1554a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1555e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1556e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      _mesa_bzero(index, n * sizeof(GLuint));
1557e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1558e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1559e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
1560e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
15617e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1562e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1563e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1564e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1565e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1566e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1567e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1568a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1569a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1570e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1571e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1572a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1573e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1574e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1575a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1576e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1577e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1578e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1579e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1580e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1581e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1582e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1583e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1584e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1585e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1586e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1587e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->GetRow);
1588e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      ASSERT(rb->_BaseFormat == GL_COLOR_INDEX);
1589e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul
1590e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      if (rb->DataType == GL_UNSIGNED_BYTE) {
1591e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLubyte index8[MAX_WIDTH];
1592e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1593e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index8);
1594e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1595e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index8[i];
1596e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1597e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_SHORT) {
1598e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLushort index16[MAX_WIDTH];
1599e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         GLint i;
1600e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index16);
1601e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         for (i = 0; i < length; i++)
1602e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul            index[skip + i] = index16[i];
1603e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1604e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      else if (rb->DataType == GL_UNSIGNED_INT) {
1605e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul         rb->GetRow(ctx, rb, length, x + skip, y, index + skip);
1606e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      }
1607e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1608e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
160967074332728acba86da7630353673b458713bb8aBrian Paul
161067074332728acba86da7630353673b458713bb8aBrian Paul
161167074332728acba86da7630353673b458713bb8aBrian Paul/**
161267074332728acba86da7630353673b458713bb8aBrian Paul * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid
161367074332728acba86da7630353673b458713bb8aBrian Paul * reading values outside the buffer bounds.
161467074332728acba86da7630353673b458713bb8aBrian Paul * We can use this for reading any format/type of renderbuffer.
1615ba001224a18fa12792696ef393e708e90092127eBrian Paul * \param valueSize is the size in bytes of each value (pixel) put into the
161667074332728acba86da7630353673b458713bb8aBrian Paul *                  values array.
161767074332728acba86da7630353673b458713bb8aBrian Paul */
161867074332728acba86da7630353673b458713bb8aBrian Paulvoid
161967074332728acba86da7630353673b458713bb8aBrian Paul_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb,
162067074332728acba86da7630353673b458713bb8aBrian Paul                   GLuint count, const GLint x[], const GLint y[],
162167074332728acba86da7630353673b458713bb8aBrian Paul                   void *values, GLuint valueSize)
162267074332728acba86da7630353673b458713bb8aBrian Paul{
162367074332728acba86da7630353673b458713bb8aBrian Paul   GLuint i, inCount = 0, inStart = 0;
162467074332728acba86da7630353673b458713bb8aBrian Paul
162567074332728acba86da7630353673b458713bb8aBrian Paul   for (i = 0; i < count; i++) {
1626ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      if (x[i] >= 0 && y[i] >= 0 &&
1627ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian	  x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
162867074332728acba86da7630353673b458713bb8aBrian Paul         /* inside */
162967074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount == 0)
163067074332728acba86da7630353673b458713bb8aBrian Paul            inStart = i;
163167074332728acba86da7630353673b458713bb8aBrian Paul         inCount++;
163267074332728acba86da7630353673b458713bb8aBrian Paul      }
163367074332728acba86da7630353673b458713bb8aBrian Paul      else {
163467074332728acba86da7630353673b458713bb8aBrian Paul         if (inCount > 0) {
163567074332728acba86da7630353673b458713bb8aBrian Paul            /* read [inStart, inStart + inCount) */
163667074332728acba86da7630353673b458713bb8aBrian Paul            rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
163767074332728acba86da7630353673b458713bb8aBrian Paul                          (GLubyte *) values + inStart * valueSize);
163867074332728acba86da7630353673b458713bb8aBrian Paul            inCount = 0;
163967074332728acba86da7630353673b458713bb8aBrian Paul         }
164067074332728acba86da7630353673b458713bb8aBrian Paul      }
164167074332728acba86da7630353673b458713bb8aBrian Paul   }
164267074332728acba86da7630353673b458713bb8aBrian Paul   if (inCount > 0) {
164367074332728acba86da7630353673b458713bb8aBrian Paul      /* read last values */
164467074332728acba86da7630353673b458713bb8aBrian Paul      rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart,
164567074332728acba86da7630353673b458713bb8aBrian Paul                    (GLubyte *) values + inStart * valueSize);
164667074332728acba86da7630353673b458713bb8aBrian Paul   }
164767074332728acba86da7630353673b458713bb8aBrian Paul}
16483fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
16493fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
16503fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul/**
16513fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul * Wrapper for gl_renderbuffer::PutRow() which does clipping.
1652a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
16533fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul */
16543fd819aef8139761ce86cb8d763de83a11c81b33Brian Paulvoid
16553fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
16563fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                GLuint count, GLint x, GLint y,
16573fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul                const GLvoid *values, GLuint valueSize)
16583fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul{
16593fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   GLint skip = 0;
16603fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
1661ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (y < 0 || y >= (GLint) rb->Height)
16623fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* above or below */
16633fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
1664ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
16653fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      return; /* entirely left or right */
16663fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
1667ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if ((GLint) (x + count) > (GLint) rb->Width) {
16683fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* right clip */
16693fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      GLint clip = x + count - rb->Width;
16703fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= clip;
16713fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
16723fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
16733fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   if (x < 0) {
16743fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      /* left clip */
16753fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      skip = -x;
16763fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      x = 0;
16773fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul      count -= skip;
16783fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   }
16793fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
16803fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul   rb->PutRow(ctx, rb, count, x, y,
16813fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul              (const GLubyte *) values + skip * valueSize, NULL);
16823fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul}
1683f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1684f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1685f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul/**
1686f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul * Wrapper for gl_renderbuffer::GetRow() which does clipping.
1687a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \param valueSize  size of each value (pixel) in bytes
1688f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul */
1689f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paulvoid
1690f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
1691f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLuint count, GLint x, GLint y,
1692f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul                GLvoid *values, GLuint valueSize)
1693f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul{
1694f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   GLint skip = 0;
1695f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1696ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (y < 0 || y >= (GLint) rb->Height)
1697f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* above or below */
1698f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1699ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1700f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* entirely left or right */
1701f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1702f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + count > rb->Width) {
1703f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* right clip */
1704f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      GLint clip = x + count - rb->Width;
1705f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= clip;
1706f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1707f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1708f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x < 0) {
1709f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* left clip */
1710f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      skip = -x;
1711f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      x = 0;
1712f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= skip;
1713f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1714f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1715f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
1716f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul}
1717a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1718a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1719a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul/**
1720a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Get RGBA pixels from the given renderbuffer.  Put the pixel colors into
1721a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * the span's specular color arrays.  The specular color arrays should no
1722a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * longer be needed by time this function is called.
1723a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Used by blending, logicop and masking functions.
1724a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \return pointer to the colors we read.
1725a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul */
1726a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paulvoid *
1727a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
1728cdb27e8242215271364602995d85607cfc06d441Brian Paul                      SWspan *span)
1729a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul{
173076e778dce59aa6f290db50242df945943fc47b05Brian Paul   const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType);
1731a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   void *rbPixels;
1732a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1733a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /*
1734a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    * Point rbPixels to a temporary space (use specular color arrays).
1735a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul    */
17369e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   rbPixels = span->array->attribs[FRAG_ATTRIB_COL1];
1737a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1738a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /* Get destination values from renderbuffer */
1739a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->arrayMask & SPAN_XY) {
1740a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
1741a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                         rbPixels, pixelSize);
1742a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1743a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1744a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul      _swrast_get_row(ctx, rb, span->end, span->x, span->y,
1745a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul                      rbPixels, pixelSize);
1746a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1747a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1748a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   return rbPixels;
1749a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul}
1750