1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg/* 26848b8605Smrg * Triangle Rasterizer Template 27848b8605Smrg * 28848b8605Smrg * This file is #include'd to generate custom triangle rasterizers. 29848b8605Smrg * 30848b8605Smrg * The following macros may be defined to indicate what auxillary information 31848b8605Smrg * must be interpolated across the triangle: 32848b8605Smrg * INTERP_Z - if defined, interpolate integer Z values 33848b8605Smrg * INTERP_RGB - if defined, interpolate integer RGB values 34848b8605Smrg * INTERP_ALPHA - if defined, interpolate integer Alpha values 35848b8605Smrg * INTERP_INT_TEX - if defined, interpolate integer ST texcoords 36848b8605Smrg * (fast, simple 2-D texture mapping, without 37848b8605Smrg * perspective correction) 38848b8605Smrg * INTERP_ATTRIBS - if defined, interpolate arbitrary attribs (texcoords, 39848b8605Smrg * varying vars, etc) This also causes W to be 40848b8605Smrg * computed for perspective correction). 41848b8605Smrg * 42848b8605Smrg * When one can directly address pixels in the color buffer the following 43848b8605Smrg * macros can be defined and used to compute pixel addresses during 44848b8605Smrg * rasterization (see pRow): 45848b8605Smrg * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint) 46848b8605Smrg * BYTES_PER_ROW - number of bytes per row in the color buffer 47848b8605Smrg * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where 48848b8605Smrg * Y==0 at bottom of screen and increases upward. 49848b8605Smrg * 50848b8605Smrg * Similarly, for direct depth buffer access, this type is used for depth 51848b8605Smrg * buffer addressing (see zRow): 52848b8605Smrg * DEPTH_TYPE - either GLushort or GLuint 53848b8605Smrg * 54848b8605Smrg * Optionally, one may provide one-time setup code per triangle: 55848b8605Smrg * SETUP_CODE - code which is to be executed once per triangle 56848b8605Smrg * 57848b8605Smrg * The following macro MUST be defined: 58848b8605Smrg * RENDER_SPAN(span) - code to write a span of pixels. 59848b8605Smrg * 60848b8605Smrg * This code was designed for the origin to be in the lower-left corner. 61848b8605Smrg * 62848b8605Smrg * Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen! 63848b8605Smrg * 64848b8605Smrg * 65848b8605Smrg * Some notes on rasterization accuracy: 66848b8605Smrg * 67848b8605Smrg * This code uses fixed point arithmetic (the GLfixed type) to iterate 68848b8605Smrg * over the triangle edges and interpolate ancillary data (such as Z, 69848b8605Smrg * color, secondary color, etc). The number of fractional bits in 70848b8605Smrg * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the 71848b8605Smrg * accuracy of rasterization. 72848b8605Smrg * 73848b8605Smrg * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest 74848b8605Smrg * 1/16 of a pixel. If we're walking up a long, nearly vertical edge 75848b8605Smrg * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in 76848b8605Smrg * GLfixed to walk the edge without error. If the maximum viewport 77848b8605Smrg * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits. 78848b8605Smrg * 79848b8605Smrg * Historically, Mesa has used 11 fractional bits in GLfixed, snaps 80848b8605Smrg * vertices to 1/16 pixel and allowed a maximum viewport height of 2K 81848b8605Smrg * pixels. 11 fractional bits is actually insufficient for accurately 82848b8605Smrg * rasterizing some triangles. More recently, the maximum viewport 83848b8605Smrg * height was increased to 4K pixels. Thus, Mesa should be using 16 84848b8605Smrg * fractional bits in GLfixed. Unfortunately, there may be some issues 85848b8605Smrg * with setting FIXED_FRAC_BITS=16, such as multiplication overflow. 86848b8605Smrg * This will have to be examined in some detail... 87848b8605Smrg * 88848b8605Smrg * For now, if you find rasterization errors, particularly with tall, 89848b8605Smrg * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing 90848b8605Smrg * SUB_PIXEL_BITS. 91848b8605Smrg */ 92848b8605Smrg 93848b8605Smrg 94b8e80941Smrg#ifndef MAX_GLUINT 95b8e80941Smrg#define MAX_GLUINT 0xffffffffu 96b8e80941Smrg#endif 97b8e80941Smrg 98b8e80941Smrg 99848b8605Smrg/* 100848b8605Smrg * Some code we unfortunately need to prevent negative interpolated colors. 101848b8605Smrg */ 102848b8605Smrg#ifndef CLAMP_INTERPOLANT 103848b8605Smrg#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \ 104848b8605Smrgdo { \ 105848b8605Smrg GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \ 106848b8605Smrg if (endVal < 0) { \ 107848b8605Smrg span.CHANNEL -= endVal; \ 108848b8605Smrg } \ 109848b8605Smrg if (span.CHANNEL < 0) { \ 110848b8605Smrg span.CHANNEL = 0; \ 111848b8605Smrg } \ 112848b8605Smrg} while (0) 113848b8605Smrg#endif 114848b8605Smrg 115848b8605Smrg 116848b8605Smrgstatic void NAME(struct gl_context *ctx, const SWvertex *v0, 117848b8605Smrg const SWvertex *v1, 118848b8605Smrg const SWvertex *v2 ) 119848b8605Smrg{ 120848b8605Smrg typedef struct { 121848b8605Smrg const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */ 122848b8605Smrg GLfloat dx; /* X(v1) - X(v0) */ 123848b8605Smrg GLfloat dy; /* Y(v1) - Y(v0) */ 124848b8605Smrg GLfloat dxdy; /* dx/dy */ 125848b8605Smrg GLfixed fdxdy; /* dx/dy in fixed-point */ 126848b8605Smrg GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */ 127848b8605Smrg GLfixed fsx; /* first sample point x coord */ 128848b8605Smrg GLfixed fsy; 129848b8605Smrg GLfixed fx0; /* fixed pt X of lower endpoint */ 130848b8605Smrg GLint lines; /* number of lines to be sampled on this edge */ 131848b8605Smrg } EdgeT; 132848b8605Smrg 133848b8605Smrg const SWcontext *swrast = SWRAST_CONTEXT(ctx); 134848b8605Smrg#ifdef INTERP_Z 135848b8605Smrg const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; 136848b8605Smrg const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0; 137848b8605Smrg const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF; 138848b8605Smrg#define FixedToDepth(F) ((F) >> fixedToDepthShift) 139848b8605Smrg#endif 140848b8605Smrg EdgeT eMaj, eTop, eBot; 141848b8605Smrg GLfloat oneOverArea; 142848b8605Smrg const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */ 143848b8605Smrg GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign; 144848b8605Smrg const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */ 145848b8605Smrg GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy; 146848b8605Smrg 147848b8605Smrg SWspan span; 148848b8605Smrg 149848b8605Smrg (void) swrast; 150848b8605Smrg 151848b8605Smrg INIT_SPAN(span, GL_POLYGON); 152848b8605Smrg span.y = 0; /* silence warnings */ 153848b8605Smrg 154848b8605Smrg#ifdef INTERP_Z 155848b8605Smrg (void) fixedToDepthShift; 156848b8605Smrg#endif 157848b8605Smrg 158848b8605Smrg /* 159b8e80941Smrg printf("%s()\n", __func__); 160848b8605Smrg printf(" %g, %g, %g\n", 161848b8605Smrg v0->attrib[VARYING_SLOT_POS][0], 162848b8605Smrg v0->attrib[VARYING_SLOT_POS][1], 163848b8605Smrg v0->attrib[VARYING_SLOT_POS][2]); 164848b8605Smrg printf(" %g, %g, %g\n", 165848b8605Smrg v1->attrib[VARYING_SLOT_POS][0], 166848b8605Smrg v1->attrib[VARYING_SLOT_POS][1], 167848b8605Smrg v1->attrib[VARYING_SLOT_POS][2]); 168848b8605Smrg printf(" %g, %g, %g\n", 169848b8605Smrg v2->attrib[VARYING_SLOT_POS][0], 170848b8605Smrg v2->attrib[VARYING_SLOT_POS][1], 171848b8605Smrg v2->attrib[VARYING_SLOT_POS][2]); 172848b8605Smrg */ 173848b8605Smrg 174848b8605Smrg /* Compute fixed point x,y coords w/ half-pixel offsets and snapping. 175848b8605Smrg * And find the order of the 3 vertices along the Y axis. 176848b8605Smrg */ 177848b8605Smrg { 178848b8605Smrg const GLfixed fy0 = FloatToFixed(v0->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask; 179848b8605Smrg const GLfixed fy1 = FloatToFixed(v1->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask; 180848b8605Smrg const GLfixed fy2 = FloatToFixed(v2->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask; 181848b8605Smrg if (fy0 <= fy1) { 182848b8605Smrg if (fy1 <= fy2) { 183848b8605Smrg /* y0 <= y1 <= y2 */ 184848b8605Smrg vMin = v0; vMid = v1; vMax = v2; 185848b8605Smrg vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2; 186848b8605Smrg } 187848b8605Smrg else if (fy2 <= fy0) { 188848b8605Smrg /* y2 <= y0 <= y1 */ 189848b8605Smrg vMin = v2; vMid = v0; vMax = v1; 190848b8605Smrg vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1; 191848b8605Smrg } 192848b8605Smrg else { 193848b8605Smrg /* y0 <= y2 <= y1 */ 194848b8605Smrg vMin = v0; vMid = v2; vMax = v1; 195848b8605Smrg vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1; 196848b8605Smrg bf = -bf; 197848b8605Smrg } 198848b8605Smrg } 199848b8605Smrg else { 200848b8605Smrg if (fy0 <= fy2) { 201848b8605Smrg /* y1 <= y0 <= y2 */ 202848b8605Smrg vMin = v1; vMid = v0; vMax = v2; 203848b8605Smrg vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2; 204848b8605Smrg bf = -bf; 205848b8605Smrg } 206848b8605Smrg else if (fy2 <= fy1) { 207848b8605Smrg /* y2 <= y1 <= y0 */ 208848b8605Smrg vMin = v2; vMid = v1; vMax = v0; 209848b8605Smrg vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0; 210848b8605Smrg bf = -bf; 211848b8605Smrg } 212848b8605Smrg else { 213848b8605Smrg /* y1 <= y2 <= y0 */ 214848b8605Smrg vMin = v1; vMid = v2; vMax = v0; 215848b8605Smrg vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0; 216848b8605Smrg } 217848b8605Smrg } 218848b8605Smrg 219848b8605Smrg /* fixed point X coords */ 220848b8605Smrg vMin_fx = FloatToFixed(vMin->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask; 221848b8605Smrg vMid_fx = FloatToFixed(vMid->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask; 222848b8605Smrg vMax_fx = FloatToFixed(vMax->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask; 223848b8605Smrg } 224848b8605Smrg 225848b8605Smrg /* vertex/edge relationship */ 226848b8605Smrg eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */ 227848b8605Smrg eTop.v0 = vMid; eTop.v1 = vMax; 228848b8605Smrg eBot.v0 = vMin; eBot.v1 = vMid; 229848b8605Smrg 230848b8605Smrg /* compute deltas for each edge: vertex[upper] - vertex[lower] */ 231848b8605Smrg eMaj.dx = FixedToFloat(vMax_fx - vMin_fx); 232848b8605Smrg eMaj.dy = FixedToFloat(vMax_fy - vMin_fy); 233848b8605Smrg eTop.dx = FixedToFloat(vMax_fx - vMid_fx); 234848b8605Smrg eTop.dy = FixedToFloat(vMax_fy - vMid_fy); 235848b8605Smrg eBot.dx = FixedToFloat(vMid_fx - vMin_fx); 236848b8605Smrg eBot.dy = FixedToFloat(vMid_fy - vMin_fy); 237848b8605Smrg 238848b8605Smrg /* compute area, oneOverArea and perform backface culling */ 239848b8605Smrg { 240848b8605Smrg const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy; 241848b8605Smrg 242848b8605Smrg if (IS_INF_OR_NAN(area) || area == 0.0F) 243848b8605Smrg return; 244848b8605Smrg 245b8e80941Smrg if (area * bf * swrast->_BackfaceCullSign < 0.0F) 246848b8605Smrg return; 247848b8605Smrg 248848b8605Smrg oneOverArea = 1.0F / area; 249848b8605Smrg 250848b8605Smrg /* 0 = front, 1 = back */ 251848b8605Smrg span.facing = oneOverArea * bf > 0.0F; 252848b8605Smrg } 253848b8605Smrg 254848b8605Smrg /* Edge setup. For a triangle strip these could be reused... */ 255848b8605Smrg { 256848b8605Smrg eMaj.fsy = FixedCeil(vMin_fy); 257848b8605Smrg eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy)); 258848b8605Smrg if (eMaj.lines > 0) { 259848b8605Smrg eMaj.dxdy = eMaj.dx / eMaj.dy; 260848b8605Smrg eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy); 261848b8605Smrg eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */ 262848b8605Smrg eMaj.fx0 = vMin_fx; 263848b8605Smrg eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy); 264848b8605Smrg } 265848b8605Smrg else { 266848b8605Smrg return; /*CULLED*/ 267848b8605Smrg } 268848b8605Smrg 269848b8605Smrg eTop.fsy = FixedCeil(vMid_fy); 270848b8605Smrg eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy)); 271848b8605Smrg if (eTop.lines > 0) { 272848b8605Smrg eTop.dxdy = eTop.dx / eTop.dy; 273848b8605Smrg eTop.fdxdy = SignedFloatToFixed(eTop.dxdy); 274848b8605Smrg eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */ 275848b8605Smrg eTop.fx0 = vMid_fx; 276848b8605Smrg eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy); 277848b8605Smrg } 278848b8605Smrg 279848b8605Smrg eBot.fsy = FixedCeil(vMin_fy); 280848b8605Smrg eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy)); 281848b8605Smrg if (eBot.lines > 0) { 282848b8605Smrg eBot.dxdy = eBot.dx / eBot.dy; 283848b8605Smrg eBot.fdxdy = SignedFloatToFixed(eBot.dxdy); 284848b8605Smrg eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */ 285848b8605Smrg eBot.fx0 = vMin_fx; 286848b8605Smrg eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy); 287848b8605Smrg } 288848b8605Smrg } 289848b8605Smrg 290848b8605Smrg /* 291848b8605Smrg * Conceptually, we view a triangle as two subtriangles 292848b8605Smrg * separated by a perfectly horizontal line. The edge that is 293848b8605Smrg * intersected by this line is one with maximal absolute dy; we 294848b8605Smrg * call it a ``major'' edge. The other two edges are the 295848b8605Smrg * ``top'' edge (for the upper subtriangle) and the ``bottom'' 296848b8605Smrg * edge (for the lower subtriangle). If either of these two 297848b8605Smrg * edges is horizontal or very close to horizontal, the 298848b8605Smrg * corresponding subtriangle might cover zero sample points; 299848b8605Smrg * we take care to handle such cases, for performance as well 300848b8605Smrg * as correctness. 301848b8605Smrg * 302848b8605Smrg * By stepping rasterization parameters along the major edge, 303848b8605Smrg * we can avoid recomputing them at the discontinuity where 304848b8605Smrg * the top and bottom edges meet. However, this forces us to 305848b8605Smrg * be able to scan both left-to-right and right-to-left. 306848b8605Smrg * Also, we must determine whether the major edge is at the 307848b8605Smrg * left or right side of the triangle. We do this by 308848b8605Smrg * computing the magnitude of the cross-product of the major 309848b8605Smrg * and top edges. Since this magnitude depends on the sine of 310848b8605Smrg * the angle between the two edges, its sign tells us whether 311848b8605Smrg * we turn to the left or to the right when travelling along 312848b8605Smrg * the major edge to the top edge, and from this we infer 313848b8605Smrg * whether the major edge is on the left or the right. 314848b8605Smrg * 315848b8605Smrg * Serendipitously, this cross-product magnitude is also a 316848b8605Smrg * value we need to compute the iteration parameter 317848b8605Smrg * derivatives for the triangle, and it can be used to perform 318848b8605Smrg * backface culling because its sign tells us whether the 319848b8605Smrg * triangle is clockwise or counterclockwise. In this code we 320848b8605Smrg * refer to it as ``area'' because it's also proportional to 321848b8605Smrg * the pixel area of the triangle. 322848b8605Smrg */ 323848b8605Smrg 324848b8605Smrg { 325848b8605Smrg GLint scan_from_left_to_right; /* true if scanning left-to-right */ 326848b8605Smrg 327848b8605Smrg /* 328848b8605Smrg * Execute user-supplied setup code 329848b8605Smrg */ 330848b8605Smrg#ifdef SETUP_CODE 331848b8605Smrg SETUP_CODE 332848b8605Smrg#endif 333848b8605Smrg 334848b8605Smrg scan_from_left_to_right = (oneOverArea < 0.0F); 335848b8605Smrg 336848b8605Smrg 337848b8605Smrg /* compute d?/dx and d?/dy derivatives */ 338848b8605Smrg#ifdef INTERP_Z 339848b8605Smrg span.interpMask |= SPAN_Z; 340848b8605Smrg { 341848b8605Smrg GLfloat eMaj_dz = vMax->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2]; 342848b8605Smrg GLfloat eBot_dz = vMid->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2]; 343848b8605Smrg span.attrStepX[VARYING_SLOT_POS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz); 344848b8605Smrg if (span.attrStepX[VARYING_SLOT_POS][2] > maxDepth || 345848b8605Smrg span.attrStepX[VARYING_SLOT_POS][2] < -maxDepth) { 346848b8605Smrg /* probably a sliver triangle */ 347848b8605Smrg span.attrStepX[VARYING_SLOT_POS][2] = 0.0; 348848b8605Smrg span.attrStepY[VARYING_SLOT_POS][2] = 0.0; 349848b8605Smrg } 350848b8605Smrg else { 351848b8605Smrg span.attrStepY[VARYING_SLOT_POS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx); 352848b8605Smrg } 353848b8605Smrg if (depthBits <= 16) 354848b8605Smrg span.zStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_POS][2]); 355848b8605Smrg else 356848b8605Smrg span.zStep = (GLint) span.attrStepX[VARYING_SLOT_POS][2]; 357848b8605Smrg } 358848b8605Smrg#endif 359848b8605Smrg#ifdef INTERP_RGB 360848b8605Smrg span.interpMask |= SPAN_RGBA; 361848b8605Smrg if (ctx->Light.ShadeModel == GL_SMOOTH) { 362848b8605Smrg GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]); 363848b8605Smrg GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]); 364848b8605Smrg GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]); 365848b8605Smrg GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]); 366848b8605Smrg GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]); 367848b8605Smrg GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]); 368848b8605Smrg# ifdef INTERP_ALPHA 369848b8605Smrg GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]); 370848b8605Smrg GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]); 371848b8605Smrg# endif 372848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr); 373848b8605Smrg span.attrStepY[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx); 374848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg); 375848b8605Smrg span.attrStepY[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx); 376848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db); 377848b8605Smrg span.attrStepY[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx); 378848b8605Smrg span.redStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][0]); 379848b8605Smrg span.greenStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][1]); 380848b8605Smrg span.blueStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][2]); 381848b8605Smrg# ifdef INTERP_ALPHA 382848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da); 383848b8605Smrg span.attrStepY[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx); 384848b8605Smrg span.alphaStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][3]); 385848b8605Smrg# endif /* INTERP_ALPHA */ 386848b8605Smrg } 387848b8605Smrg else { 388b8e80941Smrg assert(ctx->Light.ShadeModel == GL_FLAT); 389848b8605Smrg span.interpMask |= SPAN_FLAT; 390848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][0] = span.attrStepY[VARYING_SLOT_COL0][0] = 0.0F; 391848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][1] = span.attrStepY[VARYING_SLOT_COL0][1] = 0.0F; 392848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][2] = span.attrStepY[VARYING_SLOT_COL0][2] = 0.0F; 393848b8605Smrg span.redStep = 0; 394848b8605Smrg span.greenStep = 0; 395848b8605Smrg span.blueStep = 0; 396848b8605Smrg# ifdef INTERP_ALPHA 397848b8605Smrg span.attrStepX[VARYING_SLOT_COL0][3] = span.attrStepY[VARYING_SLOT_COL0][3] = 0.0F; 398848b8605Smrg span.alphaStep = 0; 399848b8605Smrg# endif 400848b8605Smrg } 401848b8605Smrg#endif /* INTERP_RGB */ 402848b8605Smrg#ifdef INTERP_INT_TEX 403848b8605Smrg { 404848b8605Smrg GLfloat eMaj_ds = (vMax->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE; 405848b8605Smrg GLfloat eBot_ds = (vMid->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE; 406848b8605Smrg GLfloat eMaj_dt = (vMax->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE; 407848b8605Smrg GLfloat eBot_dt = (vMid->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE; 408848b8605Smrg span.attrStepX[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds); 409848b8605Smrg span.attrStepY[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx); 410848b8605Smrg span.attrStepX[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt); 411848b8605Smrg span.attrStepY[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx); 412848b8605Smrg span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][0]); 413848b8605Smrg span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][1]); 414848b8605Smrg } 415848b8605Smrg#endif 416848b8605Smrg#ifdef INTERP_ATTRIBS 417848b8605Smrg { 418848b8605Smrg /* attrib[VARYING_SLOT_POS][3] is 1/W */ 419848b8605Smrg const GLfloat wMax = vMax->attrib[VARYING_SLOT_POS][3]; 420848b8605Smrg const GLfloat wMin = vMin->attrib[VARYING_SLOT_POS][3]; 421848b8605Smrg const GLfloat wMid = vMid->attrib[VARYING_SLOT_POS][3]; 422848b8605Smrg { 423848b8605Smrg const GLfloat eMaj_dw = wMax - wMin; 424848b8605Smrg const GLfloat eBot_dw = wMid - wMin; 425848b8605Smrg span.attrStepX[VARYING_SLOT_POS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw); 426848b8605Smrg span.attrStepY[VARYING_SLOT_POS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx); 427848b8605Smrg } 428848b8605Smrg ATTRIB_LOOP_BEGIN 429848b8605Smrg if (swrast->_InterpMode[attr] == GL_FLAT) { 430848b8605Smrg ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0); 431848b8605Smrg ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0); 432848b8605Smrg } 433848b8605Smrg else { 434848b8605Smrg GLuint c; 435848b8605Smrg for (c = 0; c < 4; c++) { 436848b8605Smrg GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin; 437848b8605Smrg GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin; 438848b8605Smrg span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da); 439848b8605Smrg span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx); 440848b8605Smrg } 441848b8605Smrg } 442848b8605Smrg ATTRIB_LOOP_END 443848b8605Smrg } 444848b8605Smrg#endif 445848b8605Smrg 446848b8605Smrg /* 447848b8605Smrg * We always sample at pixel centers. However, we avoid 448848b8605Smrg * explicit half-pixel offsets in this code by incorporating 449848b8605Smrg * the proper offset in each of x and y during the 450848b8605Smrg * transformation to window coordinates. 451848b8605Smrg * 452848b8605Smrg * We also apply the usual rasterization rules to prevent 453848b8605Smrg * cracks and overlaps. A pixel is considered inside a 454848b8605Smrg * subtriangle if it meets all of four conditions: it is on or 455848b8605Smrg * to the right of the left edge, strictly to the left of the 456848b8605Smrg * right edge, on or below the top edge, and strictly above 457848b8605Smrg * the bottom edge. (Some edges may be degenerate.) 458848b8605Smrg * 459848b8605Smrg * The following discussion assumes left-to-right scanning 460848b8605Smrg * (that is, the major edge is on the left); the right-to-left 461848b8605Smrg * case is a straightforward variation. 462848b8605Smrg * 463848b8605Smrg * We start by finding the half-integral y coordinate that is 464848b8605Smrg * at or below the top of the triangle. This gives us the 465848b8605Smrg * first scan line that could possibly contain pixels that are 466848b8605Smrg * inside the triangle. 467848b8605Smrg * 468848b8605Smrg * Next we creep down the major edge until we reach that y, 469848b8605Smrg * and compute the corresponding x coordinate on the edge. 470848b8605Smrg * Then we find the half-integral x that lies on or just 471848b8605Smrg * inside the edge. This is the first pixel that might lie in 472848b8605Smrg * the interior of the triangle. (We won't know for sure 473848b8605Smrg * until we check the other edges.) 474848b8605Smrg * 475848b8605Smrg * As we rasterize the triangle, we'll step down the major 476848b8605Smrg * edge. For each step in y, we'll move an integer number 477848b8605Smrg * of steps in x. There are two possible x step sizes, which 478848b8605Smrg * we'll call the ``inner'' step (guaranteed to land on the 479848b8605Smrg * edge or inside it) and the ``outer'' step (guaranteed to 480848b8605Smrg * land on the edge or outside it). The inner and outer steps 481848b8605Smrg * differ by one. During rasterization we maintain an error 482848b8605Smrg * term that indicates our distance from the true edge, and 483848b8605Smrg * select either the inner step or the outer step, whichever 484848b8605Smrg * gets us to the first pixel that falls inside the triangle. 485848b8605Smrg * 486848b8605Smrg * All parameters (z, red, etc.) as well as the buffer 487848b8605Smrg * addresses for color and z have inner and outer step values, 488848b8605Smrg * so that we can increment them appropriately. This method 489848b8605Smrg * eliminates the need to adjust parameters by creeping a 490848b8605Smrg * sub-pixel amount into the triangle at each scanline. 491848b8605Smrg */ 492848b8605Smrg 493848b8605Smrg { 494848b8605Smrg GLint subTriangle; 495848b8605Smrg GLfixed fxLeftEdge = 0, fxRightEdge = 0; 496848b8605Smrg GLfixed fdxLeftEdge = 0, fdxRightEdge = 0; 497848b8605Smrg GLfixed fError = 0, fdError = 0; 498848b8605Smrg#ifdef PIXEL_ADDRESS 499848b8605Smrg PIXEL_TYPE *pRow = NULL; 500848b8605Smrg GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */ 501848b8605Smrg#endif 502848b8605Smrg#ifdef INTERP_Z 503848b8605Smrg# ifdef DEPTH_TYPE 504848b8605Smrg struct gl_renderbuffer *zrb 505848b8605Smrg = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 506848b8605Smrg DEPTH_TYPE *zRow = NULL; 507848b8605Smrg GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */ 508848b8605Smrg# endif 509848b8605Smrg GLuint zLeft = 0; 510848b8605Smrg GLfixed fdzOuter = 0, fdzInner; 511848b8605Smrg#endif 512848b8605Smrg#ifdef INTERP_RGB 513848b8605Smrg GLint rLeft = 0, fdrOuter = 0, fdrInner; 514848b8605Smrg GLint gLeft = 0, fdgOuter = 0, fdgInner; 515848b8605Smrg GLint bLeft = 0, fdbOuter = 0, fdbInner; 516848b8605Smrg#endif 517848b8605Smrg#ifdef INTERP_ALPHA 518848b8605Smrg GLint aLeft = 0, fdaOuter = 0, fdaInner; 519848b8605Smrg#endif 520848b8605Smrg#ifdef INTERP_INT_TEX 521848b8605Smrg GLfixed sLeft=0, dsOuter=0, dsInner; 522848b8605Smrg GLfixed tLeft=0, dtOuter=0, dtInner; 523848b8605Smrg#endif 524848b8605Smrg#ifdef INTERP_ATTRIBS 525848b8605Smrg GLfloat wLeft = 0, dwOuter = 0, dwInner; 526848b8605Smrg GLfloat attrLeft[VARYING_SLOT_MAX][4]; 527848b8605Smrg GLfloat daOuter[VARYING_SLOT_MAX][4], daInner[VARYING_SLOT_MAX][4]; 528848b8605Smrg#endif 529848b8605Smrg 530848b8605Smrg for (subTriangle=0; subTriangle<=1; subTriangle++) { 531848b8605Smrg EdgeT *eLeft, *eRight; 532848b8605Smrg int setupLeft, setupRight; 533848b8605Smrg int lines; 534848b8605Smrg 535848b8605Smrg if (subTriangle==0) { 536848b8605Smrg /* bottom half */ 537848b8605Smrg if (scan_from_left_to_right) { 538848b8605Smrg eLeft = &eMaj; 539848b8605Smrg eRight = &eBot; 540848b8605Smrg lines = eRight->lines; 541848b8605Smrg setupLeft = 1; 542848b8605Smrg setupRight = 1; 543848b8605Smrg } 544848b8605Smrg else { 545848b8605Smrg eLeft = &eBot; 546848b8605Smrg eRight = &eMaj; 547848b8605Smrg lines = eLeft->lines; 548848b8605Smrg setupLeft = 1; 549848b8605Smrg setupRight = 1; 550848b8605Smrg } 551848b8605Smrg } 552848b8605Smrg else { 553848b8605Smrg /* top half */ 554848b8605Smrg if (scan_from_left_to_right) { 555848b8605Smrg eLeft = &eMaj; 556848b8605Smrg eRight = &eTop; 557848b8605Smrg lines = eRight->lines; 558848b8605Smrg setupLeft = 0; 559848b8605Smrg setupRight = 1; 560848b8605Smrg } 561848b8605Smrg else { 562848b8605Smrg eLeft = &eTop; 563848b8605Smrg eRight = &eMaj; 564848b8605Smrg lines = eLeft->lines; 565848b8605Smrg setupLeft = 1; 566848b8605Smrg setupRight = 0; 567848b8605Smrg } 568848b8605Smrg if (lines == 0) 569848b8605Smrg return; 570848b8605Smrg } 571848b8605Smrg 572848b8605Smrg if (setupLeft && eLeft->lines > 0) { 573848b8605Smrg const SWvertex *vLower = eLeft->v0; 574848b8605Smrg const GLfixed fsy = eLeft->fsy; 575848b8605Smrg const GLfixed fsx = eLeft->fsx; /* no fractional part */ 576848b8605Smrg const GLfixed fx = FixedCeil(fsx); /* no fractional part */ 577848b8605Smrg const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */ 578848b8605Smrg const GLfixed adjy = (GLfixed) eLeft->adjy; /* SCALED! */ 579848b8605Smrg GLint idxOuter; 580848b8605Smrg GLfloat dxOuter; 581848b8605Smrg GLfixed fdxOuter; 582848b8605Smrg 583848b8605Smrg fError = fx - fsx - FIXED_ONE; 584848b8605Smrg fxLeftEdge = fsx - FIXED_EPSILON; 585848b8605Smrg fdxLeftEdge = eLeft->fdxdy; 586848b8605Smrg fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON); 587848b8605Smrg fdError = fdxOuter - fdxLeftEdge + FIXED_ONE; 588848b8605Smrg idxOuter = FixedToInt(fdxOuter); 589848b8605Smrg dxOuter = (GLfloat) idxOuter; 590848b8605Smrg span.y = FixedToInt(fsy); 591848b8605Smrg 592848b8605Smrg /* silence warnings on some compilers */ 593848b8605Smrg (void) dxOuter; 594848b8605Smrg (void) adjx; 595848b8605Smrg (void) adjy; 596848b8605Smrg (void) vLower; 597848b8605Smrg 598848b8605Smrg#ifdef PIXEL_ADDRESS 599848b8605Smrg { 600848b8605Smrg pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y); 601848b8605Smrg dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE); 602848b8605Smrg /* negative because Y=0 at bottom and increases upward */ 603848b8605Smrg } 604848b8605Smrg#endif 605848b8605Smrg /* 606848b8605Smrg * Now we need the set of parameter (z, color, etc.) values at 607848b8605Smrg * the point (fx, fsy). This gives us properly-sampled parameter 608848b8605Smrg * values that we can step from pixel to pixel. Furthermore, 609848b8605Smrg * although we might have intermediate results that overflow 610848b8605Smrg * the normal parameter range when we step temporarily outside 611848b8605Smrg * the triangle, we shouldn't overflow or underflow for any 612848b8605Smrg * pixel that's actually inside the triangle. 613848b8605Smrg */ 614848b8605Smrg 615848b8605Smrg#ifdef INTERP_Z 616848b8605Smrg { 617848b8605Smrg GLfloat z0 = vLower->attrib[VARYING_SLOT_POS][2]; 618848b8605Smrg if (depthBits <= 16) { 619848b8605Smrg /* interpolate fixed-pt values */ 620848b8605Smrg GLfloat tmp = (z0 * FIXED_SCALE 621848b8605Smrg + span.attrStepX[VARYING_SLOT_POS][2] * adjx 622848b8605Smrg + span.attrStepY[VARYING_SLOT_POS][2] * adjy) + FIXED_HALF; 623848b8605Smrg if (tmp < MAX_GLUINT / 2) 624848b8605Smrg zLeft = (GLfixed) tmp; 625848b8605Smrg else 626848b8605Smrg zLeft = MAX_GLUINT / 2; 627848b8605Smrg fdzOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_POS][2] + 628848b8605Smrg dxOuter * span.attrStepX[VARYING_SLOT_POS][2]); 629848b8605Smrg } 630848b8605Smrg else { 631848b8605Smrg /* interpolate depth values w/out scaling */ 632848b8605Smrg zLeft = (GLuint) (z0 + span.attrStepX[VARYING_SLOT_POS][2] * FixedToFloat(adjx) 633848b8605Smrg + span.attrStepY[VARYING_SLOT_POS][2] * FixedToFloat(adjy)); 634848b8605Smrg fdzOuter = (GLint) (span.attrStepY[VARYING_SLOT_POS][2] + 635848b8605Smrg dxOuter * span.attrStepX[VARYING_SLOT_POS][2]); 636848b8605Smrg } 637848b8605Smrg# ifdef DEPTH_TYPE 638848b8605Smrg zRow = (DEPTH_TYPE *) 639848b8605Smrg _swrast_pixel_address(zrb, FixedToInt(fxLeftEdge), span.y); 640848b8605Smrg dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE); 641848b8605Smrg# endif 642848b8605Smrg } 643848b8605Smrg#endif 644848b8605Smrg#ifdef INTERP_RGB 645848b8605Smrg if (ctx->Light.ShadeModel == GL_SMOOTH) { 646848b8605Smrg rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP]) 647848b8605Smrg + span.attrStepX[VARYING_SLOT_COL0][0] * adjx 648848b8605Smrg + span.attrStepY[VARYING_SLOT_COL0][0] * adjy) + FIXED_HALF; 649848b8605Smrg gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP]) 650848b8605Smrg + span.attrStepX[VARYING_SLOT_COL0][1] * adjx 651848b8605Smrg + span.attrStepY[VARYING_SLOT_COL0][1] * adjy) + FIXED_HALF; 652848b8605Smrg bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP]) 653848b8605Smrg + span.attrStepX[VARYING_SLOT_COL0][2] * adjx 654848b8605Smrg + span.attrStepY[VARYING_SLOT_COL0][2] * adjy) + FIXED_HALF; 655848b8605Smrg fdrOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][0] 656848b8605Smrg + dxOuter * span.attrStepX[VARYING_SLOT_COL0][0]); 657848b8605Smrg fdgOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][1] 658848b8605Smrg + dxOuter * span.attrStepX[VARYING_SLOT_COL0][1]); 659848b8605Smrg fdbOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][2] 660848b8605Smrg + dxOuter * span.attrStepX[VARYING_SLOT_COL0][2]); 661848b8605Smrg# ifdef INTERP_ALPHA 662848b8605Smrg aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP]) 663848b8605Smrg + span.attrStepX[VARYING_SLOT_COL0][3] * adjx 664848b8605Smrg + span.attrStepY[VARYING_SLOT_COL0][3] * adjy) + FIXED_HALF; 665848b8605Smrg fdaOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][3] 666848b8605Smrg + dxOuter * span.attrStepX[VARYING_SLOT_COL0][3]); 667848b8605Smrg# endif 668848b8605Smrg } 669848b8605Smrg else { 670b8e80941Smrg assert(ctx->Light.ShadeModel == GL_FLAT); 671848b8605Smrg rLeft = ChanToFixed(v2->color[RCOMP]); 672848b8605Smrg gLeft = ChanToFixed(v2->color[GCOMP]); 673848b8605Smrg bLeft = ChanToFixed(v2->color[BCOMP]); 674848b8605Smrg fdrOuter = fdgOuter = fdbOuter = 0; 675848b8605Smrg# ifdef INTERP_ALPHA 676848b8605Smrg aLeft = ChanToFixed(v2->color[ACOMP]); 677848b8605Smrg fdaOuter = 0; 678848b8605Smrg# endif 679848b8605Smrg } 680848b8605Smrg#endif /* INTERP_RGB */ 681848b8605Smrg 682848b8605Smrg 683848b8605Smrg#ifdef INTERP_INT_TEX 684848b8605Smrg { 685848b8605Smrg GLfloat s0, t0; 686848b8605Smrg s0 = vLower->attrib[VARYING_SLOT_TEX0][0] * S_SCALE; 687848b8605Smrg sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][0] * adjx 688848b8605Smrg + span.attrStepY[VARYING_SLOT_TEX0][0] * adjy) + FIXED_HALF; 689848b8605Smrg dsOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][0] 690848b8605Smrg + dxOuter * span.attrStepX[VARYING_SLOT_TEX0][0]); 691848b8605Smrg 692848b8605Smrg t0 = vLower->attrib[VARYING_SLOT_TEX0][1] * T_SCALE; 693848b8605Smrg tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][1] * adjx 694848b8605Smrg + span.attrStepY[VARYING_SLOT_TEX0][1] * adjy) + FIXED_HALF; 695848b8605Smrg dtOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][1] 696848b8605Smrg + dxOuter * span.attrStepX[VARYING_SLOT_TEX0][1]); 697848b8605Smrg } 698848b8605Smrg#endif 699848b8605Smrg#ifdef INTERP_ATTRIBS 700848b8605Smrg { 701848b8605Smrg const GLuint attr = VARYING_SLOT_POS; 702848b8605Smrg wLeft = vLower->attrib[VARYING_SLOT_POS][3] 703848b8605Smrg + (span.attrStepX[attr][3] * adjx 704848b8605Smrg + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE); 705848b8605Smrg dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3]; 706848b8605Smrg } 707848b8605Smrg ATTRIB_LOOP_BEGIN 708848b8605Smrg const GLfloat invW = vLower->attrib[VARYING_SLOT_POS][3]; 709848b8605Smrg if (swrast->_InterpMode[attr] == GL_FLAT) { 710848b8605Smrg GLuint c; 711848b8605Smrg for (c = 0; c < 4; c++) { 712848b8605Smrg attrLeft[attr][c] = v2->attrib[attr][c] * invW; 713848b8605Smrg daOuter[attr][c] = 0.0; 714848b8605Smrg } 715848b8605Smrg } 716848b8605Smrg else { 717848b8605Smrg GLuint c; 718848b8605Smrg for (c = 0; c < 4; c++) { 719848b8605Smrg const GLfloat a = vLower->attrib[attr][c] * invW; 720848b8605Smrg attrLeft[attr][c] = a + ( span.attrStepX[attr][c] * adjx 721848b8605Smrg + span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE); 722848b8605Smrg daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c]; 723848b8605Smrg } 724848b8605Smrg } 725848b8605Smrg ATTRIB_LOOP_END 726848b8605Smrg#endif 727848b8605Smrg } /*if setupLeft*/ 728848b8605Smrg 729848b8605Smrg 730848b8605Smrg if (setupRight && eRight->lines>0) { 731848b8605Smrg fxRightEdge = eRight->fsx - FIXED_EPSILON; 732848b8605Smrg fdxRightEdge = eRight->fdxdy; 733848b8605Smrg } 734848b8605Smrg 735848b8605Smrg if (lines==0) { 736848b8605Smrg continue; 737848b8605Smrg } 738848b8605Smrg 739848b8605Smrg 740848b8605Smrg /* Rasterize setup */ 741848b8605Smrg#ifdef PIXEL_ADDRESS 742848b8605Smrg dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE); 743848b8605Smrg#endif 744848b8605Smrg#ifdef INTERP_Z 745848b8605Smrg# ifdef DEPTH_TYPE 746848b8605Smrg dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE); 747848b8605Smrg# endif 748848b8605Smrg fdzInner = fdzOuter + span.zStep; 749848b8605Smrg#endif 750848b8605Smrg#ifdef INTERP_RGB 751848b8605Smrg fdrInner = fdrOuter + span.redStep; 752848b8605Smrg fdgInner = fdgOuter + span.greenStep; 753848b8605Smrg fdbInner = fdbOuter + span.blueStep; 754848b8605Smrg#endif 755848b8605Smrg#ifdef INTERP_ALPHA 756848b8605Smrg fdaInner = fdaOuter + span.alphaStep; 757848b8605Smrg#endif 758848b8605Smrg#ifdef INTERP_INT_TEX 759848b8605Smrg dsInner = dsOuter + span.intTexStep[0]; 760848b8605Smrg dtInner = dtOuter + span.intTexStep[1]; 761848b8605Smrg#endif 762848b8605Smrg#ifdef INTERP_ATTRIBS 763848b8605Smrg dwInner = dwOuter + span.attrStepX[VARYING_SLOT_POS][3]; 764848b8605Smrg ATTRIB_LOOP_BEGIN 765848b8605Smrg GLuint c; 766848b8605Smrg for (c = 0; c < 4; c++) { 767848b8605Smrg daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c]; 768848b8605Smrg } 769848b8605Smrg ATTRIB_LOOP_END 770848b8605Smrg#endif 771848b8605Smrg 772848b8605Smrg while (lines > 0) { 773848b8605Smrg /* initialize the span interpolants to the leftmost value */ 774848b8605Smrg /* ff = fixed-pt fragment */ 775848b8605Smrg const GLint right = FixedToInt(fxRightEdge); 776848b8605Smrg span.x = FixedToInt(fxLeftEdge); 777848b8605Smrg if (right <= span.x) 778848b8605Smrg span.end = 0; 779848b8605Smrg else 780848b8605Smrg span.end = right - span.x; 781848b8605Smrg 782848b8605Smrg#ifdef INTERP_Z 783848b8605Smrg span.z = zLeft; 784848b8605Smrg#endif 785848b8605Smrg#ifdef INTERP_RGB 786848b8605Smrg span.red = rLeft; 787848b8605Smrg span.green = gLeft; 788848b8605Smrg span.blue = bLeft; 789848b8605Smrg#endif 790848b8605Smrg#ifdef INTERP_ALPHA 791848b8605Smrg span.alpha = aLeft; 792848b8605Smrg#endif 793848b8605Smrg#ifdef INTERP_INT_TEX 794848b8605Smrg span.intTex[0] = sLeft; 795848b8605Smrg span.intTex[1] = tLeft; 796848b8605Smrg#endif 797848b8605Smrg 798848b8605Smrg#ifdef INTERP_ATTRIBS 799848b8605Smrg span.attrStart[VARYING_SLOT_POS][3] = wLeft; 800848b8605Smrg ATTRIB_LOOP_BEGIN 801848b8605Smrg GLuint c; 802848b8605Smrg for (c = 0; c < 4; c++) { 803848b8605Smrg span.attrStart[attr][c] = attrLeft[attr][c]; 804848b8605Smrg } 805848b8605Smrg ATTRIB_LOOP_END 806848b8605Smrg#endif 807848b8605Smrg 808848b8605Smrg /* This is where we actually generate fragments */ 809848b8605Smrg /* XXX the test for span.y > 0 _shouldn't_ be needed but 810848b8605Smrg * it fixes a problem on 64-bit Opterons (bug 4842). 811848b8605Smrg */ 812848b8605Smrg if (span.end > 0 && span.y >= 0) { 813848b8605Smrg const GLint len = span.end - 1; 814848b8605Smrg (void) len; 815848b8605Smrg#ifdef INTERP_RGB 816848b8605Smrg CLAMP_INTERPOLANT(red, redStep, len); 817848b8605Smrg CLAMP_INTERPOLANT(green, greenStep, len); 818848b8605Smrg CLAMP_INTERPOLANT(blue, blueStep, len); 819848b8605Smrg#endif 820848b8605Smrg#ifdef INTERP_ALPHA 821848b8605Smrg CLAMP_INTERPOLANT(alpha, alphaStep, len); 822848b8605Smrg#endif 823848b8605Smrg { 824848b8605Smrg RENDER_SPAN( span ); 825848b8605Smrg } 826848b8605Smrg } 827848b8605Smrg 828848b8605Smrg /* 829848b8605Smrg * Advance to the next scan line. Compute the 830848b8605Smrg * new edge coordinates, and adjust the 831848b8605Smrg * pixel-center x coordinate so that it stays 832848b8605Smrg * on or inside the major edge. 833848b8605Smrg */ 834848b8605Smrg span.y++; 835848b8605Smrg lines--; 836848b8605Smrg 837848b8605Smrg fxLeftEdge += fdxLeftEdge; 838848b8605Smrg fxRightEdge += fdxRightEdge; 839848b8605Smrg 840848b8605Smrg fError += fdError; 841848b8605Smrg if (fError >= 0) { 842848b8605Smrg fError -= FIXED_ONE; 843848b8605Smrg 844848b8605Smrg#ifdef PIXEL_ADDRESS 845848b8605Smrg pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter); 846848b8605Smrg#endif 847848b8605Smrg#ifdef INTERP_Z 848848b8605Smrg# ifdef DEPTH_TYPE 849848b8605Smrg zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter); 850848b8605Smrg# endif 851848b8605Smrg zLeft += fdzOuter; 852848b8605Smrg#endif 853848b8605Smrg#ifdef INTERP_RGB 854848b8605Smrg rLeft += fdrOuter; 855848b8605Smrg gLeft += fdgOuter; 856848b8605Smrg bLeft += fdbOuter; 857848b8605Smrg#endif 858848b8605Smrg#ifdef INTERP_ALPHA 859848b8605Smrg aLeft += fdaOuter; 860848b8605Smrg#endif 861848b8605Smrg#ifdef INTERP_INT_TEX 862848b8605Smrg sLeft += dsOuter; 863848b8605Smrg tLeft += dtOuter; 864848b8605Smrg#endif 865848b8605Smrg#ifdef INTERP_ATTRIBS 866848b8605Smrg wLeft += dwOuter; 867848b8605Smrg ATTRIB_LOOP_BEGIN 868848b8605Smrg GLuint c; 869848b8605Smrg for (c = 0; c < 4; c++) { 870848b8605Smrg attrLeft[attr][c] += daOuter[attr][c]; 871848b8605Smrg } 872848b8605Smrg ATTRIB_LOOP_END 873848b8605Smrg#endif 874848b8605Smrg } 875848b8605Smrg else { 876848b8605Smrg#ifdef PIXEL_ADDRESS 877848b8605Smrg pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner); 878848b8605Smrg#endif 879848b8605Smrg#ifdef INTERP_Z 880848b8605Smrg# ifdef DEPTH_TYPE 881848b8605Smrg zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner); 882848b8605Smrg# endif 883848b8605Smrg zLeft += fdzInner; 884848b8605Smrg#endif 885848b8605Smrg#ifdef INTERP_RGB 886848b8605Smrg rLeft += fdrInner; 887848b8605Smrg gLeft += fdgInner; 888848b8605Smrg bLeft += fdbInner; 889848b8605Smrg#endif 890848b8605Smrg#ifdef INTERP_ALPHA 891848b8605Smrg aLeft += fdaInner; 892848b8605Smrg#endif 893848b8605Smrg#ifdef INTERP_INT_TEX 894848b8605Smrg sLeft += dsInner; 895848b8605Smrg tLeft += dtInner; 896848b8605Smrg#endif 897848b8605Smrg#ifdef INTERP_ATTRIBS 898848b8605Smrg wLeft += dwInner; 899848b8605Smrg ATTRIB_LOOP_BEGIN 900848b8605Smrg GLuint c; 901848b8605Smrg for (c = 0; c < 4; c++) { 902848b8605Smrg attrLeft[attr][c] += daInner[attr][c]; 903848b8605Smrg } 904848b8605Smrg ATTRIB_LOOP_END 905848b8605Smrg#endif 906848b8605Smrg } 907848b8605Smrg } /*while lines>0*/ 908848b8605Smrg 909848b8605Smrg } /* for subTriangle */ 910848b8605Smrg 911848b8605Smrg } 912848b8605Smrg } 913848b8605Smrg} 914848b8605Smrg 915848b8605Smrg#undef SETUP_CODE 916848b8605Smrg#undef RENDER_SPAN 917848b8605Smrg 918848b8605Smrg#undef PIXEL_TYPE 919848b8605Smrg#undef BYTES_PER_ROW 920848b8605Smrg#undef PIXEL_ADDRESS 921848b8605Smrg#undef DEPTH_TYPE 922848b8605Smrg 923848b8605Smrg#undef INTERP_Z 924848b8605Smrg#undef INTERP_RGB 925848b8605Smrg#undef INTERP_ALPHA 926848b8605Smrg#undef INTERP_INT_TEX 927848b8605Smrg#undef INTERP_ATTRIBS 928848b8605Smrg 929848b8605Smrg#undef S_SCALE 930848b8605Smrg#undef T_SCALE 931848b8605Smrg 932848b8605Smrg#undef FixedToDepth 933848b8605Smrg 934848b8605Smrg#undef NAME 935