1e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library
36a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul * Version:  7.5
422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
56a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
66a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
722144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
8e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * copy of this software and associated documentation files (the "Software"),
10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to deal in the Software without restriction, including without limitation
11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
13e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Software is furnished to do so, subject to the following conditions:
1422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
15e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice shall be included
16e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in all copies or substantial portions of the Software.
1722144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
18e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
26e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
2779c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
28bcb148de9201c7f90a68c7c46434e7ebf7204000Brian Paul * \file swrast/s_span.c
2979c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \brief Span processing functions used by all rasterization functions.
3079c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * This is where all the per-fragment tests are performed
3179c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul * \author Brian Paul
32e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
34bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/glheader.h"
35bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/colormac.h"
360ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul#include "main/format_pack.h"
370ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul#include "main/format_unpack.h"
38bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/macros.h"
39bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/imports.h"
40bbd287103dad776d8a45c87c4e51fbc26d9b80d5Brian Paul#include "main/image.h"
41cbdc1d53542b3ecca0085399c4bb3b3371f94809Pauli Nieminen#include "main/samplerobj.h"
42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
437f752fed993e5e9423abac200dd59141edbada56Dave Airlie#include "s_atifragshader.h"
44bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol#include "s_alpha.h"
45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_blend.h"
46cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "s_context.h"
47e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_depth.h"
48e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_fog.h"
49e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_logic.h"
50e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_masking.h"
51c968d3d410a1897ecbb41d3557adaef69a4c627aBrian#include "s_fragprog.h"
52e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_span.h"
53e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "s_stencil.h"
5455187ea63e980b32c7a701855571332f4357d634Brian Paul#include "s_texcombine.h"
55e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
569be3be3c6654da18466626c2d45ff4d06b5fb953Ian Romanick#include <stdbool.h>
572a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
5879c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Set default fragment attributes for the span using the
609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * current raster values.  Used prior to glDraw/CopyPixels
619e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * and glBitmap.
622a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul */
632a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulvoid
64f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_span_default_attribs(struct gl_context *ctx, SWspan *span)
652a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
6660121c41ce9ee50ff8d8476d4eb04867adf9b8c5Karl Schultz   GLchan r, g, b, a;
679e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* Z*/
689e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   {
699e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF;
709e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (ctx->DrawBuffer->Visual.depthBits <= 16)
719e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F);
726254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao      else {
736254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao         GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax;
746254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao         tmpf = MIN2(tmpf, depthMax);
756254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao         span->z = (GLint)tmpf;
766254be9b7144821e044d3fbade514fa0358db693Xiang, Haihao      }
779e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->zStep = 0;
789e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->interpMask |= SPAN_Z;
79884af408644e3fa9aa0ffc544f84ec4a7f3a93b9Brian   }
802a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
819e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* W (for perspective correction) */
829e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->attrStart[FRAG_ATTRIB_WPOS][3] = 1.0;
839e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0;
849e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
852a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
869e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* primary color, or color index */
872b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]);
882b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]);
892b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]);
902b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]);
912a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#if CHAN_TYPE == GL_FLOAT
922b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->red = r;
932b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->green = g;
942b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->blue = b;
952b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->alpha = a;
962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#else
972b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->red   = IntToFixed(r);
982b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->green = IntToFixed(g);
992b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->blue  = IntToFixed(b);
1002b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->alpha = IntToFixed(a);
1012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul#endif
1022b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->redStep = 0;
1032b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->greenStep = 0;
1042b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->blueStep = 0;
1052b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->alphaStep = 0;
1062b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   span->interpMask |= SPAN_RGBA;
1079e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1082b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   COPY_4V(span->attrStart[FRAG_ATTRIB_COL0], ctx->Current.RasterColor);
1092b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
1102b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL0], 0.0, 0.0, 0.0, 0.0);
1112a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
1129e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* Secondary color */
1132b7911d37dc1518b9047b02acdc6f8476abad70fIan Romanick   if (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled)
114f793e90e823a58c0408771c38f3a6209f78a3617Brian   {
1159e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      COPY_4V(span->attrStart[FRAG_ATTRIB_COL1], ctx->Current.RasterSecondaryColor);
1169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      ASSIGN_4V(span->attrStepX[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
1179e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      ASSIGN_4V(span->attrStepY[FRAG_ATTRIB_COL1], 0.0, 0.0, 0.0, 0.0);
1189e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
1199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* fog */
1219e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   {
1229e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1239e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLfloat fogVal; /* a coord or a blend factor */
1249e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (swrast->_PreferPixelFog) {
1259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* fog blend factors will be computed from fog coordinates per pixel */
1269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         fogVal = ctx->Current.RasterDistance;
1279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
1289e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      else {
1299e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* fog blend factor should be computed from fogcoord now */
1309e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
1319e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
1329e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->attrStart[FRAG_ATTRIB_FOGC][0] = fogVal;
1339e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0;
1349e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0;
1359e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
1369e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1379e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* texcoords */
1389e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   {
1399e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLuint i;
1409e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
1419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLuint attr = FRAG_ATTRIB_TEX0 + i;
1429e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat *tc = ctx->Current.RasterTexCoords[i];
1431c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace         if (_swrast_use_fragment_program(ctx) ||
1441c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace             ctx->ATIFragmentShader._Enabled) {
1459e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            COPY_4V(span->attrStart[attr], tc);
1469e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
1479e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         else if (tc[3] > 0.0F) {
1489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            /* use (s/q, t/q, r/q, 1) */
1499e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][0] = tc[0] / tc[3];
1509e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][1] = tc[1] / tc[3];
1519e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][2] = tc[2] / tc[3];
1529e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->attrStart[attr][3] = 1.0;
1539e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
1549e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         else {
1559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F);
1569e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
1579e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F);
1589e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F);
1599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
16038a1c2b4959d35236933c14d3944cce94283ca30Brian   }
16138a1c2b4959d35236933c14d3944cce94283ca30Brian}
16238a1c2b4959d35236933c14d3944cce94283ca30Brian
16338a1c2b4959d35236933c14d3944cce94283ca30Brian
1644753d60dd070bb08d0116076bcc08025c86ce857Brian Paul/**
1659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Interpolate the active attributes (and'd with attrMask) to
1669e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * fill in span->array->attribs[].
1679e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Perspective correction will be done.  The point/line/triangle function
1689e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]!
1694753d60dd070bb08d0116076bcc08025c86ce857Brian Paul */
1709520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
1718dffb6bdab25dcacf165851e9d1fdb3beb73099aBrian Paulinterpolate_active_attribs(struct gl_context *ctx, SWspan *span,
1728dffb6bdab25dcacf165851e9d1fdb3beb73099aBrian Paul                           GLbitfield64 attrMask)
1734753d60dd070bb08d0116076bcc08025c86ce857Brian Paul{
1749e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1759e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
1769dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian   /*
1779dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian    * Don't overwrite existing array values, such as colors that may have
1789dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian    * been produced by glDraw/CopyPixels.
179171dcdfa27dda30916a7f9bfed89577feee5d350Brian    */
1809dca42a4a10acbf1980c0f2eafb3e28e11ca1bf3Brian   attrMask &= ~span->arrayAttribs;
181171dcdfa27dda30916a7f9bfed89577feee5d350Brian
1829e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ATTRIB_LOOP_BEGIN
183706400f0a7a59bba89eca8e97a1ada45445ee6dfBrian Paul      if (attrMask & BITFIELD64_BIT(attr)) {
1849e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
1859e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3];
1869e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv0dx = span->attrStepX[attr][0];
1879e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv1dx = span->attrStepX[attr][1];
1889e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv2dx = span->attrStepX[attr][2];
1899e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         const GLfloat dv3dx = span->attrStepX[attr][3];
1906a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat v0 = span->attrStart[attr][0] + span->leftClip * dv0dx;
1916a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx;
1926a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx;
1936a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx;
1949e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLuint k;
1959e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         for (k = 0; k < span->end; k++) {
1969e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            const GLfloat invW = 1.0f / w;
1979e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][0] = v0 * invW;
1989e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][1] = v1 * invW;
1999e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][2] = v2 * invW;
2009e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span->array->attribs[attr][k][3] = v3 * invW;
2019e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v0 += dv0dx;
2029e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v1 += dv1dx;
2039e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v2 += dv2dx;
2049e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            v3 += dv3dx;
2059e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            w += dwdx;
2069e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
207706400f0a7a59bba89eca8e97a1ada45445ee6dfBrian Paul         ASSERT((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0);
208706400f0a7a59bba89eca8e97a1ada45445ee6dfBrian Paul         span->arrayAttribs |= BITFIELD64_BIT(attr);
209e63cb85cbc13c083f5d9f4640bb81ba9417a4f28Brian Paul      }
2109e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ATTRIB_LOOP_END
2114753d60dd070bb08d0116076bcc08025c86ce857Brian Paul}
2124753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
2134753d60dd070bb08d0116076bcc08025c86ce857Brian Paul
214d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
2159e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16)
2169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * color array.
217d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
2189520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
219f9995b30756140724f41daf963fa06167912be7fKristian Høgsberginterpolate_int_colors(struct gl_context *ctx, SWspan *span)
2202a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
221afd1d857752b5c30a3082068f8bb9002e0c69699Fabio Pedretti#if CHAN_BITS != 32
2222a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
2232a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
2242a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
2259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(!(span->arrayMask & SPAN_RGBA));
2269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
2272a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
228e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   switch (span->array->ChanType) {
2291e3223c02a2f6155beb5784cadbea1f46703829aBrian Paul#if CHAN_BITS != 32
230e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_BYTE:
231e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
2329e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLubyte (*rgba)[4] = span->array->rgba8;
233e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
234d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLubyte color[4];
235e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
236e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
237e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
238e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
239d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
240d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4UBV(rgba[i], color);
241d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
242d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
243e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
244e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed r = span->red;
245e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed g = span->green;
246e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed b = span->blue;
247e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLfixed a = span->alpha;
248e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dr = span->redStep;
249e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint dg = span->greenStep;
250e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint db = span->blueStep;
251e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLint da = span->alphaStep;
252d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
253e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][RCOMP] = FixedToChan(r);
254e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][GCOMP] = FixedToChan(g);
255e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][BCOMP] = FixedToChan(b);
256e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               rgba[i][ACOMP] = FixedToChan(a);
257e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               r += dr;
258e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               g += dg;
259e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               b += db;
260e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul               a += da;
261d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
262d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
263e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
264e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
265e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_UNSIGNED_SHORT:
266e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      {
2679e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLushort (*rgba)[4] = span->array->rgba16;
268e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         if (span->interpMask & SPAN_FLAT) {
269e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            GLushort color[4];
270e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[RCOMP] = FixedToInt(span->red);
271e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[GCOMP] = FixedToInt(span->green);
272e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[BCOMP] = FixedToInt(span->blue);
273e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            color[ACOMP] = FixedToInt(span->alpha);
274d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
275d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               COPY_4V(rgba[i], color);
276d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
277d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
278e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         else {
2799e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            GLushort (*rgba)[4] = span->array->rgba16;
280d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLfixed r, g, b, a;
281d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            GLint dr, dg, db, da;
282e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            r = span->red;
283e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            g = span->green;
284e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            b = span->blue;
285e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            a = span->alpha;
286e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dr = span->redStep;
287e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            dg = span->greenStep;
288e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            db = span->blueStep;
289e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul            da = span->alphaStep;
290d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            for (i = 0; i < n; i++) {
291d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][RCOMP] = FixedToChan(r);
292d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][GCOMP] = FixedToChan(g);
293d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][BCOMP] = FixedToChan(b);
294d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               rgba[i][ACOMP] = FixedToChan(a);
295d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               r += dr;
296d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               g += dg;
297d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               b += db;
298d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul               a += da;
299d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul            }
300d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul         }
301e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      }
302e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
303e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul#endif
304e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   case GL_FLOAT:
3059e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
306e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul      break;
307e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul   default:
308147148fd50ec2db089a0fbcca9740146aa096be8Brian Paul      _mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors",
309147148fd50ec2db089a0fbcca9740146aa096be8Brian Paul                    span->array->ChanType);
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 */
3189520f483b8f1e45fa474674b415554988de5d8d3Brian 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
3769e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian/**
3779e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Fill in the span.zArray array from the span->z, zStep values.
3789e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian */
379711e27fda27e4235b20a4cf73c2767c984ab2b81Brian Paulvoid
380f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span )
3812a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
3822a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   const GLuint n = span->end;
3832a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   GLuint i;
3842a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
3859e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(!(span->arrayMask & SPAN_Z));
3862a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
38731e739a18931fa48454f172818245b0927c8910fBrian Paul   if (ctx->DrawBuffer->Visual.depthBits <= 16) {
3882a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      GLfixed zval = span->z;
3893e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
390ad8cd6111e022c90c93df106c0fde6f64d205816Brian Paul      for (i = 0; i < n; i++) {
39177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = FixedToInt(zval);
3922a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
3932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
3942a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
3952a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   else {
3962a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      /* Deep Z buffer, no fixed->int shift */
3977265556b9aa0367e9b5031e7cb15ed2a5d73866dBrian Paul      GLuint zval = span->z;
3983e37bafab0a339021354b9c78f983d05d433d735Brian Paul      GLuint *z = span->array->z;
3992a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      for (i = 0; i < n; i++) {
40077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         z[i] = zval;
4012a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul         zval += span->zStep;
4022a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul      }
4032a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   }
40432340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   span->interpMask &= ~SPAN_Z;
4052a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   span->arrayMask |= SPAN_Z;
4062a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul}
4072a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4082a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
4099e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian/**
4109e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Compute mipmap LOD from partial derivatives.
41131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul * This the ideal solution, as given in the OpenGL spec.
412c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
413c334ce273e946733928339b1c7f9a02ccdef1b4bBrian PaulGLfloat
414c334ce273e946733928339b1c7f9a02ccdef1b4bBrian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
415c334ce273e946733928339b1c7f9a02ccdef1b4bBrian Paul                       GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
416c334ce273e946733928339b1c7f9a02ccdef1b4bBrian Paul                       GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
417c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
41831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ);
41931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ);
42031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ);
42131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ);
422f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx);
423f9b1e5241facc8cf255c258082d5cb5b04783e93Brian Paul   GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy);
42431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat rho = MAX2(x, y);
42531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat lambda = LOG2(rho);
42631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
427c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
428c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
42931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul
4309e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian/**
4319e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Compute mipmap LOD from partial derivatives.
4329e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * This is a faster approximation than above function.
433c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
434c334ce273e946733928339b1c7f9a02ccdef1b4bBrian Paul#if 0
435350353adcd75f94fda63c787c86961716114e0bfBrian PaulGLfloat
43645bc887da226403f2c41077e40ca38b6f60f1359Brian Paul_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
437350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH,
438350353adcd75f94fda63c787c86961716114e0bfBrian Paul                     GLfloat s, GLfloat t, GLfloat q, GLfloat invQ)
439c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul{
44031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ;
44131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ;
44231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ;
44331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ;
44431f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   GLfloat maxU, maxV, rho, lambda;
44531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdx2 = FABSF(dsdx2);
44631f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dsdy2 = FABSF(dsdy2);
44731f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdx2 = FABSF(dtdx2);
44831f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   dtdy2 = FABSF(dtdy2);
44931f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxU = MAX2(dsdx2, dsdy2) * texW;
45031f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   maxV = MAX2(dtdx2, dtdy2) * texH;
45131f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   rho = MAX2(maxU, maxV);
45231f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   lambda = LOG2(rho);
45331f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul   return lambda;
454c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul}
455c334ce273e946733928339b1c7f9a02ccdef1b4bBrian Paul#endif
456c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul
457d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul
458d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul/**
4599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Fill in the span.array->attrib[FRAG_ATTRIB_TEXn] arrays from the
4609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * using the attrStart/Step values.
4619e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian *
4629e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * This function only used during fixed-function fragment processing.
4639e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian *
464d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * Note: in the places where we divide by Q (or mult by invQ) we're
465d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * really doing two things: perspective correction and texcoord
466d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * projection.  Remember, for texcoord (s,t,r,q) we need to index
467d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul * texels with (s/q, t/q, r/q).
468c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul */
4692a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paulstatic void
470f9995b30756140724f41daf963fa06167912be7fKristian Høgsberginterpolate_texcoords(struct gl_context *ctx, SWspan *span)
4712a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul{
472e4f976b8b9d74a74b5816146cb11880c3a493929Brian   const GLuint maxUnit
473e4f976b8b9d74a74b5816146cb11880c3a493929Brian      = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1;
474e4f976b8b9d74a74b5816146cb11880c3a493929Brian   GLuint u;
475e4f976b8b9d74a74b5816146cb11880c3a493929Brian
476e4f976b8b9d74a74b5816146cb11880c3a493929Brian   /* XXX CoordUnits vs. ImageUnits */
477e4f976b8b9d74a74b5816146cb11880c3a493929Brian   for (u = 0; u < maxUnit; u++) {
478e4f976b8b9d74a74b5816146cb11880c3a493929Brian      if (ctx->Texture._EnabledCoordUnits & (1 << u)) {
479e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLuint attr = FRAG_ATTRIB_TEX0 + u;
480c000843a14e73d593d87ff6674d0295d2cb64a12Brian         const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
481e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat texW, texH;
482e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLboolean needLambda;
483e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat (*texcoord)[4] = span->array->attribs[attr];
484e4f976b8b9d74a74b5816146cb11880c3a493929Brian         GLfloat *lambda = span->array->lambda[u];
485e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dsdx = span->attrStepX[attr][0];
486e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dsdy = span->attrStepY[attr][0];
487e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dtdx = span->attrStepX[attr][1];
488e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dtdy = span->attrStepY[attr][1];
489e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat drdx = span->attrStepX[attr][2];
490e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dqdx = span->attrStepX[attr][3];
491e4f976b8b9d74a74b5816146cb11880c3a493929Brian         const GLfloat dqdy = span->attrStepY[attr][3];
4926a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx;
4936a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx;
4946a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx;
4956a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx;
496e4f976b8b9d74a74b5816146cb11880c3a493929Brian
497e4f976b8b9d74a74b5816146cb11880c3a493929Brian         if (obj) {
498e4f976b8b9d74a74b5816146cb11880c3a493929Brian            const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
499980f6f1b37ca88529b3e000235156eab93254facBrian Paul            const struct swrast_texture_image *swImg =
500980f6f1b37ca88529b3e000235156eab93254facBrian Paul               swrast_texture_image_const(img);
501cbdc1d53542b3ecca0085399c4bb3b3371f94809Pauli Nieminen            const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, u);
502980f6f1b37ca88529b3e000235156eab93254facBrian Paul
503cbdc1d53542b3ecca0085399c4bb3b3371f94809Pauli Nieminen            needLambda = (samp->MinFilter != samp->MagFilter)
5041c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace               || _swrast_use_fragment_program(ctx);
5058a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            /* LOD is calculated directly in the ansiotropic filter, we can
5068a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger             * skip the normal lambda function as the result is ignored.
5078a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger             */
508cbdc1d53542b3ecca0085399c4bb3b3371f94809Pauli Nieminen            if (samp->MaxAnisotropy > 1.0 &&
509cbdc1d53542b3ecca0085399c4bb3b3371f94809Pauli Nieminen                samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
5108a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger               needLambda = GL_FALSE;
5118a98aabe0bcea42cfdc982001ae4876e3d9b1214Andreas Faenger            }
512980f6f1b37ca88529b3e000235156eab93254facBrian Paul            texW = swImg->WidthScale;
513980f6f1b37ca88529b3e000235156eab93254facBrian Paul            texH = swImg->HeightScale;
514e4f976b8b9d74a74b5816146cb11880c3a493929Brian         }
515e4f976b8b9d74a74b5816146cb11880c3a493929Brian         else {
516e4f976b8b9d74a74b5816146cb11880c3a493929Brian            /* using a fragment program */
517e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texW = 1.0;
518e4f976b8b9d74a74b5816146cb11880c3a493929Brian            texH = 1.0;
519e4f976b8b9d74a74b5816146cb11880c3a493929Brian            needLambda = GL_FALSE;
520e4f976b8b9d74a74b5816146cb11880c3a493929Brian         }
521e4f976b8b9d74a74b5816146cb11880c3a493929Brian
522e4f976b8b9d74a74b5816146cb11880c3a493929Brian         if (needLambda) {
523e4f976b8b9d74a74b5816146cb11880c3a493929Brian            GLuint i;
5241c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace            if (_swrast_use_fragment_program(ctx)
525e4f976b8b9d74a74b5816146cb11880c3a493929Brian                || ctx->ATIFragmentShader._Enabled) {
526e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* do perspective correction but don't divide s, t, r by q */
527e4f976b8b9d74a74b5816146cb11880c3a493929Brian               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
5286a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
529e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
530e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invW = 1.0F / w;
531e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invW;
532e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invW;
533e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invW;
534e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q * invW;
535e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
536e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     dqdx, dqdy, texW, texH,
537e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     s, t, q, invW);
538e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
539e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
540e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
541e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
542e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  w += dwdx;
5432a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
5442a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul            }
54531f12f504e61cb2ad65b8890a68eb7154edcb64bBrian Paul            else {
546e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
5472a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
548e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
549e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
550e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
551e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
552e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
553e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     dqdx, dqdy, texW, texH,
554e4f976b8b9d74a74b5816146cb11880c3a493929Brian                                                     s, t, q, invQ);
555e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
556e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
557e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
558e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
5592a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul               }
560d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul            }
561e4f976b8b9d74a74b5816146cb11880c3a493929Brian            span->arrayMask |= SPAN_LAMBDA;
562d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         }
563d8b82147c3cb17a06bf41e97141b8427b4580459Brian Paul         else {
564e4f976b8b9d74a74b5816146cb11880c3a493929Brian            GLuint i;
5651c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace            if (_swrast_use_fragment_program(ctx) ||
566e4f976b8b9d74a74b5816146cb11880c3a493929Brian                ctx->ATIFragmentShader._Enabled) {
567e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* do perspective correction but don't divide s, t, r by q */
568e4f976b8b9d74a74b5816146cb11880c3a493929Brian               const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3];
5696a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul               GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dwdx;
570e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
571e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invW = 1.0F / w;
572e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invW;
573e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invW;
574e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invW;
575e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q * invW;
576e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
577e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
578e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
579e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
580e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
581e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  w += dwdx;
582e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
583c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
584e4f976b8b9d74a74b5816146cb11880c3a493929Brian            else if (dqdx == 0.0F) {
585e4f976b8b9d74a74b5816146cb11880c3a493929Brian               /* Ortho projection or polygon's parallel to window X axis */
586c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
587e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
588e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
589e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
590e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
591e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
592e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
593e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
594e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
595e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
596e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
597c14a5a6c6285b29860a722359faa11a16da4eac9Brian Paul            }
598e4f976b8b9d74a74b5816146cb11880c3a493929Brian            else {
599e4f976b8b9d74a74b5816146cb11880c3a493929Brian               for (i = 0; i < span->end; i++) {
600e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
601e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][0] = s * invQ;
602e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][1] = t * invQ;
603e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][2] = r * invQ;
604e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  texcoord[i][3] = q;
605e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  lambda[i] = 0.0;
606e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  s += dsdx;
607e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  t += dtdx;
608e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  r += drdx;
609e4f976b8b9d74a74b5816146cb11880c3a493929Brian                  q += dqdx;
610e4f976b8b9d74a74b5816146cb11880c3a493929Brian               }
611e4f976b8b9d74a74b5816146cb11880c3a493929Brian            }
612e4f976b8b9d74a74b5816146cb11880c3a493929Brian         } /* lambda */
613e4f976b8b9d74a74b5816146cb11880c3a493929Brian      } /* if */
614e4f976b8b9d74a74b5816146cb11880c3a493929Brian   } /* for */
61510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
616e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
617e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
618bb38cadb1c5f2dc13096a091bdaf61dc3e3cfa4dMichal Krol/**
619f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array.
620f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian */
6219520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
622f9995b30756140724f41daf963fa06167912be7fKristian Høgsberginterpolate_wpos(struct gl_context *ctx, SWspan *span)
623f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian{
624f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS];
625f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLuint i;
626880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul   const GLfloat zScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
6278e6207396c6314d07614c80670f4e3196e3a8551Brian   GLfloat w, dw;
6288e6207396c6314d07614c80670f4e3196e3a8551Brian
629f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   if (span->arrayMask & SPAN_XY) {
630f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      for (i = 0; i < span->end; i++) {
631f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][0] = (GLfloat) span->array->x[i];
632f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][1] = (GLfloat) span->array->y[i];
633f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      }
634f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
635f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   else {
636f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      for (i = 0; i < span->end; i++) {
637f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][0] = (GLfloat) span->x + i;
638f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         wpos[i][1] = (GLfloat) span->y;
639f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      }
640f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
6418e6207396c6314d07614c80670f4e3196e3a8551Brian
6428e6207396c6314d07614c80670f4e3196e3a8551Brian   dw = span->attrStepX[FRAG_ATTRIB_WPOS][3];
6436a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul   w = span->attrStart[FRAG_ATTRIB_WPOS][3] + span->leftClip * dw;
644f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   for (i = 0; i < span->end; i++) {
6458e6207396c6314d07614c80670f4e3196e3a8551Brian      wpos[i][2] = (GLfloat) span->array->z[i] * zScale;
6468e6207396c6314d07614c80670f4e3196e3a8551Brian      wpos[i][3] = w;
6478e6207396c6314d07614c80670f4e3196e3a8551Brian      w += dw;
648f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   }
649f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian}
650f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
651f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
652f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian/**
653e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Apply the current polygon stipple pattern to a span of pixels.
654e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
6559520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
656f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergstipple_polygon_span(struct gl_context *ctx, SWspan *span)
65710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
65877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   GLubyte *mask = span->array->mask;
659733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
660733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   ASSERT(ctx->Polygon.StippleFlag);
66110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
662ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (span->arrayMask & SPAN_XY) {
663ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      /* arrays of x/y pixel coords */
664ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      GLuint i;
665ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      for (i = 0; i < span->end; i++) {
666ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLint col = span->array->x[i] % 32;
667ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLint row = span->array->y[i] % 32;
668ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         const GLuint stipple = ctx->PolygonStipple[row];
669ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if (((1 << col) & stipple) == 0) {
670ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            mask[i] = 0;
671ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
67210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
673ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   }
674ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   else {
675ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      /* horizontal span of pixels */
676ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      const GLuint highBit = 1 << 31;
677ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      const GLuint stipple = ctx->PolygonStipple[span->y % 32];
678ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      GLuint i, m = highBit >> (GLuint) (span->x % 32);
679ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      for (i = 0; i < span->end; i++) {
680ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if ((m & stipple) == 0) {
681ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            mask[i] = 0;
682ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
683ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         m = m >> 1;
684ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         if (m == 0) {
685ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian            m = highBit;
686ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian         }
68710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
68810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
6892ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul   span->writeAll = GL_FALSE;
69010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
69110f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
692e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
69379c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
694733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Clip a pixel span to the current buffer/window boundaries:
695733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax.  This will accomplish
696733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * window clipping and scissoring.
697733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * Return:   GL_TRUE   some pixels still visible
69810f30eb43835c57c00783390a02d72daf4f78e26Brian Paul *           GL_FALSE  nothing visible
69910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul */
7009520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline GLuint
701f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergclip_span( struct gl_context *ctx, SWspan *span )
70210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul{
703733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmin = ctx->DrawBuffer->_Xmin;
704733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint xmax = ctx->DrawBuffer->_Xmax;
705733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymin = ctx->DrawBuffer->_Ymin;
706733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   const GLint ymax = ctx->DrawBuffer->_Ymax;
707733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
7086a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul   span->leftClip = 0;
7096a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul
710733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_XY) {
711733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* arrays of x/y pixel coords */
71277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *x = span->array->x;
71377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      const GLint *y = span->array->y;
714733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint n = span->end;
71577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul      GLubyte *mask = span->array->mask;
716733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      GLint i;
717718cbe4ba95439c074144ea2ce06ebf0915a660cBrian Paul      GLuint passed = 0;
718b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      if (span->arrayMask & SPAN_MASK) {
719b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
720b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
721b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] &= (x[i] >= xmin) & (x[i] < xmax)
722b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                     & (y[i] >= ymin) & (y[i] < ymax);
723718cbe4ba95439c074144ea2ce06ebf0915a660cBrian Paul            passed += mask[i];
724b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
725b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
726b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      else {
727b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         /* note: using & intead of && to reduce branches */
728b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         for (i = 0; i < n; i++) {
729b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul            mask[i] = (x[i] >= xmin) & (x[i] < xmax)
730b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul                    & (y[i] >= ymin) & (y[i] < ymax);
731718cbe4ba95439c074144ea2ce06ebf0915a660cBrian Paul            passed += mask[i];
732b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
73310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
734718cbe4ba95439c074144ea2ce06ebf0915a660cBrian Paul      return passed > 0;
73510f30eb43835c57c00783390a02d72daf4f78e26Brian Paul   }
736733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
737733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* horizontal span of pixels */
738733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint x = span->x;
739733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      const GLint y = span->y;
7406a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      GLint n = span->end;
741733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
742733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Trivial rejection tests */
743733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) {
744733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->end = 0;
745733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         return GL_FALSE;  /* all pixels clipped */
746733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      }
74710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
7486a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      /* Clip to right */
7496a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      if (x + n > xmax) {
7506a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         ASSERT(x < xmax);
7516a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         n = span->end = xmax - x;
7526a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      }
7536a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul
754733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* Clip to the left */
755733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      if (x < xmin) {
7566a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         const GLint leftClip = xmin - x;
7576a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         GLuint i;
7586a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul
7596a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         ASSERT(leftClip > 0);
760733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         ASSERT(x + n > xmin);
7616a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul
7626a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         /* Clip 'leftClip' pixels from the left side.
7636a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul          * The span->leftClip field will be applied when we interpolate
7646a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul          * fragment attributes.
7656a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul          * For arrays of values, shift them left.
7666a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul          */
7676a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
768a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul            if (span->interpMask & (1 << i)) {
769a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul               GLuint j;
770a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul               for (j = 0; j < 4; j++) {
771a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul                  span->attrStart[i][j] += leftClip * span->attrStepX[i][j];
772a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul               }
773a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul            }
774a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         }
775a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul
776a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->red += leftClip * span->redStep;
777a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->green += leftClip * span->greenStep;
778a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->blue += leftClip * span->blueStep;
779a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->alpha += leftClip * span->alphaStep;
780a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->index += leftClip * span->indexStep;
781a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->z += leftClip * span->zStep;
782a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->intTex[0] += leftClip * span->intTexStep[0];
783a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         span->intTex[1] += leftClip * span->intTexStep[1];
784a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul
785a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul#define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \
786a44d715d2b19dc2f8f48b01144cc38e4e2c5015aBrian Paul         memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0]))
787a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul
788a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
7896a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul            if (span->arrayAttribs & (1 << i)) {
7906a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul               /* shift array elements left by 'leftClip' */
791a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul               SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip);
7926a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul            }
7936a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         }
7946a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul
795a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->mask, leftClip, n - leftClip);
796a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->rgba8, leftClip, n - leftClip);
797a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->rgba16, leftClip, n - leftClip);
798a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->x, leftClip, n - leftClip);
799a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->y, leftClip, n - leftClip);
800a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->z, leftClip, n - leftClip);
801a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->index, leftClip, n - leftClip);
802a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
803a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul            SHIFT_ARRAY(span->array->lambda[i], leftClip, n - leftClip);
804a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         }
805a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul         SHIFT_ARRAY(span->array->coverage, leftClip, n - leftClip);
806a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul
807a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul#undef SHIFT_ARRAY
808a61dce363929bbc3520f91cefa3ba15bbe31c5bdBrian Paul
8096a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         span->leftClip = leftClip;
8106a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         span->x = xmin;
8116a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul         span->end -= leftClip;
812733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul         span->writeAll = GL_FALSE;
81310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul      }
814733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul
8156a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      ASSERT(span->x >= xmin);
8166a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      ASSERT(span->x + span->end <= xmax);
8176a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      ASSERT(span->y >= ymin);
8186a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      ASSERT(span->y < ymax);
81910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
820733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      return GL_TRUE;  /* some pixels visible */
821733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
82210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
82310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
82410f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
82579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
8269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Add specular colors to primary colors.
8279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Only called during fixed-function operation.
8289e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian * Result is float color array (FRAG_ATTRIB_COL0).
829e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
8309520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
831f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergadd_specular(struct gl_context *ctx, SWspan *span)
832e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
8339e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
8349e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const GLubyte *mask = span->array->mask;
8359e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat (*col0)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
8369e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat (*col1)[4] = span->array->attribs[FRAG_ATTRIB_COL1];
8379e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLuint i;
8389e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
8391c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace   ASSERT(!_swrast_use_fragment_program(ctx));
8409e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(span->arrayMask & SPAN_RGBA);
8419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(swrast->_ActiveAttribMask & FRAG_BIT_COL1);
8429d216be8cfe57f88cd2d890c2334df8ff5c30436Brian Paul   (void) swrast; /* silence warning */
8439e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
8449e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if (span->array->ChanType == GL_FLOAT) {
8459e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
8469e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
847d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
8489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
8499e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   else {
8509e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* need float colors */
8519e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
8529e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_float_colors(span);
853d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
8549e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
8559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
8569e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if ((span->arrayAttribs & FRAG_BIT_COL1) == 0) {
8579e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* XXX could avoid this and interpolate COL1 in the loop below */
8589e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      interpolate_active_attribs(ctx, span, FRAG_BIT_COL1);
8599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
8609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
8619e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(span->arrayAttribs & FRAG_BIT_COL0);
8629e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   ASSERT(span->arrayAttribs & FRAG_BIT_COL1);
8639e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
8649e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   for (i = 0; i < span->end; i++) {
8659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (mask[i]) {
8669e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][0] += col1[i][0];
8679e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][1] += col1[i][1];
8689e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         col0[i][2] += col1[i][2];
869d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul      }
870e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
8719e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
8729e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->array->ChanType = GL_FLOAT;
873e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
874e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
875e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
87679c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
877b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul * Apply antialiasing coverage value to alpha values.
878b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul */
8799520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
880b88af5b4681d2085cd784b930dc259b66a55347eBrian Paulapply_aa_coverage(SWspan *span)
881b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul{
882b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   const GLfloat *coverage = span->array->coverage;
883b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   GLuint i;
884b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   if (span->array->ChanType == GL_UNSIGNED_BYTE) {
8859e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLubyte (*rgba)[4] = span->array->rgba8;
886b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
887e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
888e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0);
889b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] >= 0.0);
890b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         ASSERT(coverage[i] <= 1.0);
891b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
892b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
893b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
8949e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLushort (*rgba)[4] = span->array->rgba16;
895b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
896e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         const GLfloat a = rgba[i][ACOMP] * coverage[i];
897e9d7190bb2b1bf3a057e27ecd7e79302360961a1Brian Paul         rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0);
898b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
899b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
900b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   else {
901f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
902b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      for (i = 0; i < span->end; i++) {
903b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul         rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i];
9049e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* clamp later */
905b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      }
906b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul   }
907b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul}
908b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
909b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul
910b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul/**
91131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul * Clamp span's float colors to [0,1]
91231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul */
9139520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
91431293910b4e982f2ef54d79aff78f2f854121da1Brian Paulclamp_colors(SWspan *span)
91531293910b4e982f2ef54d79aff78f2f854121da1Brian Paul{
916f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian   GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
91731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   GLuint i;
91831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->array->ChanType == GL_FLOAT);
91931293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   for (i = 0; i < span->end; i++) {
92031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F);
92131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F);
92231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F);
92331293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F);
92431293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   }
92531293910b4e982f2ef54d79aff78f2f854121da1Brian Paul}
92631293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
92731293910b4e982f2ef54d79aff78f2f854121da1Brian Paul
92831293910b4e982f2ef54d79aff78f2f854121da1Brian Paul/**
929d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul * Convert the span's color arrays to the given type.
930ff73c783cc47361ff0dd819c82d067b4b85870ddBrian * The only way 'output' can be greater than zero is when we have a fragment
9311c09bcfdda4083636a3ac27d804a34ef87875ce7Brian * program that writes to gl_FragData[1] or higher.
9321c09bcfdda4083636a3ac27d804a34ef87875ce7Brian * \param output  which fragment program color output is being processed
933d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul */
9349520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
9351c09bcfdda4083636a3ac27d804a34ef87875ce7Brianconvert_color_type(SWspan *span, GLenum newType, GLuint output)
936d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul{
937f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   GLvoid *src, *dst;
9381c09bcfdda4083636a3ac27d804a34ef87875ce7Brian
9391c09bcfdda4083636a3ac27d804a34ef87875ce7Brian   if (output > 0 || span->array->ChanType == GL_FLOAT) {
9401c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      src = span->array->attribs[FRAG_ATTRIB_COL0 + output];
9411c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      span->array->ChanType = GL_FLOAT;
942f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
943f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else if (span->array->ChanType == GL_UNSIGNED_BYTE) {
9449e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      src = span->array->rgba8;
945f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
946f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
9471c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      ASSERT(span->array->ChanType == GL_UNSIGNED_SHORT);
9489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      src = span->array->rgba16;
949f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
9501c09bcfdda4083636a3ac27d804a34ef87875ce7Brian
951f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   if (newType == GL_UNSIGNED_BYTE) {
9529e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      dst = span->array->rgba8;
953f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
9541c09bcfdda4083636a3ac27d804a34ef87875ce7Brian   else if (newType == GL_UNSIGNED_SHORT) {
9559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      dst = span->array->rgba16;
956f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
957f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   else {
958f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian      dst = span->array->attribs[FRAG_ATTRIB_COL0];
959f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   }
960d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
961f971e24cf0341dd2779196a0836327b74fc82336Brian Paul   _mesa_convert_colors(span->array->ChanType, src,
962f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        newType, dst,
963f971e24cf0341dd2779196a0836327b74fc82336Brian Paul                        span->end, span->array->mask);
964d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
965d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul   span->array->ChanType = newType;
96693becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   span->array->rgba = dst;
967d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul}
968d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
969d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
970d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul
971d92da49bae30be612efb6ea20bdfda232ee3d01dBrian Paul/**
97261c89be3135cedc795e48d36283769298e250837Brian Paul * Apply fragment shader, fragment program or normal texturing to span.
97361c89be3135cedc795e48d36283769298e250837Brian Paul */
9749520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
975f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergshade_texture_span(struct gl_context *ctx, SWspan *span)
97661c89be3135cedc795e48d36283769298e250837Brian Paul{
9771c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace   if (_swrast_use_fragment_program(ctx) ||
97861c89be3135cedc795e48d36283769298e250837Brian Paul       ctx->ATIFragmentShader._Enabled) {
9799e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      /* programmable shading */
980171dcdfa27dda30916a7f9bfed89577feee5d350Brian      if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) {
981171dcdfa27dda30916a7f9bfed89577feee5d350Brian         convert_color_type(span, GL_FLOAT, 0);
982b9080dd5493eb23af6c5c494550c7b1cb481ca7bBrian      }
983c8e714df013cdf360602f9cc96d26cb732b19a32M.Froehlich@science-computing.de      else {
984c8e714df013cdf360602f9cc96d26cb732b19a32M.Froehlich@science-computing.de         span->array->rgba = (void *) span->array->attribs[FRAG_ATTRIB_COL0];
985c8e714df013cdf360602f9cc96d26cb732b19a32M.Froehlich@science-computing.de      }
986c8e714df013cdf360602f9cc96d26cb732b19a32M.Froehlich@science-computing.de
987bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao      if (span->primitive != GL_POINT ||
988bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao	  (span->interpMask & SPAN_RGBA) ||
989bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao	  ctx->Point.PointSprite) {
990bff94a91c6852157a8251652cb61dc699cd8e4f1Xiang, Haihao         /* for single-pixel points, we populated the arrays already */
9911d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian         interpolate_active_attribs(ctx, span, ~0);
9921d52b6aaf41b32aaf8d1cdf5a3cd5ff4ecba28f4Brian      }
9939e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span->array->ChanType = GL_FLOAT;
99461c89be3135cedc795e48d36283769298e250837Brian Paul
9959e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_Z))
99661c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_span_interpolate_z (ctx, span);
99761c89be3135cedc795e48d36283769298e250837Brian Paul
99860d136f63c5a5a18b12952ec8e8532cbce086a4dBrian#if 0
999c000843a14e73d593d87ff6674d0295d2cb64a12Brian      if (inputsRead & FRAG_BIT_WPOS)
100060d136f63c5a5a18b12952ec8e8532cbce086a4dBrian#else
100160d136f63c5a5a18b12952ec8e8532cbce086a4dBrian      /* XXX always interpolate wpos so that DDX/DDY work */
100260d136f63c5a5a18b12952ec8e8532cbce086a4dBrian#endif
1003f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian         interpolate_wpos(ctx, span);
1004f3e507ef9f75dbfc58ccd07b5fe8cfca10d9a9e3Brian
100512ef1fbefcee964b715783d3ade6b69b2c699ed8Brian      /* Run fragment program/shader now */
10061c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace      if (_swrast_use_fragment_program(ctx)) {
100761c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_program(ctx, span);
100861c89be3135cedc795e48d36283769298e250837Brian Paul      }
100961c89be3135cedc795e48d36283769298e250837Brian Paul      else {
101061c89be3135cedc795e48d36283769298e250837Brian Paul         ASSERT(ctx->ATIFragmentShader._Enabled);
101161c89be3135cedc795e48d36283769298e250837Brian Paul         _swrast_exec_fragment_shader(ctx, span);
101261c89be3135cedc795e48d36283769298e250837Brian Paul      }
101361c89be3135cedc795e48d36283769298e250837Brian Paul   }
101407e50058a5699fc9279de6bf5d1449d52ccdc476Brian Paul   else if (ctx->Texture._EnabledCoordUnits) {
101561c89be3135cedc795e48d36283769298e250837Brian Paul      /* conventional texturing */
10169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
10179e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#if CHAN_BITS == 32
10189e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
10199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_int_colors(ctx, span);
10209e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      }
10219e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#else
10229e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_RGBA))
10239e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_int_colors(ctx, span);
10249e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
10259e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if ((span->arrayAttribs & FRAG_BITS_TEX_ANY) == 0x0)
10269e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         interpolate_texcoords(ctx, span);
10279e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
102861c89be3135cedc795e48d36283769298e250837Brian Paul      _swrast_texture_span(ctx, span);
102961c89be3135cedc795e48d36283769298e250837Brian Paul   }
103061c89be3135cedc795e48d36283769298e250837Brian Paul}
103161c89be3135cedc795e48d36283769298e250837Brian Paul
103261c89be3135cedc795e48d36283769298e250837Brian Paul
10330ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul/** Put colors at x/y locations into a renderbuffer */
10340ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paulstatic void
10350ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paulput_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
1036f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul           GLenum datatype,
10370ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul           GLuint count, const GLint x[], const GLint y[],
10380ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul           const void *values, const GLubyte *mask)
10390ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul{
104088e7f56dd7130077494ff36b9765dd48cd3d4a91Brian Paul   gl_pack_ubyte_rgba_func pack_ubyte = NULL;
104188e7f56dd7130077494ff36b9765dd48cd3d4a91Brian Paul   gl_pack_float_rgba_func pack_float = NULL;
10420ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   GLuint i;
10430ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
1044881ef2a9db22cff4c7d07b873d23b0c324da555aBrian Paul   if (datatype == GL_UNSIGNED_BYTE)
1045881ef2a9db22cff4c7d07b873d23b0c324da555aBrian Paul      pack_ubyte = _mesa_get_pack_ubyte_rgba_function(rb->Format);
1046881ef2a9db22cff4c7d07b873d23b0c324da555aBrian Paul   else
1047881ef2a9db22cff4c7d07b873d23b0c324da555aBrian Paul      pack_float = _mesa_get_pack_float_rgba_function(rb->Format);
1048881ef2a9db22cff4c7d07b873d23b0c324da555aBrian Paul
10490ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   for (i = 0; i < count; i++) {
10500ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      if (mask[i]) {
10510ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]);
10520ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
1053f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul         if (datatype == GL_UNSIGNED_BYTE) {
1054881ef2a9db22cff4c7d07b873d23b0c324da555aBrian Paul            pack_ubyte((const GLubyte *) values + 4 * i, dst);
10550ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         }
10560ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         else {
1057f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul            assert(datatype == GL_FLOAT);
1058881ef2a9db22cff4c7d07b873d23b0c324da555aBrian Paul            pack_float((const GLfloat *) values + 4 * i, dst);
10590ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         }
10600ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      }
10610ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   }
10620ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul}
10630ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
10640ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
10650ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul/** Put row of colors into renderbuffer */
10660ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paulvoid
10670ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul_swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
1068f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul                GLenum datatype,
10690ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                GLuint count, GLint x, GLint y,
10700ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                const void *values, const GLubyte *mask)
10710ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul{
10720ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   GLubyte *dst = _swrast_pixel_address(rb, x, y);
10730ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
10740ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   if (!mask) {
1075f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul      if (datatype == GL_UNSIGNED_BYTE) {
10760ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         _mesa_pack_ubyte_rgba_row(rb->Format, count,
10770ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                   (const GLubyte (*)[4]) values, dst);
10780ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      }
10790ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      else {
1080f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul         assert(datatype == GL_FLOAT);
10810ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         _mesa_pack_float_rgba_row(rb->Format, count,
10820ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                   (const GLfloat (*)[4]) values, dst);
10830ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      }
10840ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   }
10850ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   else {
10860ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      const GLuint bpp = _mesa_get_format_bytes(rb->Format);
10870ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      GLuint i, runLen, runStart;
10880ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions
10890ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul       * so look for runs where mask=1...
10900ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul       */
1091ba151a333be7a23266b23ee6f65669bb19221546Brian Paul      runLen = runStart = 0;
10920ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      for (i = 0; i < count; i++) {
10930ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         if (mask[i]) {
10940ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            if (runLen == 0)
10950ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul               runStart = i;
10960ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            runLen++;
10970ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         }
10980ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
10990ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         if (!mask[i] || i == count - 1) {
11000ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            /* might be the end of a run of pixels */
11010ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            if (runLen > 0) {
1102f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul               if (datatype == GL_UNSIGNED_BYTE) {
11030ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                  _mesa_pack_ubyte_rgba_row(rb->Format, runLen,
11040ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                     (const GLubyte (*)[4]) values + runStart,
11050ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                     dst + runStart * bpp);
11060ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul               }
11070ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul               else {
1108f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul                  assert(datatype == GL_FLOAT);
11090ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                  _mesa_pack_float_rgba_row(rb->Format, runLen,
11100ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                   (const GLfloat (*)[4]) values + runStart,
11110ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                   dst + runStart * bpp);
11120ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul               }
11130ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul               runLen = 0;
11140ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            }
11150ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         }
11160ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      }
11170ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   }
11180ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul}
11190ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
11200ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
112161c89be3135cedc795e48d36283769298e250837Brian Paul
112261c89be3135cedc795e48d36283769298e250837Brian Paul/**
1123a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * Apply all the per-fragment operations to a span.
1124a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul * This now includes texturing (_swrast_write_texture_span() is history).
1125f1e236987829393c81dc86ea19cb49eefe190317Brian Paul * This function may modify any of the array values in the span.
11267956292a765910077f50352d7cd0174e1e66d26cBrian Paul * span->interpMask and span->arrayMask may be changed but will be restored
11277956292a765910077f50352d7cd0174e1e66d26cBrian Paul * to their original values before returning.
112878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul */
112978940758e90069ceaca2b6cddb6438488fbad5ccBrian Paulvoid
1130f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_write_rgba_span( struct gl_context *ctx, SWspan *span)
113178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul{
113261c89be3135cedc795e48d36283769298e250837Brian Paul   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1133fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul   const GLuint *colorMask = (GLuint *) ctx->Color.ColorMask;
1134e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origInterpMask = span->interpMask;
1135e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paul   const GLbitfield origArrayMask = span->arrayMask;
11368dffb6bdab25dcacf165851e9d1fdb3beb73099aBrian Paul   const GLbitfield64 origArrayAttribs = span->arrayAttribs;
113793becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   const GLenum origChanType = span->array->ChanType;
113893becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   void * const origRgba = span->array->rgba;
11391c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace   const GLboolean shader = (_swrast_use_fragment_program(ctx)
114012ef1fbefcee964b715783d3ade6b69b2c699ed8Brian                             || ctx->ATIFragmentShader._Enabled);
114107e50058a5699fc9279de6bf5d1449d52ccdc476Brian Paul   const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits;
11421c09bcfdda4083636a3ac27d804a34ef87875ce7Brian   struct gl_framebuffer *fb = ctx->DrawBuffer;
114361c89be3135cedc795e48d36283769298e250837Brian Paul
1144bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /*
1145bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__,
1146bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul          span->interpMask, span->arrayMask);
1147bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   */
1148f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
114931293910b4e982f2ef54d79aff78f2f854121da1Brian Paul   ASSERT(span->primitive == GL_POINT ||
115031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_LINE ||
115131293910b4e982f2ef54d79aff78f2f854121da1Brian Paul	  span->primitive == GL_POLYGON ||
115231293910b4e982f2ef54d79aff78f2f854121da1Brian Paul          span->primitive == GL_BITMAP);
1153ceb39f4f8dc4863fde17d668c752533a2184476eBrian Paul
1154bb19e64d12eaf27e2adc3faac7e09555bb66d724Brian Paul   /* Fragment write masks */
1155733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   if (span->arrayMask & SPAN_MASK) {
1156733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      /* mask was initialized by caller, probably glBitmap */
1157733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_FALSE;
1158733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   }
1159733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul   else {
116026f8fad1456fdc2b352cea9d3b4c32cb5f6ae947Kenneth Graunke      memset(span->array->mask, 1, span->end);
1161733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      span->writeAll = GL_TRUE;
116278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
116378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1164a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Clip to window/scissor box */
1165f25e1007c2da21dc529811e9e1f4b4da6bda8be4Brian Paul   if (!clip_span(ctx, span)) {
1166f25e1007c2da21dc529811e9e1f4b4da6bda8be4Brian Paul      return;
116778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
116878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
116947d88ef204b42a9220c6be3e98c92df9c9aa0860Brian Paul   ASSERT(span->end <= SWRAST_MAX_WIDTH);
1170f25e1007c2da21dc529811e9e1f4b4da6bda8be4Brian Paul
11712c5aa02e2086f5e79630cdffec804a3e9de0d966Brian Paul   /* Depth bounds test */
11722c5aa02e2086f5e79630cdffec804a3e9de0d966Brian Paul   if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) {
11732c5aa02e2086f5e79630cdffec804a3e9de0d966Brian Paul      if (!_swrast_depth_bounds_test(ctx, span)) {
11742c5aa02e2086f5e79630cdffec804a3e9de0d966Brian Paul         return;
11752c5aa02e2086f5e79630cdffec804a3e9de0d966Brian Paul      }
11762c5aa02e2086f5e79630cdffec804a3e9de0d966Brian Paul   }
11772c5aa02e2086f5e79630cdffec804a3e9de0d966Brian Paul
1178b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#ifdef DEBUG
1179a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* Make sure all fragments are within window bounds */
1180b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   if (span->arrayMask & SPAN_XY) {
11816a3004b9ae58dafd1ce995df78b0f3183827a59dBrian Paul      /* array of pixel locations */
1182a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      GLuint i;
1183b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      for (i = 0; i < span->end; i++) {
118477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul         if (span->array->mask[i]) {
11851c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->x[i] >= fb->_Xmin);
11861c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->x[i] < fb->_Xmax);
11871c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->y[i] >= fb->_Ymin);
11881c09bcfdda4083636a3ac27d804a34ef87875ce7Brian            assert(span->array->y[i] < fb->_Ymax);
1189b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul         }
1190b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul      }
1191b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul   }
1192b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul#endif
1193b37a084357dd08573b86d6d8c5ba43d65bdc1bd7Brian Paul
119478940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   /* Polygon Stippling */
1195b7f5e92f1749ce4601a758f66ddc64959f11742bBrian Paul   if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) {
1196733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul      stipple_polygon_span(ctx, span);
119778940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
119878940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
11999e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   /* This is the normal place to compute the fragment color/Z
12009e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian    * from texturing or shading.
1201a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
12029e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if (shaderOrTexture && !swrast->_DeferredTexture) {
120361c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
120461c89be3135cedc795e48d36283769298e250837Brian Paul   }
1205c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul
120661c89be3135cedc795e48d36283769298e250837Brian Paul   /* Do the alpha test */
120761c89be3135cedc795e48d36283769298e250837Brian Paul   if (ctx->Color.AlphaEnabled) {
120861c89be3135cedc795e48d36283769298e250837Brian Paul      if (!_swrast_alpha_test(ctx, span)) {
12098962bac0a1e422afcd034f4ce00d45d8f3df46bfBrian Paul         /* all fragments failed test */
121061c89be3135cedc795e48d36283769298e250837Brian Paul         goto end;
121178940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul      }
121278940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul   }
121378940758e90069ceaca2b6cddb6438488fbad5ccBrian Paul
1214f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   /* Stencil and Z testing */
121591e61f435a71436c209934a0ece165b540aba3e0Brian Paul   if (ctx->Stencil._Enabled || ctx->Depth.Test) {
12169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      if (!(span->arrayMask & SPAN_Z))
121745bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         _swrast_span_interpolate_z(ctx, span);
121832ec3f26731ac998b6fda7ce596ec568d6f76eebEric Anholt
121932ec3f26731ac998b6fda7ce596ec568d6f76eebEric Anholt      if (ctx->Transform.DepthClamp)
122032ec3f26731ac998b6fda7ce596ec568d6f76eebEric Anholt	 _swrast_depth_clamp_span(ctx, span);
122132ec3f26731ac998b6fda7ce596ec568d6f76eebEric Anholt
122291e61f435a71436c209934a0ece165b540aba3e0Brian Paul      if (ctx->Stencil._Enabled) {
1223a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Combined Z/stencil tests */
122445bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_stencil_and_ztest_span(ctx, span)) {
12258962bac0a1e422afcd034f4ce00d45d8f3df46bfBrian Paul            /* all fragments failed test */
1226c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1227f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
122871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
12291c09bcfdda4083636a3ac27d804a34ef87875ce7Brian      else if (fb->Visual.depthBits > 0) {
1230a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul         /* Just regular depth testing */
1231f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(ctx->Depth.Test);
1232f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         ASSERT(span->arrayMask & SPAN_Z);
123345bc887da226403f2c41077e40ca38b6f60f1359Brian Paul         if (!_swrast_depth_test_span(ctx, span)) {
12348962bac0a1e422afcd034f4ce00d45d8f3df46bfBrian Paul            /* all fragments failed test */
1235c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul            goto end;
1236f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         }
123771340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
123871340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
123971340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
124023ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul   if (ctx->Query.CurrentOcclusionObject) {
1241939dd17653245621bf7488803f09418244b7b0b7Brian Paul      /* update count of 'passed' fragments */
124223ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul      struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;
1243b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      GLuint i;
1244b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul      for (i = 0; i < span->end; i++)
124523ffc3a85d6172f8a98d17d7f23610bab808d84eBrian Paul         q->Result += span->array->mask[i];
1246b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul   }
1247b17a722ca3989e8563ee04cb2939f4835f8a171eBrian Paul
1248a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul   /* We had to wait until now to check for glColorMask(0,0,0,0) because of
1249f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    * the occlusion test.
1250f1e236987829393c81dc86ea19cb49eefe190317Brian Paul    */
1251fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul   if (fb->_NumColorDrawBuffers == 1 && colorMask[0] == 0x0) {
12528962bac0a1e422afcd034f4ce00d45d8f3df46bfBrian Paul      /* no colors to write */
1253c3caaa3dd45809e672177ab322445fe51d03af25Brian Paul      goto end;
125471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
125571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
125632340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul   /* If we were able to defer fragment color computation to now, there's
125732340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * a good chance that many fragments will have already been killed by
125832340aea1308153dad5c105fc0748aea1e4c37eeBrian Paul    * Z/stencil testing.
1259a803b0c891404dcd7c376e91f6a033cd4e42abc3Brian Paul    */
12609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if (shaderOrTexture && swrast->_DeferredTexture) {
126161c89be3135cedc795e48d36283769298e250837Brian Paul      shade_texture_span(ctx, span);
126261c89be3135cedc795e48d36283769298e250837Brian Paul   }
1263d09df24082d69e534470f9a5f667b30c34ae6d74Brian Paul
12649e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#if CHAN_BITS == 32
12659e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   if ((span->arrayAttribs & FRAG_BIT_COL0) == 0) {
126651b728cf9aff383142a2a1e220a7d8963d1ca189Brian      interpolate_active_attribs(ctx, span, FRAG_BIT_COL0);
12679e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   }
12689e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#else
126961c89be3135cedc795e48d36283769298e250837Brian Paul   if ((span->arrayMask & SPAN_RGBA) == 0) {
12709e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      interpolate_int_colors(ctx, span);
127171340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
12729e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
127371340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1274f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   ASSERT(span->arrayMask & SPAN_RGBA);
12752ef866d1fc0a5cc5ef8543d65744dfd4da4dbbafBrian Paul
127676ac75af8e5481b498981c133836efa2101be2dcBrian Paul   if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) {
127776ac75af8e5481b498981c133836efa2101be2dcBrian Paul      /* Add primary and specular (diffuse + specular) colors */
12783e79d650835b3431464de876699d04702df99806Brian Paul      if (!shader) {
12793e79d650835b3431464de876699d04702df99806Brian Paul         if (ctx->Fog.ColorSumEnabled ||
12803e79d650835b3431464de876699d04702df99806Brian Paul             (ctx->Light.Enabled &&
12813e79d650835b3431464de876699d04702df99806Brian Paul              ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
12823e79d650835b3431464de876699d04702df99806Brian Paul            add_specular(ctx, span);
12833e79d650835b3431464de876699d04702df99806Brian Paul         }
128471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul      }
128571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
128671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
12876e1666437ea091ecc50ab2b56d87129318f641d2Brian Paul   /* Fog */
128809da0b8e6621a831e3eeb9381430f2bed18a22adBrian Paul   if (swrast->_FogEnabled) {
128945bc887da226403f2c41077e40ca38b6f60f1359Brian Paul      _swrast_fog_rgba_span(ctx, span);
129071340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
1291f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
129271340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   /* Antialias coverage application */
12932a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul   if (span->arrayMask & SPAN_COVERAGE) {
1294b88af5b4681d2085cd784b930dc259b66a55347eBrian Paul      apply_aa_coverage(span);
129571340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul   }
129671340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1297ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   /* Clamp color/alpha values over the range [0.0, 1.0] before storage */
12980b26e826bda0da7aeec9a79ee07fe21d54bb1263Brian Paul   if (ctx->Color.ClampFragmentColor == GL_TRUE &&
129931293910b4e982f2ef54d79aff78f2f854121da1Brian Paul       span->array->ChanType == GL_FLOAT) {
130031293910b4e982f2ef54d79aff78f2f854121da1Brian Paul      clamp_colors(span);
1301ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul   }
1302ba3da6154c324cc916845bc5de3de077d0b59ffcBrian Paul
1303ba001224a18fa12792696ef393e708e90092127eBrian Paul   /*
13049cc79fc2dcdd8e21d9616cc65a931f1f5859fc30Brian Paul    * Write to renderbuffers.
13059cc79fc2dcdd8e21d9616cc65a931f1f5859fc30Brian Paul    * Depending on glDrawBuffer() state and the which color outputs are
13069cc79fc2dcdd8e21d9616cc65a931f1f5859fc30Brian Paul    * written by the fragment shader, we may either replicate one color to
13079cc79fc2dcdd8e21d9616cc65a931f1f5859fc30Brian Paul    * all renderbuffers or write a different color to each renderbuffer.
13089cc79fc2dcdd8e21d9616cc65a931f1f5859fc30Brian Paul    * multiFragOutputs=TRUE for the later case.
1309ba001224a18fa12792696ef393e708e90092127eBrian Paul    */
1310ff73c783cc47361ff0dd819c82d067b4b85870ddBrian   {
1311ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      const GLuint numBuffers = fb->_NumColorDrawBuffers;
13129cc79fc2dcdd8e21d9616cc65a931f1f5859fc30Brian Paul      const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
13139cc79fc2dcdd8e21d9616cc65a931f1f5859fc30Brian Paul      const GLboolean multiFragOutputs =
13141c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace         _swrast_use_fragment_program(ctx)
13151c0f1dd42a50464eeb81de4aad8eecf24b3d6c89Chad Versace         && fp->Base.OutputsWritten >= (1 << FRAG_RESULT_DATA0);
1316ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      GLuint buf;
1317ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1318ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      for (buf = 0; buf < numBuffers; buf++) {
1319ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf];
1320ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1321ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         /* color[fragOutput] will be written to buffer[buf] */
1322ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1323ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         if (rb) {
1324ed65c5ccc3d15c350965f669d6891813c0ba8bccBrian Paul            /* re-use one of the attribute array buffers for rgbaSave */
1325ed65c5ccc3d15c350965f669d6891813c0ba8bccBrian Paul            GLchan (*rgbaSave)[4] = (GLchan (*)[4]) span->array->attribs[0];
1326bd1ae51b13535bc4438c663ffe91ded49db4890aBrian Paul            struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
1327bd1ae51b13535bc4438c663ffe91ded49db4890aBrian Paul            GLenum colorType = srb->ColorType;
1328ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1329bd1ae51b13535bc4438c663ffe91ded49db4890aBrian Paul            assert(colorType == GL_UNSIGNED_BYTE ||
1330bd1ae51b13535bc4438c663ffe91ded49db4890aBrian Paul                   colorType == GL_FLOAT);
1331660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick
1332bd1ae51b13535bc4438c663ffe91ded49db4890aBrian Paul            /* set span->array->rgba to colors for renderbuffer's datatype */
1333bd1ae51b13535bc4438c663ffe91ded49db4890aBrian Paul            if (span->array->ChanType != colorType) {
1334bd1ae51b13535bc4438c663ffe91ded49db4890aBrian Paul               convert_color_type(span, colorType, 0);
1335ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1336c8e714df013cdf360602f9cc96d26cb732b19a32M.Froehlich@science-computing.de            else {
1337660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick               if (span->array->ChanType == GL_UNSIGNED_BYTE) {
1338660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick                  span->array->rgba = span->array->rgba8;
1339660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick               }
1340660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick               else {
1341660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick                  span->array->rgba = (void *)
1342660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick                     span->array->attribs[FRAG_ATTRIB_COL0];
1343660ed923ded3552e023ef8c3dd9f92e6792f1bd2Ian Romanick               }
1344c8e714df013cdf360602f9cc96d26cb732b19a32M.Froehlich@science-computing.de            }
1345ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1346ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (!multiFragOutputs && numBuffers > 1) {
1347ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* save colors for second, third renderbuffer writes */
1348c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke               memcpy(rgbaSave, span->array->rgba,
1349c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke                      4 * span->end * sizeof(GLchan));
1350ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1351ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1352b7f670655dc57ea90963888f95e22773ce0ad131Brian Paul            ASSERT(rb->_BaseFormat == GL_RGBA ||
1353b7f670655dc57ea90963888f95e22773ce0ad131Brian Paul                   rb->_BaseFormat == GL_RGB ||
1354b7f670655dc57ea90963888f95e22773ce0ad131Brian Paul                   rb->_BaseFormat == GL_RED ||
1355b7f670655dc57ea90963888f95e22773ce0ad131Brian Paul                   rb->_BaseFormat == GL_RG ||
135650a3349bee04088bee3491622d6ef3c032d01eacEric Anholt		   rb->_BaseFormat == GL_ALPHA);
1357ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
13582836aab2031d5b6926923fbc70f867ec638301bdIan Romanick            if (ctx->Color.ColorLogicOpEnabled) {
1359ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               _swrast_logicop_rgba_span(ctx, rb, span);
1360ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
13613728673bd1b974e54858fbab6ff62d3607b0d3f0Brian Paul            else if ((ctx->Color.BlendEnabled >> buf) & 1) {
1362ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               _swrast_blend_span(ctx, rb, span);
1363ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1364ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1365fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul            if (colorMask[buf] != 0xffffffff) {
1366fd5511d27fc44096117c47ab503fb5b47f993061Brian Paul               _swrast_mask_rgba_span(ctx, rb, span, buf);
1367ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1368ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1369ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (span->arrayMask & SPAN_XY) {
1370ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* array of pixel coords */
1371f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul               put_values(ctx, rb,
1372f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul                          span->array->ChanType, span->end,
13730ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                          span->array->x, span->array->y,
13740ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                          span->array->rgba, span->array->mask);
1375ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1376ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            else {
1377ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* horizontal run of pixels */
1378f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul               _swrast_put_row(ctx, rb,
1379f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul                               span->array->ChanType,
1380f9874feef4d8952df5054bd8e8f4e0deda4ef44fBrian Paul                               span->end, span->x, span->y,
13810ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                               span->array->rgba,
13820ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                               span->writeAll ? NULL: span->array->mask);
1383ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1384ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1385ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            if (!multiFragOutputs && numBuffers > 1) {
1386ff73c783cc47361ff0dd819c82d067b4b85870ddBrian               /* restore original span values */
1387c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke               memcpy(span->array->rgba, rgbaSave,
1388c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke                      4 * span->end * sizeof(GLchan));
1389ff73c783cc47361ff0dd819c82d067b4b85870ddBrian            }
1390ff73c783cc47361ff0dd819c82d067b4b85870ddBrian
1391ff73c783cc47361ff0dd819c82d067b4b85870ddBrian         } /* if rb */
1392ff73c783cc47361ff0dd819c82d067b4b85870ddBrian      } /* for buf */
1393ff73c783cc47361ff0dd819c82d067b4b85870ddBrian   }
139471340e861edf35bfdeb536718cd230fc33c41ee2Brian Paul
1395c3caaa3dd45809e672177ab322445fe51d03af25Brian Paulend:
139661c89be3135cedc795e48d36283769298e250837Brian Paul   /* restore these values before returning */
1397e5b244ff7f984805c1bcc020342f1300f2639c71Brian Paul   span->interpMask = origInterpMask;
1398f1e236987829393c81dc86ea19cb49eefe190317Brian Paul   span->arrayMask = origArrayMask;
13999e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   span->arrayAttribs = origArrayAttribs;
140093becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   span->array->ChanType = origChanType;
140193becd8a18f6ccf2f86e506ee36fc0bb75787c29Brian   span->array->rgba = origRgba;
140210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul}
140310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
1404e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
140579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
1406267fb178844d3f17503dd0f921791f3ab059c4e7Brian Paul * Read float RGBA pixels from a renderbuffer.  Clipping will be done to
1407267fb178844d3f17503dd0f921791f3ab059c4e7Brian Paul * prevent reading ouside the buffer's boundaries.
140876e778dce59aa6f290db50242df945943fc47b05Brian Paul * \param rgba  the returned colors
1409e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
14105071b0812fc73bcba92e2b6fcbad2f53f063fc32Brian Paulvoid
1411f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb,
1412267fb178844d3f17503dd0f921791f3ab059c4e7Brian Paul                        GLuint n, GLint x, GLint y,
141376e778dce59aa6f290db50242df945943fc47b05Brian Paul                        GLvoid *rgba)
1414e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
14150c1862851f27c428a18ba5509636efcc2f0084f8Brian Paul   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
1416267fb178844d3f17503dd0f921791f3ab059c4e7Brian Paul   GLenum dstType = GL_FLOAT;
1417e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufWidth = (GLint) rb->Width;
1418e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul   const GLint bufHeight = (GLint) rb->Height;
1419a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul
1420a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul   if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) {
1421e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      /* completely above, below, or right */
1422e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul      /* XXX maybe leave rgba values undefined? */
14236bf1ea897fa470af58fe8916dff45e2da79634a3Brian Paul      memset(rgba, 0, 4 * n * sizeof(GLchan));
1424e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1425e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
1426e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      GLint skip, length;
14270ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      GLubyte *src;
14280ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
1429e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (x < 0) {
14307e152b83cbc3af028175a52450c60101cb16acf8Brian Paul         /* left edge clipping */
1431e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = -x;
1432e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n - skip;
1433e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1434e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely left of window */
1435e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1436e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1437a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         if (length > bufWidth) {
1438a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul            length = bufWidth;
1439e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1440e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1441a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul      else if ((GLint) (x + n) > bufWidth) {
1442e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* right edge clipping */
1443e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1444a670c1280b78e6da3b298b61f623e4c733c6be94Brian Paul         length = bufWidth - x;
1445e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         if (length < 0) {
1446e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            /* completely to right of window */
1447e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell            return;
1448e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1449e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1450e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
1451e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         /* no clipping */
1452e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         skip = 0;
1453e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         length = (GLint) n;
1454e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
1455e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1456bb8b302dbce4f830d060efecd8a9f75b10e25abbBrian Paul      ASSERT(rb);
1457641dd899bd485c194c20a871633797a47e4f912dEric Anholt      ASSERT(rb->_BaseFormat == GL_RGBA ||
1458641dd899bd485c194c20a871633797a47e4f912dEric Anholt	     rb->_BaseFormat == GL_RGB ||
1459641dd899bd485c194c20a871633797a47e4f912dEric Anholt	     rb->_BaseFormat == GL_RG ||
1460641dd899bd485c194c20a871633797a47e4f912dEric Anholt	     rb->_BaseFormat == GL_RED ||
1461a45b757f788d3a59a446fe2596065ec5f0d5eac2Eric Anholt	     rb->_BaseFormat == GL_LUMINANCE ||
1462a45b757f788d3a59a446fe2596065ec5f0d5eac2Eric Anholt	     rb->_BaseFormat == GL_INTENSITY ||
1463a45b757f788d3a59a446fe2596065ec5f0d5eac2Eric Anholt	     rb->_BaseFormat == GL_LUMINANCE_ALPHA ||
146450a3349bee04088bee3491622d6ef3c032d01eacEric Anholt	     rb->_BaseFormat == GL_ALPHA);
146576e778dce59aa6f290db50242df945943fc47b05Brian Paul
14660c1862851f27c428a18ba5509636efcc2f0084f8Brian Paul      assert(srb->Map);
14670ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
14680ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      src = _swrast_pixel_address(rb, x + skip, y);
14690ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
14700ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      if (dstType == GL_UNSIGNED_BYTE) {
14710ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         _mesa_unpack_ubyte_rgba_row(rb->Format, length, src,
14720ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                     (GLubyte (*)[4]) rgba + skip);
14730ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      }
14740ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      else if (dstType == GL_FLOAT) {
14750ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         _mesa_unpack_rgba_row(rb->Format, length, src,
14760ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                               (GLfloat (*)[4]) rgba + skip);
147776e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
147876e778dce59aa6f290db50242df945943fc47b05Brian Paul      else {
14790ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()");
148076e778dce59aa6f290db50242df945943fc47b05Brian Paul      }
1481e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
1482e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
1483e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
1484e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
148579c2f534916046fab91f53ebd37f705bd25f7dcbBrian Paul/**
14860ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul * Get colors at x/y positions with clipping.
14870ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul * \param type  type of values to return
148867074332728acba86da7630353673b458713bb8aBrian Paul */
1489ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paulstatic void
1490ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paulget_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
1491ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paul           GLuint count, const GLint x[], const GLint y[],
14920ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul           void *values, GLenum type)
149367074332728acba86da7630353673b458713bb8aBrian Paul{
14940ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   GLuint i;
149567074332728acba86da7630353673b458713bb8aBrian Paul
149667074332728acba86da7630353673b458713bb8aBrian Paul   for (i = 0; i < count; i++) {
1497ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian      if (x[i] >= 0 && y[i] >= 0 &&
1498ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian	  x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) {
149967074332728acba86da7630353673b458713bb8aBrian Paul         /* inside */
15000ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]);
15010ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
15020ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         if (type == GL_UNSIGNED_BYTE) {
15030ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src,
15040ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                        (GLubyte (*)[4]) values + i);
15050ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         }
15060ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         else if (type == GL_FLOAT) {
15070ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            _mesa_unpack_rgba_row(rb->Format, 1, src,
15080ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                  (GLfloat (*)[4]) values + i);
15090ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         }
15100ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul         else {
15110ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul            _mesa_problem(ctx, "unexpected type in get_values()");
151267074332728acba86da7630353673b458713bb8aBrian Paul         }
151367074332728acba86da7630353673b458713bb8aBrian Paul      }
151467074332728acba86da7630353673b458713bb8aBrian Paul   }
151567074332728acba86da7630353673b458713bb8aBrian Paul}
15163fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15173fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul
15183fd819aef8139761ce86cb8d763de83a11c81b33Brian Paul/**
15190ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul * Get row of colors with clipping.
15200ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul * \param type  type of values to return
1521f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul */
1522ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paulstatic void
1523ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paulget_row(struct gl_context *ctx, struct gl_renderbuffer *rb,
1524ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paul        GLuint count, GLint x, GLint y,
15250ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul        GLvoid *values, GLenum type)
1526f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul{
1527f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   GLint skip = 0;
15280ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   GLubyte *src;
1529f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1530ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (y < 0 || y >= (GLint) rb->Height)
1531f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* above or below */
1532f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1533ea8b68e0f7e7a4025ce662d36380157273ce10a3Brian   if (x + (GLint) count <= 0 || x >= (GLint) rb->Width)
1534f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      return; /* entirely left or right */
1535f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1536f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x + count > rb->Width) {
1537f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* right clip */
1538f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      GLint clip = x + count - rb->Width;
1539f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= clip;
1540f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1541f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
1542f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   if (x < 0) {
1543f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      /* left clip */
1544f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      skip = -x;
1545f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      x = 0;
1546f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul      count -= skip;
1547f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul   }
1548f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul
15490ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   src = _swrast_pixel_address(rb, x, y);
15500ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul
15510ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   if (type == GL_UNSIGNED_BYTE) {
15520ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      _mesa_unpack_ubyte_rgba_row(rb->Format, count, src,
15530ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                                  (GLubyte (*)[4]) values + skip);
15540ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   }
15550ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   else if (type == GL_FLOAT) {
15560ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      _mesa_unpack_rgba_row(rb->Format, count, src,
15570ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                            (GLfloat (*)[4]) values + skip);
15580ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   }
15590ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   else {
15600ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul      _mesa_problem(ctx, "unexpected type in get_row()");
15610ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul   }
1562f493a04be0e004bb07f84b2e28124ed8cb6a9b38Brian Paul}
1563a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1564a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1565a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul/**
1566195e7657e2f15f7ad8b22042b86bcf33c5bba76bBrian Paul * Get RGBA pixels from the given renderbuffer.
1567a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * Used by blending, logicop and masking functions.
1568a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul * \return pointer to the colors we read.
1569a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul */
1570a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paulvoid *
1571f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb,
1572cdb27e8242215271364602995d85607cfc06d441Brian Paul                      SWspan *span)
1573a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul{
1574a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   void *rbPixels;
1575a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1576195e7657e2f15f7ad8b22042b86bcf33c5bba76bBrian Paul   /* Point rbPixels to a temporary space */
1577195e7657e2f15f7ad8b22042b86bcf33c5bba76bBrian Paul   rbPixels = span->array->attribs[FRAG_ATTRIB_MAX - 1];
1578a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1579a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   /* Get destination values from renderbuffer */
1580a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   if (span->arrayMask & SPAN_XY) {
1581ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paul      get_values(ctx, rb, span->end, span->array->x, span->array->y,
15820ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul                 rbPixels, span->array->ChanType);
1583a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1584a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   else {
1585ff57b0f037a45b0d5ced38234f0a8b29d32e7f9dBrian Paul      get_row(ctx, rb, span->end, span->x, span->y,
15860ff817f200ef4cb4a5ab0d90eccfc83d0671fb65Brian Paul              rbPixels, span->array->ChanType);
1587a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   }
1588a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul
1589a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul   return rbPixels;
1590a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4Brian Paul}
1591