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 26b8e80941Smrg#include "c99_math.h" 27848b8605Smrg#include "main/glheader.h" 28848b8605Smrg#include "main/imports.h" 29848b8605Smrg#include "main/macros.h" 30848b8605Smrg#include "main/mtypes.h" 31b8e80941Smrg#include "main/teximage.h" 32848b8605Smrg#include "swrast/s_aaline.h" 33848b8605Smrg#include "swrast/s_context.h" 34848b8605Smrg#include "swrast/s_span.h" 35848b8605Smrg#include "swrast/swrast.h" 36848b8605Smrg 37848b8605Smrg 38848b8605Smrg#define SUB_PIXEL 4 39848b8605Smrg 40848b8605Smrg 41848b8605Smrg/* 42848b8605Smrg * Info about the AA line we're rendering 43848b8605Smrg */ 44848b8605Smrgstruct LineInfo 45848b8605Smrg{ 46848b8605Smrg GLfloat x0, y0; /* start */ 47848b8605Smrg GLfloat x1, y1; /* end */ 48848b8605Smrg GLfloat dx, dy; /* direction vector */ 49848b8605Smrg GLfloat len; /* length */ 50848b8605Smrg GLfloat halfWidth; /* half of line width */ 51848b8605Smrg GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */ 52848b8605Smrg /* for coverage computation */ 53848b8605Smrg GLfloat qx0, qy0; /* quad vertices */ 54848b8605Smrg GLfloat qx1, qy1; 55848b8605Smrg GLfloat qx2, qy2; 56848b8605Smrg GLfloat qx3, qy3; 57848b8605Smrg GLfloat ex0, ey0; /* quad edge vectors */ 58848b8605Smrg GLfloat ex1, ey1; 59848b8605Smrg GLfloat ex2, ey2; 60848b8605Smrg GLfloat ex3, ey3; 61848b8605Smrg 62848b8605Smrg /* DO_Z */ 63848b8605Smrg GLfloat zPlane[4]; 64848b8605Smrg /* DO_RGBA - always enabled */ 65848b8605Smrg GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; 66848b8605Smrg /* DO_ATTRIBS */ 67848b8605Smrg GLfloat wPlane[4]; 68848b8605Smrg GLfloat attrPlane[VARYING_SLOT_MAX][4][4]; 69848b8605Smrg GLfloat lambda[VARYING_SLOT_MAX]; 70848b8605Smrg GLfloat texWidth[VARYING_SLOT_MAX]; 71848b8605Smrg GLfloat texHeight[VARYING_SLOT_MAX]; 72848b8605Smrg 73848b8605Smrg SWspan span; 74848b8605Smrg}; 75848b8605Smrg 76848b8605Smrg 77848b8605Smrg 78848b8605Smrg/* 79848b8605Smrg * Compute the equation of a plane used to interpolate line fragment data 80848b8605Smrg * such as color, Z, texture coords, etc. 81848b8605Smrg * Input: (x0, y0) and (x1,y1) are the endpoints of the line. 82848b8605Smrg * z0, and z1 are the end point values to interpolate. 83848b8605Smrg * Output: plane - the plane equation. 84848b8605Smrg * 85848b8605Smrg * Note: we don't really have enough parameters to specify a plane. 86848b8605Smrg * We take the endpoints of the line and compute a plane such that 87848b8605Smrg * the cross product of the line vector and the plane normal is 88848b8605Smrg * parallel to the projection plane. 89848b8605Smrg */ 90848b8605Smrgstatic void 91848b8605Smrgcompute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, 92848b8605Smrg GLfloat z0, GLfloat z1, GLfloat plane[4]) 93848b8605Smrg{ 94848b8605Smrg#if 0 95848b8605Smrg /* original */ 96848b8605Smrg const GLfloat px = x1 - x0; 97848b8605Smrg const GLfloat py = y1 - y0; 98848b8605Smrg const GLfloat pz = z1 - z0; 99848b8605Smrg const GLfloat qx = -py; 100848b8605Smrg const GLfloat qy = px; 101848b8605Smrg const GLfloat qz = 0; 102848b8605Smrg const GLfloat a = py * qz - pz * qy; 103848b8605Smrg const GLfloat b = pz * qx - px * qz; 104848b8605Smrg const GLfloat c = px * qy - py * qx; 105848b8605Smrg const GLfloat d = -(a * x0 + b * y0 + c * z0); 106848b8605Smrg plane[0] = a; 107848b8605Smrg plane[1] = b; 108848b8605Smrg plane[2] = c; 109848b8605Smrg plane[3] = d; 110848b8605Smrg#else 111848b8605Smrg /* simplified */ 112848b8605Smrg const GLfloat px = x1 - x0; 113848b8605Smrg const GLfloat py = y1 - y0; 114848b8605Smrg const GLfloat pz = z0 - z1; 115848b8605Smrg const GLfloat a = pz * px; 116848b8605Smrg const GLfloat b = pz * py; 117848b8605Smrg const GLfloat c = px * px + py * py; 118848b8605Smrg const GLfloat d = -(a * x0 + b * y0 + c * z0); 119b8e80941Smrg if (a == 0.0F && b == 0.0F && c == 0.0F && d == 0.0F) { 120b8e80941Smrg plane[0] = 0.0F; 121b8e80941Smrg plane[1] = 0.0F; 122b8e80941Smrg plane[2] = 1.0F; 123b8e80941Smrg plane[3] = 0.0F; 124848b8605Smrg } 125848b8605Smrg else { 126848b8605Smrg plane[0] = a; 127848b8605Smrg plane[1] = b; 128848b8605Smrg plane[2] = c; 129848b8605Smrg plane[3] = d; 130848b8605Smrg } 131848b8605Smrg#endif 132848b8605Smrg} 133848b8605Smrg 134848b8605Smrg 135848b8605Smrgstatic inline void 136848b8605Smrgconstant_plane(GLfloat value, GLfloat plane[4]) 137848b8605Smrg{ 138b8e80941Smrg plane[0] = 0.0F; 139b8e80941Smrg plane[1] = 0.0F; 140b8e80941Smrg plane[2] = -1.0F; 141848b8605Smrg plane[3] = value; 142848b8605Smrg} 143848b8605Smrg 144848b8605Smrg 145848b8605Smrgstatic inline GLfloat 146848b8605Smrgsolve_plane(GLfloat x, GLfloat y, const GLfloat plane[4]) 147848b8605Smrg{ 148848b8605Smrg const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; 149848b8605Smrg return z; 150848b8605Smrg} 151848b8605Smrg 152848b8605Smrg#define SOLVE_PLANE(X, Y, PLANE) \ 153848b8605Smrg ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2]) 154848b8605Smrg 155848b8605Smrg 156848b8605Smrg/* 157848b8605Smrg * Return 1 / solve_plane(). 158848b8605Smrg */ 159848b8605Smrgstatic inline GLfloat 160848b8605Smrgsolve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) 161848b8605Smrg{ 162848b8605Smrg const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; 163b8e80941Smrg if (denom == 0.0F) 164b8e80941Smrg return 0.0F; 165848b8605Smrg else 166848b8605Smrg return -plane[2] / denom; 167848b8605Smrg} 168848b8605Smrg 169848b8605Smrg 170848b8605Smrg/* 171848b8605Smrg * Solve plane and return clamped GLchan value. 172848b8605Smrg */ 173848b8605Smrgstatic inline GLchan 174848b8605Smrgsolve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4]) 175848b8605Smrg{ 176848b8605Smrg const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; 177848b8605Smrg#if CHAN_TYPE == GL_FLOAT 178848b8605Smrg return CLAMP(z, 0.0F, CHAN_MAXF); 179848b8605Smrg#else 180848b8605Smrg if (z < 0) 181848b8605Smrg return 0; 182848b8605Smrg else if (z > CHAN_MAX) 183848b8605Smrg return CHAN_MAX; 184848b8605Smrg return (GLchan) IROUND_POS(z); 185848b8605Smrg#endif 186848b8605Smrg} 187848b8605Smrg 188848b8605Smrg 189848b8605Smrg/* 190848b8605Smrg * Compute mipmap level of detail. 191848b8605Smrg */ 192848b8605Smrgstatic inline GLfloat 193848b8605Smrgcompute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4], 194848b8605Smrg GLfloat invQ, GLfloat width, GLfloat height) 195848b8605Smrg{ 196848b8605Smrg GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width; 197848b8605Smrg GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width; 198848b8605Smrg GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height; 199848b8605Smrg GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height; 200848b8605Smrg GLfloat r1 = dudx * dudx + dudy * dudy; 201848b8605Smrg GLfloat r2 = dvdx * dvdx + dvdy * dvdy; 202848b8605Smrg GLfloat rho2 = r1 + r2; 203848b8605Smrg /* return log base 2 of rho */ 204848b8605Smrg if (rho2 == 0.0F) 205848b8605Smrg return 0.0; 206848b8605Smrg else 207b8e80941Smrg return logf(rho2) * 1.442695f * 0.5f;/* 1.442695 = 1/log(2) */ 208848b8605Smrg} 209848b8605Smrg 210848b8605Smrg 211848b8605Smrg 212848b8605Smrg 213848b8605Smrg/* 214848b8605Smrg * Fill in the samples[] array with the (x,y) subpixel positions of 215848b8605Smrg * xSamples * ySamples sample positions. 216848b8605Smrg * Note that the four corner samples are put into the first four 217848b8605Smrg * positions of the array. This allows us to optimize for the common 218848b8605Smrg * case of all samples being inside the polygon. 219848b8605Smrg */ 220848b8605Smrgstatic void 221848b8605Smrgmake_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2]) 222848b8605Smrg{ 223848b8605Smrg const GLfloat dx = 1.0F / (GLfloat) xSamples; 224848b8605Smrg const GLfloat dy = 1.0F / (GLfloat) ySamples; 225848b8605Smrg GLint x, y; 226848b8605Smrg GLint i; 227848b8605Smrg 228848b8605Smrg i = 4; 229848b8605Smrg for (x = 0; x < xSamples; x++) { 230848b8605Smrg for (y = 0; y < ySamples; y++) { 231848b8605Smrg GLint j; 232848b8605Smrg if (x == 0 && y == 0) { 233848b8605Smrg /* lower left */ 234848b8605Smrg j = 0; 235848b8605Smrg } 236848b8605Smrg else if (x == xSamples - 1 && y == 0) { 237848b8605Smrg /* lower right */ 238848b8605Smrg j = 1; 239848b8605Smrg } 240848b8605Smrg else if (x == 0 && y == ySamples - 1) { 241848b8605Smrg /* upper left */ 242848b8605Smrg j = 2; 243848b8605Smrg } 244848b8605Smrg else if (x == xSamples - 1 && y == ySamples - 1) { 245848b8605Smrg /* upper right */ 246848b8605Smrg j = 3; 247848b8605Smrg } 248848b8605Smrg else { 249848b8605Smrg j = i++; 250848b8605Smrg } 251848b8605Smrg samples[j][0] = x * dx + 0.5F * dx; 252848b8605Smrg samples[j][1] = y * dy + 0.5F * dy; 253848b8605Smrg } 254848b8605Smrg } 255848b8605Smrg} 256848b8605Smrg 257848b8605Smrg 258848b8605Smrg 259848b8605Smrg/* 260848b8605Smrg * Compute how much of the given pixel's area is inside the rectangle 261848b8605Smrg * defined by vertices v0, v1, v2, v3. 262848b8605Smrg * Vertices MUST be specified in counter-clockwise order. 263848b8605Smrg * Return: coverage in [0, 1]. 264848b8605Smrg */ 265848b8605Smrgstatic GLfloat 266848b8605Smrgcompute_coveragef(const struct LineInfo *info, 267848b8605Smrg GLint winx, GLint winy) 268848b8605Smrg{ 269848b8605Smrg static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2]; 270848b8605Smrg static GLboolean haveSamples = GL_FALSE; 271848b8605Smrg const GLfloat x = (GLfloat) winx; 272848b8605Smrg const GLfloat y = (GLfloat) winy; 273848b8605Smrg GLint stop = 4, i; 274848b8605Smrg GLfloat insideCount = SUB_PIXEL * SUB_PIXEL; 275848b8605Smrg 276848b8605Smrg if (!haveSamples) { 277848b8605Smrg make_sample_table(SUB_PIXEL, SUB_PIXEL, samples); 278848b8605Smrg haveSamples = GL_TRUE; 279848b8605Smrg } 280848b8605Smrg 281848b8605Smrg#if 0 /*DEBUG*/ 282848b8605Smrg { 283848b8605Smrg const GLfloat area = dx0 * dy1 - dx1 * dy0; 284848b8605Smrg assert(area >= 0.0); 285848b8605Smrg } 286848b8605Smrg#endif 287848b8605Smrg 288848b8605Smrg for (i = 0; i < stop; i++) { 289848b8605Smrg const GLfloat sx = x + samples[i][0]; 290848b8605Smrg const GLfloat sy = y + samples[i][1]; 291848b8605Smrg const GLfloat fx0 = sx - info->qx0; 292848b8605Smrg const GLfloat fy0 = sy - info->qy0; 293848b8605Smrg const GLfloat fx1 = sx - info->qx1; 294848b8605Smrg const GLfloat fy1 = sy - info->qy1; 295848b8605Smrg const GLfloat fx2 = sx - info->qx2; 296848b8605Smrg const GLfloat fy2 = sy - info->qy2; 297848b8605Smrg const GLfloat fx3 = sx - info->qx3; 298848b8605Smrg const GLfloat fy3 = sy - info->qy3; 299848b8605Smrg /* cross product determines if sample is inside or outside each edge */ 300848b8605Smrg GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0); 301848b8605Smrg GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1); 302848b8605Smrg GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2); 303848b8605Smrg GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3); 304848b8605Smrg /* Check if the sample is exactly on an edge. If so, let cross be a 305848b8605Smrg * positive or negative value depending on the direction of the edge. 306848b8605Smrg */ 307848b8605Smrg if (cross0 == 0.0F) 308848b8605Smrg cross0 = info->ex0 + info->ey0; 309848b8605Smrg if (cross1 == 0.0F) 310848b8605Smrg cross1 = info->ex1 + info->ey1; 311848b8605Smrg if (cross2 == 0.0F) 312848b8605Smrg cross2 = info->ex2 + info->ey2; 313848b8605Smrg if (cross3 == 0.0F) 314848b8605Smrg cross3 = info->ex3 + info->ey3; 315848b8605Smrg if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) { 316848b8605Smrg /* point is outside quadrilateral */ 317848b8605Smrg insideCount -= 1.0F; 318848b8605Smrg stop = SUB_PIXEL * SUB_PIXEL; 319848b8605Smrg } 320848b8605Smrg } 321848b8605Smrg if (stop == 4) 322848b8605Smrg return 1.0F; 323848b8605Smrg else 324848b8605Smrg return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL)); 325848b8605Smrg} 326848b8605Smrg 327848b8605Smrg 328848b8605Smrgtypedef void (*plot_func)(struct gl_context *ctx, struct LineInfo *line, 329848b8605Smrg int ix, int iy); 330848b8605Smrg 331848b8605Smrg 332848b8605Smrg 333848b8605Smrg/* 334848b8605Smrg * Draw an AA line segment (called many times per line when stippling) 335848b8605Smrg */ 336848b8605Smrgstatic void 337848b8605Smrgsegment(struct gl_context *ctx, 338848b8605Smrg struct LineInfo *line, 339848b8605Smrg plot_func plot, 340848b8605Smrg GLfloat t0, GLfloat t1) 341848b8605Smrg{ 342848b8605Smrg const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx; 343848b8605Smrg const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy; 344848b8605Smrg /* compute the actual segment's endpoints */ 345848b8605Smrg const GLfloat x0 = line->x0 + t0 * line->dx; 346848b8605Smrg const GLfloat y0 = line->y0 + t0 * line->dy; 347848b8605Smrg const GLfloat x1 = line->x0 + t1 * line->dx; 348848b8605Smrg const GLfloat y1 = line->y0 + t1 * line->dy; 349848b8605Smrg 350848b8605Smrg /* compute vertices of the line-aligned quadrilateral */ 351848b8605Smrg line->qx0 = x0 - line->yAdj; 352848b8605Smrg line->qy0 = y0 + line->xAdj; 353848b8605Smrg line->qx1 = x0 + line->yAdj; 354848b8605Smrg line->qy1 = y0 - line->xAdj; 355848b8605Smrg line->qx2 = x1 + line->yAdj; 356848b8605Smrg line->qy2 = y1 - line->xAdj; 357848b8605Smrg line->qx3 = x1 - line->yAdj; 358848b8605Smrg line->qy3 = y1 + line->xAdj; 359848b8605Smrg /* compute the quad's edge vectors (for coverage calc) */ 360848b8605Smrg line->ex0 = line->qx1 - line->qx0; 361848b8605Smrg line->ey0 = line->qy1 - line->qy0; 362848b8605Smrg line->ex1 = line->qx2 - line->qx1; 363848b8605Smrg line->ey1 = line->qy2 - line->qy1; 364848b8605Smrg line->ex2 = line->qx3 - line->qx2; 365848b8605Smrg line->ey2 = line->qy3 - line->qy2; 366848b8605Smrg line->ex3 = line->qx0 - line->qx3; 367848b8605Smrg line->ey3 = line->qy0 - line->qy3; 368848b8605Smrg 369848b8605Smrg if (absDx > absDy) { 370848b8605Smrg /* X-major line */ 371848b8605Smrg GLfloat dydx = line->dy / line->dx; 372848b8605Smrg GLfloat xLeft, xRight, yBot, yTop; 373848b8605Smrg GLint ix, ixRight; 374848b8605Smrg if (x0 < x1) { 375848b8605Smrg xLeft = x0 - line->halfWidth; 376848b8605Smrg xRight = x1 + line->halfWidth; 377b8e80941Smrg if (line->dy >= 0.0F) { 378848b8605Smrg yBot = y0 - 3.0F * line->halfWidth; 379848b8605Smrg yTop = y0 + line->halfWidth; 380848b8605Smrg } 381848b8605Smrg else { 382848b8605Smrg yBot = y0 - line->halfWidth; 383848b8605Smrg yTop = y0 + 3.0F * line->halfWidth; 384848b8605Smrg } 385848b8605Smrg } 386848b8605Smrg else { 387848b8605Smrg xLeft = x1 - line->halfWidth; 388848b8605Smrg xRight = x0 + line->halfWidth; 389b8e80941Smrg if (line->dy <= 0.0F) { 390848b8605Smrg yBot = y1 - 3.0F * line->halfWidth; 391848b8605Smrg yTop = y1 + line->halfWidth; 392848b8605Smrg } 393848b8605Smrg else { 394848b8605Smrg yBot = y1 - line->halfWidth; 395848b8605Smrg yTop = y1 + 3.0F * line->halfWidth; 396848b8605Smrg } 397848b8605Smrg } 398848b8605Smrg 399848b8605Smrg /* scan along the line, left-to-right */ 400848b8605Smrg ixRight = (GLint) (xRight + 1.0F); 401848b8605Smrg 402848b8605Smrg /*printf("avg span height: %g\n", yTop - yBot);*/ 403848b8605Smrg for (ix = (GLint) xLeft; ix < ixRight; ix++) { 404848b8605Smrg const GLint iyBot = (GLint) yBot; 405848b8605Smrg const GLint iyTop = (GLint) (yTop + 1.0F); 406848b8605Smrg GLint iy; 407848b8605Smrg /* scan across the line, bottom-to-top */ 408848b8605Smrg for (iy = iyBot; iy < iyTop; iy++) { 409848b8605Smrg (*plot)(ctx, line, ix, iy); 410848b8605Smrg } 411848b8605Smrg yBot += dydx; 412848b8605Smrg yTop += dydx; 413848b8605Smrg } 414848b8605Smrg } 415848b8605Smrg else { 416848b8605Smrg /* Y-major line */ 417848b8605Smrg GLfloat dxdy = line->dx / line->dy; 418848b8605Smrg GLfloat yBot, yTop, xLeft, xRight; 419848b8605Smrg GLint iy, iyTop; 420848b8605Smrg if (y0 < y1) { 421848b8605Smrg yBot = y0 - line->halfWidth; 422848b8605Smrg yTop = y1 + line->halfWidth; 423b8e80941Smrg if (line->dx >= 0.0F) { 424848b8605Smrg xLeft = x0 - 3.0F * line->halfWidth; 425848b8605Smrg xRight = x0 + line->halfWidth; 426848b8605Smrg } 427848b8605Smrg else { 428848b8605Smrg xLeft = x0 - line->halfWidth; 429848b8605Smrg xRight = x0 + 3.0F * line->halfWidth; 430848b8605Smrg } 431848b8605Smrg } 432848b8605Smrg else { 433848b8605Smrg yBot = y1 - line->halfWidth; 434848b8605Smrg yTop = y0 + line->halfWidth; 435b8e80941Smrg if (line->dx <= 0.0F) { 436848b8605Smrg xLeft = x1 - 3.0F * line->halfWidth; 437848b8605Smrg xRight = x1 + line->halfWidth; 438848b8605Smrg } 439848b8605Smrg else { 440848b8605Smrg xLeft = x1 - line->halfWidth; 441848b8605Smrg xRight = x1 + 3.0F * line->halfWidth; 442848b8605Smrg } 443848b8605Smrg } 444848b8605Smrg 445848b8605Smrg /* scan along the line, bottom-to-top */ 446848b8605Smrg iyTop = (GLint) (yTop + 1.0F); 447848b8605Smrg 448848b8605Smrg /*printf("avg span width: %g\n", xRight - xLeft);*/ 449848b8605Smrg for (iy = (GLint) yBot; iy < iyTop; iy++) { 450848b8605Smrg const GLint ixLeft = (GLint) xLeft; 451848b8605Smrg const GLint ixRight = (GLint) (xRight + 1.0F); 452848b8605Smrg GLint ix; 453848b8605Smrg /* scan across the line, left-to-right */ 454848b8605Smrg for (ix = ixLeft; ix < ixRight; ix++) { 455848b8605Smrg (*plot)(ctx, line, ix, iy); 456848b8605Smrg } 457848b8605Smrg xLeft += dxdy; 458848b8605Smrg xRight += dxdy; 459848b8605Smrg } 460848b8605Smrg } 461848b8605Smrg} 462848b8605Smrg 463848b8605Smrg 464848b8605Smrg#define NAME(x) aa_rgba_##x 465848b8605Smrg#define DO_Z 466848b8605Smrg#include "s_aalinetemp.h" 467848b8605Smrg 468848b8605Smrg 469848b8605Smrg#define NAME(x) aa_general_rgba_##x 470848b8605Smrg#define DO_Z 471848b8605Smrg#define DO_ATTRIBS 472848b8605Smrg#include "s_aalinetemp.h" 473848b8605Smrg 474848b8605Smrg 475848b8605Smrg 476848b8605Smrgvoid 477848b8605Smrg_swrast_choose_aa_line_function(struct gl_context *ctx) 478848b8605Smrg{ 479848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 480848b8605Smrg 481b8e80941Smrg assert(ctx->Line.SmoothFlag); 482848b8605Smrg 483848b8605Smrg if (ctx->Texture._EnabledCoordUnits != 0 484848b8605Smrg || _swrast_use_fragment_program(ctx) 485848b8605Smrg || (ctx->Light.Enabled && 486848b8605Smrg ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) 487848b8605Smrg || ctx->Fog.ColorSumEnabled 488848b8605Smrg || swrast->_FogEnabled) { 489848b8605Smrg swrast->Line = aa_general_rgba_line; 490848b8605Smrg } 491848b8605Smrg else { 492848b8605Smrg swrast->Line = aa_rgba_line; 493848b8605Smrg } 494848b8605Smrg} 495