1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26 /* 27 * Antialiased line template. 28 */ 29 30 31 /* 32 * Function to render each fragment in the AA line. 33 * \param ix - integer fragment window X coordiante 34 * \param iy - integer fragment window Y coordiante 35 */ 36 static void 37 NAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy) 38 { 39 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 40 const GLfloat fx = (GLfloat) ix; 41 const GLfloat fy = (GLfloat) iy; 42 const GLfloat coverage = compute_coveragef(line, ix, iy); 43 const GLuint i = line->span.end; 44 45 (void) swrast; 46 47 if (coverage == 0.0) 48 return; 49 50 line->span.end++; 51 line->span.array->coverage[i] = coverage; 52 line->span.array->x[i] = ix; 53 line->span.array->y[i] = iy; 54 55 /* 56 * Compute Z, color, texture coords, fog for the fragment by 57 * solving the plane equations at (ix,iy). 58 */ 59 #ifdef DO_Z 60 line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane); 61 #endif 62 line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane); 63 line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane); 64 line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane); 65 line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane); 66 #if defined(DO_ATTRIBS) 67 ATTRIB_LOOP_BEGIN 68 GLfloat (*attribArray)[4] = line->span.array->attribs[attr]; 69 if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0 70 && !_swrast_use_fragment_program(ctx)) { 71 /* texcoord w/ divide by Q */ 72 const GLuint unit = attr - FRAG_ATTRIB_TEX0; 73 const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]); 74 GLuint c; 75 for (c = 0; c < 3; c++) { 76 attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invQ; 77 } 78 line->span.array->lambda[unit][i] 79 = compute_lambda(line->attrPlane[attr][0], 80 line->attrPlane[attr][1], invQ, 81 line->texWidth[attr], line->texHeight[attr]); 82 } 83 else { 84 /* non-texture attrib */ 85 const GLfloat invW = solve_plane_recip(fx, fy, line->wPlane); 86 GLuint c; 87 for (c = 0; c < 4; c++) { 88 attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invW; 89 } 90 } 91 ATTRIB_LOOP_END 92 #endif 93 94 if (line->span.end == SWRAST_MAX_WIDTH) { 95 _swrast_write_rgba_span(ctx, &(line->span)); 96 line->span.end = 0; /* reset counter */ 97 } 98 } 99 100 101 102 /* 103 * Line setup 104 */ 105 static void 106 NAME(line)(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1) 107 { 108 SWcontext *swrast = SWRAST_CONTEXT(ctx); 109 GLfloat tStart, tEnd; /* segment start, end along line length */ 110 GLboolean inSegment; 111 GLint iLen, i; 112 113 /* Init the LineInfo struct */ 114 struct LineInfo line; 115 line.x0 = v0->attrib[FRAG_ATTRIB_WPOS][0]; 116 line.y0 = v0->attrib[FRAG_ATTRIB_WPOS][1]; 117 line.x1 = v1->attrib[FRAG_ATTRIB_WPOS][0]; 118 line.y1 = v1->attrib[FRAG_ATTRIB_WPOS][1]; 119 line.dx = line.x1 - line.x0; 120 line.dy = line.y1 - line.y0; 121 line.len = SQRTF(line.dx * line.dx + line.dy * line.dy); 122 line.halfWidth = 0.5F * CLAMP(ctx->Line.Width, 123 ctx->Const.MinLineWidthAA, 124 ctx->Const.MaxLineWidthAA); 125 126 if (line.len == 0.0 || IS_INF_OR_NAN(line.len)) 127 return; 128 129 INIT_SPAN(line.span, GL_LINE); 130 line.span.arrayMask = SPAN_XY | SPAN_COVERAGE; 131 line.span.facing = swrast->PointLineFacing; 132 line.xAdj = line.dx / line.len * line.halfWidth; 133 line.yAdj = line.dy / line.len * line.halfWidth; 134 135 #ifdef DO_Z 136 line.span.arrayMask |= SPAN_Z; 137 compute_plane(line.x0, line.y0, line.x1, line.y1, 138 v0->attrib[FRAG_ATTRIB_WPOS][2], v1->attrib[FRAG_ATTRIB_WPOS][2], line.zPlane); 139 #endif 140 line.span.arrayMask |= SPAN_RGBA; 141 if (ctx->Light.ShadeModel == GL_SMOOTH) { 142 compute_plane(line.x0, line.y0, line.x1, line.y1, 143 v0->color[RCOMP], v1->color[RCOMP], line.rPlane); 144 compute_plane(line.x0, line.y0, line.x1, line.y1, 145 v0->color[GCOMP], v1->color[GCOMP], line.gPlane); 146 compute_plane(line.x0, line.y0, line.x1, line.y1, 147 v0->color[BCOMP], v1->color[BCOMP], line.bPlane); 148 compute_plane(line.x0, line.y0, line.x1, line.y1, 149 v0->color[ACOMP], v1->color[ACOMP], line.aPlane); 150 } 151 else { 152 constant_plane(v1->color[RCOMP], line.rPlane); 153 constant_plane(v1->color[GCOMP], line.gPlane); 154 constant_plane(v1->color[BCOMP], line.bPlane); 155 constant_plane(v1->color[ACOMP], line.aPlane); 156 } 157 #if defined(DO_ATTRIBS) 158 { 159 const GLfloat invW0 = v0->attrib[FRAG_ATTRIB_WPOS][3]; 160 const GLfloat invW1 = v1->attrib[FRAG_ATTRIB_WPOS][3]; 161 line.span.arrayMask |= SPAN_LAMBDA; 162 compute_plane(line.x0, line.y0, line.x1, line.y1, invW0, invW1, line.wPlane); 163 ATTRIB_LOOP_BEGIN 164 GLuint c; 165 if (swrast->_InterpMode[attr] == GL_FLAT) { 166 for (c = 0; c < 4; c++) { 167 constant_plane(v1->attrib[attr][c], line.attrPlane[attr][c]); 168 } 169 } 170 else { 171 for (c = 0; c < 4; c++) { 172 const GLfloat a0 = v0->attrib[attr][c] * invW0; 173 const GLfloat a1 = v1->attrib[attr][c] * invW1; 174 compute_plane(line.x0, line.y0, line.x1, line.y1, a0, a1, 175 line.attrPlane[attr][c]); 176 } 177 } 178 line.span.arrayAttribs |= BITFIELD64_BIT(attr); 179 if (attr >= FRAG_ATTRIB_TEX0 && attr < FRAG_ATTRIB_VAR0) { 180 const GLuint u = attr - FRAG_ATTRIB_TEX0; 181 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; 182 const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel]; 183 line.texWidth[attr] = (GLfloat) texImage->Width; 184 line.texHeight[attr] = (GLfloat) texImage->Height; 185 } 186 ATTRIB_LOOP_END 187 } 188 #endif 189 190 tStart = tEnd = 0.0; 191 inSegment = GL_FALSE; 192 iLen = (GLint) line.len; 193 194 if (ctx->Line.StippleFlag) { 195 for (i = 0; i < iLen; i++) { 196 const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf; 197 if ((1 << bit) & ctx->Line.StipplePattern) { 198 /* stipple bit is on */ 199 const GLfloat t = (GLfloat) i / (GLfloat) line.len; 200 if (!inSegment) { 201 /* start new segment */ 202 inSegment = GL_TRUE; 203 tStart = t; 204 } 205 else { 206 /* still in the segment, extend it */ 207 tEnd = t; 208 } 209 } 210 else { 211 /* stipple bit is off */ 212 if (inSegment && (tEnd > tStart)) { 213 /* draw the segment */ 214 segment(ctx, &line, NAME(plot), tStart, tEnd); 215 inSegment = GL_FALSE; 216 } 217 else { 218 /* still between segments, do nothing */ 219 } 220 } 221 swrast->StippleCounter++; 222 } 223 224 if (inSegment) { 225 /* draw the final segment of the line */ 226 segment(ctx, &line, NAME(plot), tStart, 1.0F); 227 } 228 } 229 else { 230 /* non-stippled */ 231 segment(ctx, &line, NAME(plot), 0.0, 1.0); 232 } 233 234 _swrast_write_rgba_span(ctx, &(line.span)); 235 } 236 237 238 239 240 #undef DO_Z 241 #undef DO_ATTRIBS 242 #undef NAME 243