17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 47117f1b4Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 57117f1b4Smrg * 67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 87117f1b4Smrg * to deal in the Software without restriction, including without limitation 97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 117117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 127117f1b4Smrg * 137117f1b4Smrg * The above copyright notice and this permission notice shall be included 147117f1b4Smrg * in all copies or substantial portions of the Software. 157117f1b4Smrg * 167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 237117f1b4Smrg */ 247117f1b4Smrg 257117f1b4Smrg 2601e04c3fSmrg#include "c99_math.h" 27c1f859d4Smrg#include "main/glheader.h" 28c1f859d4Smrg#include "main/macros.h" 29c1f859d4Smrg#include "main/mtypes.h" 3001e04c3fSmrg#include "main/teximage.h" 317117f1b4Smrg#include "swrast/s_aaline.h" 327117f1b4Smrg#include "swrast/s_context.h" 337117f1b4Smrg#include "swrast/s_span.h" 347117f1b4Smrg#include "swrast/swrast.h" 357117f1b4Smrg 367117f1b4Smrg 377117f1b4Smrg#define SUB_PIXEL 4 387117f1b4Smrg 397117f1b4Smrg 407117f1b4Smrg/* 417117f1b4Smrg * Info about the AA line we're rendering 427117f1b4Smrg */ 437117f1b4Smrgstruct LineInfo 447117f1b4Smrg{ 457117f1b4Smrg GLfloat x0, y0; /* start */ 467117f1b4Smrg GLfloat x1, y1; /* end */ 477117f1b4Smrg GLfloat dx, dy; /* direction vector */ 487117f1b4Smrg GLfloat len; /* length */ 497117f1b4Smrg GLfloat halfWidth; /* half of line width */ 507117f1b4Smrg GLfloat xAdj, yAdj; /* X and Y adjustment for quad corners around line */ 517117f1b4Smrg /* for coverage computation */ 527117f1b4Smrg GLfloat qx0, qy0; /* quad vertices */ 537117f1b4Smrg GLfloat qx1, qy1; 547117f1b4Smrg GLfloat qx2, qy2; 557117f1b4Smrg GLfloat qx3, qy3; 567117f1b4Smrg GLfloat ex0, ey0; /* quad edge vectors */ 577117f1b4Smrg GLfloat ex1, ey1; 587117f1b4Smrg GLfloat ex2, ey2; 597117f1b4Smrg GLfloat ex3, ey3; 607117f1b4Smrg 617117f1b4Smrg /* DO_Z */ 627117f1b4Smrg GLfloat zPlane[4]; 63cdc920a0Smrg /* DO_RGBA - always enabled */ 647117f1b4Smrg GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; 657117f1b4Smrg /* DO_ATTRIBS */ 66c1f859d4Smrg GLfloat wPlane[4]; 67af69d88dSmrg GLfloat attrPlane[VARYING_SLOT_MAX][4][4]; 68af69d88dSmrg GLfloat lambda[VARYING_SLOT_MAX]; 69af69d88dSmrg GLfloat texWidth[VARYING_SLOT_MAX]; 70af69d88dSmrg GLfloat texHeight[VARYING_SLOT_MAX]; 717117f1b4Smrg 727117f1b4Smrg SWspan span; 737117f1b4Smrg}; 747117f1b4Smrg 757117f1b4Smrg 767117f1b4Smrg 777117f1b4Smrg/* 787117f1b4Smrg * Compute the equation of a plane used to interpolate line fragment data 797117f1b4Smrg * such as color, Z, texture coords, etc. 807117f1b4Smrg * Input: (x0, y0) and (x1,y1) are the endpoints of the line. 817117f1b4Smrg * z0, and z1 are the end point values to interpolate. 827117f1b4Smrg * Output: plane - the plane equation. 837117f1b4Smrg * 847117f1b4Smrg * Note: we don't really have enough parameters to specify a plane. 857117f1b4Smrg * We take the endpoints of the line and compute a plane such that 867117f1b4Smrg * the cross product of the line vector and the plane normal is 877117f1b4Smrg * parallel to the projection plane. 887117f1b4Smrg */ 897117f1b4Smrgstatic void 907117f1b4Smrgcompute_plane(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, 917117f1b4Smrg GLfloat z0, GLfloat z1, GLfloat plane[4]) 927117f1b4Smrg{ 937117f1b4Smrg#if 0 947117f1b4Smrg /* original */ 957117f1b4Smrg const GLfloat px = x1 - x0; 967117f1b4Smrg const GLfloat py = y1 - y0; 977117f1b4Smrg const GLfloat pz = z1 - z0; 987117f1b4Smrg const GLfloat qx = -py; 997117f1b4Smrg const GLfloat qy = px; 1007117f1b4Smrg const GLfloat qz = 0; 1017117f1b4Smrg const GLfloat a = py * qz - pz * qy; 1027117f1b4Smrg const GLfloat b = pz * qx - px * qz; 1037117f1b4Smrg const GLfloat c = px * qy - py * qx; 1047117f1b4Smrg const GLfloat d = -(a * x0 + b * y0 + c * z0); 1057117f1b4Smrg plane[0] = a; 1067117f1b4Smrg plane[1] = b; 1077117f1b4Smrg plane[2] = c; 1087117f1b4Smrg plane[3] = d; 1097117f1b4Smrg#else 1107117f1b4Smrg /* simplified */ 1117117f1b4Smrg const GLfloat px = x1 - x0; 1127117f1b4Smrg const GLfloat py = y1 - y0; 1137117f1b4Smrg const GLfloat pz = z0 - z1; 1147117f1b4Smrg const GLfloat a = pz * px; 1157117f1b4Smrg const GLfloat b = pz * py; 1167117f1b4Smrg const GLfloat c = px * px + py * py; 1177117f1b4Smrg const GLfloat d = -(a * x0 + b * y0 + c * z0); 11801e04c3fSmrg if (a == 0.0F && b == 0.0F && c == 0.0F && d == 0.0F) { 11901e04c3fSmrg plane[0] = 0.0F; 12001e04c3fSmrg plane[1] = 0.0F; 12101e04c3fSmrg plane[2] = 1.0F; 12201e04c3fSmrg plane[3] = 0.0F; 1237117f1b4Smrg } 1247117f1b4Smrg else { 1257117f1b4Smrg plane[0] = a; 1267117f1b4Smrg plane[1] = b; 1277117f1b4Smrg plane[2] = c; 1287117f1b4Smrg plane[3] = d; 1297117f1b4Smrg } 1307117f1b4Smrg#endif 1317117f1b4Smrg} 1327117f1b4Smrg 1337117f1b4Smrg 134af69d88dSmrgstatic inline void 1357117f1b4Smrgconstant_plane(GLfloat value, GLfloat plane[4]) 1367117f1b4Smrg{ 13701e04c3fSmrg plane[0] = 0.0F; 13801e04c3fSmrg plane[1] = 0.0F; 13901e04c3fSmrg plane[2] = -1.0F; 1407117f1b4Smrg plane[3] = value; 1417117f1b4Smrg} 1427117f1b4Smrg 1437117f1b4Smrg 144af69d88dSmrgstatic inline GLfloat 1457117f1b4Smrgsolve_plane(GLfloat x, GLfloat y, const GLfloat plane[4]) 1467117f1b4Smrg{ 1477117f1b4Smrg const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; 1487117f1b4Smrg return z; 1497117f1b4Smrg} 1507117f1b4Smrg 1517117f1b4Smrg#define SOLVE_PLANE(X, Y, PLANE) \ 1527117f1b4Smrg ((PLANE[3] + PLANE[0] * (X) + PLANE[1] * (Y)) / -PLANE[2]) 1537117f1b4Smrg 1547117f1b4Smrg 1557117f1b4Smrg/* 1567117f1b4Smrg * Return 1 / solve_plane(). 1577117f1b4Smrg */ 158af69d88dSmrgstatic inline GLfloat 1597117f1b4Smrgsolve_plane_recip(GLfloat x, GLfloat y, const GLfloat plane[4]) 1607117f1b4Smrg{ 1617117f1b4Smrg const GLfloat denom = plane[3] + plane[0] * x + plane[1] * y; 16201e04c3fSmrg if (denom == 0.0F) 16301e04c3fSmrg return 0.0F; 1647117f1b4Smrg else 1657117f1b4Smrg return -plane[2] / denom; 1667117f1b4Smrg} 1677117f1b4Smrg 1687117f1b4Smrg 1697117f1b4Smrg/* 1707117f1b4Smrg * Solve plane and return clamped GLchan value. 1717117f1b4Smrg */ 172af69d88dSmrgstatic inline GLchan 1737117f1b4Smrgsolve_plane_chan(GLfloat x, GLfloat y, const GLfloat plane[4]) 1747117f1b4Smrg{ 1757117f1b4Smrg const GLfloat z = (plane[3] + plane[0] * x + plane[1] * y) / -plane[2]; 1767117f1b4Smrg#if CHAN_TYPE == GL_FLOAT 1777117f1b4Smrg return CLAMP(z, 0.0F, CHAN_MAXF); 1787117f1b4Smrg#else 1797117f1b4Smrg if (z < 0) 1807117f1b4Smrg return 0; 1817117f1b4Smrg else if (z > CHAN_MAX) 1827117f1b4Smrg return CHAN_MAX; 1837ec681f3Smrg return (GLchan) lroundf(z); 1847117f1b4Smrg#endif 1857117f1b4Smrg} 1867117f1b4Smrg 1877117f1b4Smrg 1887117f1b4Smrg/* 1897117f1b4Smrg * Compute mipmap level of detail. 1907117f1b4Smrg */ 191af69d88dSmrgstatic inline GLfloat 1927117f1b4Smrgcompute_lambda(const GLfloat sPlane[4], const GLfloat tPlane[4], 1937117f1b4Smrg GLfloat invQ, GLfloat width, GLfloat height) 1947117f1b4Smrg{ 1957117f1b4Smrg GLfloat dudx = sPlane[0] / sPlane[2] * invQ * width; 1967117f1b4Smrg GLfloat dudy = sPlane[1] / sPlane[2] * invQ * width; 1977117f1b4Smrg GLfloat dvdx = tPlane[0] / tPlane[2] * invQ * height; 1987117f1b4Smrg GLfloat dvdy = tPlane[1] / tPlane[2] * invQ * height; 1997117f1b4Smrg GLfloat r1 = dudx * dudx + dudy * dudy; 2007117f1b4Smrg GLfloat r2 = dvdx * dvdx + dvdy * dvdy; 2017117f1b4Smrg GLfloat rho2 = r1 + r2; 2027117f1b4Smrg /* return log base 2 of rho */ 2037117f1b4Smrg if (rho2 == 0.0F) 2047117f1b4Smrg return 0.0; 2057117f1b4Smrg else 20601e04c3fSmrg return logf(rho2) * 1.442695f * 0.5f;/* 1.442695 = 1/log(2) */ 2077117f1b4Smrg} 2087117f1b4Smrg 2097117f1b4Smrg 2107117f1b4Smrg 2117117f1b4Smrg 2127117f1b4Smrg/* 2137117f1b4Smrg * Fill in the samples[] array with the (x,y) subpixel positions of 2147117f1b4Smrg * xSamples * ySamples sample positions. 2157117f1b4Smrg * Note that the four corner samples are put into the first four 2167117f1b4Smrg * positions of the array. This allows us to optimize for the common 2177117f1b4Smrg * case of all samples being inside the polygon. 2187117f1b4Smrg */ 2197117f1b4Smrgstatic void 2207117f1b4Smrgmake_sample_table(GLint xSamples, GLint ySamples, GLfloat samples[][2]) 2217117f1b4Smrg{ 2227117f1b4Smrg const GLfloat dx = 1.0F / (GLfloat) xSamples; 2237117f1b4Smrg const GLfloat dy = 1.0F / (GLfloat) ySamples; 2247117f1b4Smrg GLint x, y; 2257117f1b4Smrg GLint i; 2267117f1b4Smrg 2277117f1b4Smrg i = 4; 2287117f1b4Smrg for (x = 0; x < xSamples; x++) { 2297117f1b4Smrg for (y = 0; y < ySamples; y++) { 2307117f1b4Smrg GLint j; 2317117f1b4Smrg if (x == 0 && y == 0) { 2327117f1b4Smrg /* lower left */ 2337117f1b4Smrg j = 0; 2347117f1b4Smrg } 2357117f1b4Smrg else if (x == xSamples - 1 && y == 0) { 2367117f1b4Smrg /* lower right */ 2377117f1b4Smrg j = 1; 2387117f1b4Smrg } 2397117f1b4Smrg else if (x == 0 && y == ySamples - 1) { 2407117f1b4Smrg /* upper left */ 2417117f1b4Smrg j = 2; 2427117f1b4Smrg } 2437117f1b4Smrg else if (x == xSamples - 1 && y == ySamples - 1) { 2447117f1b4Smrg /* upper right */ 2457117f1b4Smrg j = 3; 2467117f1b4Smrg } 2477117f1b4Smrg else { 2487117f1b4Smrg j = i++; 2497117f1b4Smrg } 2507117f1b4Smrg samples[j][0] = x * dx + 0.5F * dx; 2517117f1b4Smrg samples[j][1] = y * dy + 0.5F * dy; 2527117f1b4Smrg } 2537117f1b4Smrg } 2547117f1b4Smrg} 2557117f1b4Smrg 2567117f1b4Smrg 2577117f1b4Smrg 2587117f1b4Smrg/* 2597117f1b4Smrg * Compute how much of the given pixel's area is inside the rectangle 2607117f1b4Smrg * defined by vertices v0, v1, v2, v3. 2617117f1b4Smrg * Vertices MUST be specified in counter-clockwise order. 2627117f1b4Smrg * Return: coverage in [0, 1]. 2637117f1b4Smrg */ 2647117f1b4Smrgstatic GLfloat 2657117f1b4Smrgcompute_coveragef(const struct LineInfo *info, 2667117f1b4Smrg GLint winx, GLint winy) 2677117f1b4Smrg{ 2687117f1b4Smrg static GLfloat samples[SUB_PIXEL * SUB_PIXEL][2]; 2697117f1b4Smrg static GLboolean haveSamples = GL_FALSE; 2707117f1b4Smrg const GLfloat x = (GLfloat) winx; 2717117f1b4Smrg const GLfloat y = (GLfloat) winy; 2727117f1b4Smrg GLint stop = 4, i; 2737117f1b4Smrg GLfloat insideCount = SUB_PIXEL * SUB_PIXEL; 2747117f1b4Smrg 2757117f1b4Smrg if (!haveSamples) { 2767117f1b4Smrg make_sample_table(SUB_PIXEL, SUB_PIXEL, samples); 2777117f1b4Smrg haveSamples = GL_TRUE; 2787117f1b4Smrg } 2797117f1b4Smrg 2807117f1b4Smrg#if 0 /*DEBUG*/ 2817117f1b4Smrg { 2827117f1b4Smrg const GLfloat area = dx0 * dy1 - dx1 * dy0; 2837117f1b4Smrg assert(area >= 0.0); 2847117f1b4Smrg } 2857117f1b4Smrg#endif 2867117f1b4Smrg 2877117f1b4Smrg for (i = 0; i < stop; i++) { 2887117f1b4Smrg const GLfloat sx = x + samples[i][0]; 2897117f1b4Smrg const GLfloat sy = y + samples[i][1]; 2907117f1b4Smrg const GLfloat fx0 = sx - info->qx0; 2917117f1b4Smrg const GLfloat fy0 = sy - info->qy0; 2927117f1b4Smrg const GLfloat fx1 = sx - info->qx1; 2937117f1b4Smrg const GLfloat fy1 = sy - info->qy1; 2947117f1b4Smrg const GLfloat fx2 = sx - info->qx2; 2957117f1b4Smrg const GLfloat fy2 = sy - info->qy2; 2967117f1b4Smrg const GLfloat fx3 = sx - info->qx3; 2977117f1b4Smrg const GLfloat fy3 = sy - info->qy3; 2987117f1b4Smrg /* cross product determines if sample is inside or outside each edge */ 2997117f1b4Smrg GLfloat cross0 = (info->ex0 * fy0 - info->ey0 * fx0); 3007117f1b4Smrg GLfloat cross1 = (info->ex1 * fy1 - info->ey1 * fx1); 3017117f1b4Smrg GLfloat cross2 = (info->ex2 * fy2 - info->ey2 * fx2); 3027117f1b4Smrg GLfloat cross3 = (info->ex3 * fy3 - info->ey3 * fx3); 3037117f1b4Smrg /* Check if the sample is exactly on an edge. If so, let cross be a 3047117f1b4Smrg * positive or negative value depending on the direction of the edge. 3057117f1b4Smrg */ 3067117f1b4Smrg if (cross0 == 0.0F) 3077117f1b4Smrg cross0 = info->ex0 + info->ey0; 3087117f1b4Smrg if (cross1 == 0.0F) 3097117f1b4Smrg cross1 = info->ex1 + info->ey1; 3107117f1b4Smrg if (cross2 == 0.0F) 3117117f1b4Smrg cross2 = info->ex2 + info->ey2; 3127117f1b4Smrg if (cross3 == 0.0F) 3137117f1b4Smrg cross3 = info->ex3 + info->ey3; 3147117f1b4Smrg if (cross0 < 0.0F || cross1 < 0.0F || cross2 < 0.0F || cross3 < 0.0F) { 3157117f1b4Smrg /* point is outside quadrilateral */ 3167117f1b4Smrg insideCount -= 1.0F; 3177117f1b4Smrg stop = SUB_PIXEL * SUB_PIXEL; 3187117f1b4Smrg } 3197117f1b4Smrg } 3207117f1b4Smrg if (stop == 4) 3217117f1b4Smrg return 1.0F; 3227117f1b4Smrg else 3237117f1b4Smrg return insideCount * (1.0F / (SUB_PIXEL * SUB_PIXEL)); 3247117f1b4Smrg} 3257117f1b4Smrg 3267117f1b4Smrg 3273464ebd5Sriastradhtypedef void (*plot_func)(struct gl_context *ctx, struct LineInfo *line, 3287117f1b4Smrg int ix, int iy); 3297ec681f3Smrg 3307117f1b4Smrg 3317117f1b4Smrg 3327117f1b4Smrg/* 3337117f1b4Smrg * Draw an AA line segment (called many times per line when stippling) 3347117f1b4Smrg */ 3357117f1b4Smrgstatic void 3363464ebd5Sriastradhsegment(struct gl_context *ctx, 3377117f1b4Smrg struct LineInfo *line, 3387117f1b4Smrg plot_func plot, 3397117f1b4Smrg GLfloat t0, GLfloat t1) 3407117f1b4Smrg{ 3417117f1b4Smrg const GLfloat absDx = (line->dx < 0.0F) ? -line->dx : line->dx; 3427117f1b4Smrg const GLfloat absDy = (line->dy < 0.0F) ? -line->dy : line->dy; 3437117f1b4Smrg /* compute the actual segment's endpoints */ 3447117f1b4Smrg const GLfloat x0 = line->x0 + t0 * line->dx; 3457117f1b4Smrg const GLfloat y0 = line->y0 + t0 * line->dy; 3467117f1b4Smrg const GLfloat x1 = line->x0 + t1 * line->dx; 3477117f1b4Smrg const GLfloat y1 = line->y0 + t1 * line->dy; 3487117f1b4Smrg 3497117f1b4Smrg /* compute vertices of the line-aligned quadrilateral */ 3507117f1b4Smrg line->qx0 = x0 - line->yAdj; 3517117f1b4Smrg line->qy0 = y0 + line->xAdj; 3527117f1b4Smrg line->qx1 = x0 + line->yAdj; 3537117f1b4Smrg line->qy1 = y0 - line->xAdj; 3547117f1b4Smrg line->qx2 = x1 + line->yAdj; 3557117f1b4Smrg line->qy2 = y1 - line->xAdj; 3567117f1b4Smrg line->qx3 = x1 - line->yAdj; 3577117f1b4Smrg line->qy3 = y1 + line->xAdj; 3587117f1b4Smrg /* compute the quad's edge vectors (for coverage calc) */ 3597117f1b4Smrg line->ex0 = line->qx1 - line->qx0; 3607117f1b4Smrg line->ey0 = line->qy1 - line->qy0; 3617117f1b4Smrg line->ex1 = line->qx2 - line->qx1; 3627117f1b4Smrg line->ey1 = line->qy2 - line->qy1; 3637117f1b4Smrg line->ex2 = line->qx3 - line->qx2; 3647117f1b4Smrg line->ey2 = line->qy3 - line->qy2; 3657117f1b4Smrg line->ex3 = line->qx0 - line->qx3; 3667117f1b4Smrg line->ey3 = line->qy0 - line->qy3; 3677117f1b4Smrg 3687117f1b4Smrg if (absDx > absDy) { 3697117f1b4Smrg /* X-major line */ 3707117f1b4Smrg GLfloat dydx = line->dy / line->dx; 3717117f1b4Smrg GLfloat xLeft, xRight, yBot, yTop; 3727117f1b4Smrg GLint ix, ixRight; 3737117f1b4Smrg if (x0 < x1) { 3747117f1b4Smrg xLeft = x0 - line->halfWidth; 3757117f1b4Smrg xRight = x1 + line->halfWidth; 37601e04c3fSmrg if (line->dy >= 0.0F) { 3777117f1b4Smrg yBot = y0 - 3.0F * line->halfWidth; 3787117f1b4Smrg yTop = y0 + line->halfWidth; 3797117f1b4Smrg } 3807117f1b4Smrg else { 3817117f1b4Smrg yBot = y0 - line->halfWidth; 3827117f1b4Smrg yTop = y0 + 3.0F * line->halfWidth; 3837117f1b4Smrg } 3847117f1b4Smrg } 3857117f1b4Smrg else { 3867117f1b4Smrg xLeft = x1 - line->halfWidth; 3877117f1b4Smrg xRight = x0 + line->halfWidth; 38801e04c3fSmrg if (line->dy <= 0.0F) { 3897117f1b4Smrg yBot = y1 - 3.0F * line->halfWidth; 3907117f1b4Smrg yTop = y1 + line->halfWidth; 3917117f1b4Smrg } 3927117f1b4Smrg else { 3937117f1b4Smrg yBot = y1 - line->halfWidth; 3947117f1b4Smrg yTop = y1 + 3.0F * line->halfWidth; 3957117f1b4Smrg } 3967117f1b4Smrg } 3977117f1b4Smrg 3987117f1b4Smrg /* scan along the line, left-to-right */ 3997117f1b4Smrg ixRight = (GLint) (xRight + 1.0F); 4007117f1b4Smrg 4017117f1b4Smrg /*printf("avg span height: %g\n", yTop - yBot);*/ 4027117f1b4Smrg for (ix = (GLint) xLeft; ix < ixRight; ix++) { 4037117f1b4Smrg const GLint iyBot = (GLint) yBot; 4047117f1b4Smrg const GLint iyTop = (GLint) (yTop + 1.0F); 4057117f1b4Smrg GLint iy; 4067117f1b4Smrg /* scan across the line, bottom-to-top */ 4077117f1b4Smrg for (iy = iyBot; iy < iyTop; iy++) { 4087ec681f3Smrg plot(ctx, line, ix, iy); 4097117f1b4Smrg } 4107117f1b4Smrg yBot += dydx; 4117117f1b4Smrg yTop += dydx; 4127117f1b4Smrg } 4137117f1b4Smrg } 4147117f1b4Smrg else { 4157117f1b4Smrg /* Y-major line */ 4167117f1b4Smrg GLfloat dxdy = line->dx / line->dy; 4177117f1b4Smrg GLfloat yBot, yTop, xLeft, xRight; 4187117f1b4Smrg GLint iy, iyTop; 4197117f1b4Smrg if (y0 < y1) { 4207117f1b4Smrg yBot = y0 - line->halfWidth; 4217117f1b4Smrg yTop = y1 + line->halfWidth; 42201e04c3fSmrg if (line->dx >= 0.0F) { 4237117f1b4Smrg xLeft = x0 - 3.0F * line->halfWidth; 4247117f1b4Smrg xRight = x0 + line->halfWidth; 4257117f1b4Smrg } 4267117f1b4Smrg else { 4277117f1b4Smrg xLeft = x0 - line->halfWidth; 4287117f1b4Smrg xRight = x0 + 3.0F * line->halfWidth; 4297117f1b4Smrg } 4307117f1b4Smrg } 4317117f1b4Smrg else { 4327117f1b4Smrg yBot = y1 - line->halfWidth; 4337117f1b4Smrg yTop = y0 + line->halfWidth; 43401e04c3fSmrg if (line->dx <= 0.0F) { 4357117f1b4Smrg xLeft = x1 - 3.0F * line->halfWidth; 4367117f1b4Smrg xRight = x1 + line->halfWidth; 4377117f1b4Smrg } 4387117f1b4Smrg else { 4397117f1b4Smrg xLeft = x1 - line->halfWidth; 4407117f1b4Smrg xRight = x1 + 3.0F * line->halfWidth; 4417117f1b4Smrg } 4427117f1b4Smrg } 4437117f1b4Smrg 4447117f1b4Smrg /* scan along the line, bottom-to-top */ 4457117f1b4Smrg iyTop = (GLint) (yTop + 1.0F); 4467117f1b4Smrg 4477117f1b4Smrg /*printf("avg span width: %g\n", xRight - xLeft);*/ 4487117f1b4Smrg for (iy = (GLint) yBot; iy < iyTop; iy++) { 4497117f1b4Smrg const GLint ixLeft = (GLint) xLeft; 4507117f1b4Smrg const GLint ixRight = (GLint) (xRight + 1.0F); 4517117f1b4Smrg GLint ix; 4527117f1b4Smrg /* scan across the line, left-to-right */ 4537117f1b4Smrg for (ix = ixLeft; ix < ixRight; ix++) { 4547ec681f3Smrg plot(ctx, line, ix, iy); 4557117f1b4Smrg } 4567117f1b4Smrg xLeft += dxdy; 4577117f1b4Smrg xRight += dxdy; 4587117f1b4Smrg } 4597117f1b4Smrg } 4607117f1b4Smrg} 4617117f1b4Smrg 4627117f1b4Smrg 4637117f1b4Smrg#define NAME(x) aa_rgba_##x 4647117f1b4Smrg#define DO_Z 4657117f1b4Smrg#include "s_aalinetemp.h" 4667117f1b4Smrg 4677117f1b4Smrg 468c1f859d4Smrg#define NAME(x) aa_general_rgba_##x 4697117f1b4Smrg#define DO_Z 4707117f1b4Smrg#define DO_ATTRIBS 4717117f1b4Smrg#include "s_aalinetemp.h" 4727117f1b4Smrg 4737117f1b4Smrg 4747117f1b4Smrg 4757117f1b4Smrgvoid 4763464ebd5Sriastradh_swrast_choose_aa_line_function(struct gl_context *ctx) 4777117f1b4Smrg{ 4787117f1b4Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 4797117f1b4Smrg 48001e04c3fSmrg assert(ctx->Line.SmoothFlag); 4817117f1b4Smrg 482cdc920a0Smrg if (ctx->Texture._EnabledCoordUnits != 0 483af69d88dSmrg || _swrast_use_fragment_program(ctx) 484cdc920a0Smrg || (ctx->Light.Enabled && 485cdc920a0Smrg ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) 486cdc920a0Smrg || ctx->Fog.ColorSumEnabled 487cdc920a0Smrg || swrast->_FogEnabled) { 488cdc920a0Smrg swrast->Line = aa_general_rgba_line; 4897117f1b4Smrg } 4907117f1b4Smrg else { 491cdc920a0Smrg swrast->Line = aa_rgba_line; 4927117f1b4Smrg } 4937117f1b4Smrg} 494