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/* 27848b8605Smrg * Antialiased line template. 28848b8605Smrg */ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg/* 32848b8605Smrg * Function to render each fragment in the AA line. 33848b8605Smrg * \param ix - integer fragment window X coordiante 34848b8605Smrg * \param iy - integer fragment window Y coordiante 35848b8605Smrg */ 36848b8605Smrgstatic void 37848b8605SmrgNAME(plot)(struct gl_context *ctx, struct LineInfo *line, int ix, int iy) 38848b8605Smrg{ 39848b8605Smrg const SWcontext *swrast = SWRAST_CONTEXT(ctx); 40848b8605Smrg const GLfloat fx = (GLfloat) ix; 41848b8605Smrg const GLfloat fy = (GLfloat) iy; 42848b8605Smrg const GLfloat coverage = compute_coveragef(line, ix, iy); 43848b8605Smrg const GLuint i = line->span.end; 44848b8605Smrg 45848b8605Smrg (void) swrast; 46848b8605Smrg 47b8e80941Smrg if (coverage == 0.0F) 48848b8605Smrg return; 49848b8605Smrg 50848b8605Smrg line->span.end++; 51848b8605Smrg line->span.array->coverage[i] = coverage; 52848b8605Smrg line->span.array->x[i] = ix; 53848b8605Smrg line->span.array->y[i] = iy; 54848b8605Smrg 55848b8605Smrg /* 56848b8605Smrg * Compute Z, color, texture coords, fog for the fragment by 57848b8605Smrg * solving the plane equations at (ix,iy). 58848b8605Smrg */ 59848b8605Smrg#ifdef DO_Z 60848b8605Smrg line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane); 61848b8605Smrg#endif 62848b8605Smrg line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane); 63848b8605Smrg line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane); 64848b8605Smrg line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane); 65848b8605Smrg line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane); 66848b8605Smrg#if defined(DO_ATTRIBS) 67848b8605Smrg ATTRIB_LOOP_BEGIN 68848b8605Smrg GLfloat (*attribArray)[4] = line->span.array->attribs[attr]; 69848b8605Smrg if (attr >= VARYING_SLOT_TEX0 && attr < VARYING_SLOT_VAR0 70848b8605Smrg && !_swrast_use_fragment_program(ctx)) { 71848b8605Smrg /* texcoord w/ divide by Q */ 72848b8605Smrg const GLuint unit = attr - VARYING_SLOT_TEX0; 73848b8605Smrg const GLfloat invQ = solve_plane_recip(fx, fy, line->attrPlane[attr][3]); 74848b8605Smrg GLuint c; 75848b8605Smrg for (c = 0; c < 3; c++) { 76848b8605Smrg attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invQ; 77848b8605Smrg } 78848b8605Smrg line->span.array->lambda[unit][i] 79848b8605Smrg = compute_lambda(line->attrPlane[attr][0], 80848b8605Smrg line->attrPlane[attr][1], invQ, 81848b8605Smrg line->texWidth[attr], line->texHeight[attr]); 82848b8605Smrg } 83848b8605Smrg else { 84848b8605Smrg /* non-texture attrib */ 85848b8605Smrg const GLfloat invW = solve_plane_recip(fx, fy, line->wPlane); 86848b8605Smrg GLuint c; 87848b8605Smrg for (c = 0; c < 4; c++) { 88848b8605Smrg attribArray[i][c] = solve_plane(fx, fy, line->attrPlane[attr][c]) * invW; 89848b8605Smrg } 90848b8605Smrg } 91848b8605Smrg ATTRIB_LOOP_END 92848b8605Smrg#endif 93848b8605Smrg 94848b8605Smrg if (line->span.end == SWRAST_MAX_WIDTH) { 95848b8605Smrg _swrast_write_rgba_span(ctx, &(line->span)); 96848b8605Smrg line->span.end = 0; /* reset counter */ 97848b8605Smrg } 98848b8605Smrg} 99848b8605Smrg 100848b8605Smrg 101848b8605Smrg 102848b8605Smrg/* 103848b8605Smrg * Line setup 104848b8605Smrg */ 105848b8605Smrgstatic void 106848b8605SmrgNAME(line)(struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1) 107848b8605Smrg{ 108848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 109848b8605Smrg GLfloat tStart, tEnd; /* segment start, end along line length */ 110848b8605Smrg GLboolean inSegment; 111848b8605Smrg GLint iLen, i; 112848b8605Smrg 113848b8605Smrg /* Init the LineInfo struct */ 114848b8605Smrg struct LineInfo line; 115848b8605Smrg line.x0 = v0->attrib[VARYING_SLOT_POS][0]; 116848b8605Smrg line.y0 = v0->attrib[VARYING_SLOT_POS][1]; 117848b8605Smrg line.x1 = v1->attrib[VARYING_SLOT_POS][0]; 118848b8605Smrg line.y1 = v1->attrib[VARYING_SLOT_POS][1]; 119848b8605Smrg line.dx = line.x1 - line.x0; 120848b8605Smrg line.dy = line.y1 - line.y0; 121848b8605Smrg line.len = sqrtf(line.dx * line.dx + line.dy * line.dy); 122848b8605Smrg line.halfWidth = 0.5F * CLAMP(ctx->Line.Width, 123848b8605Smrg ctx->Const.MinLineWidthAA, 124848b8605Smrg ctx->Const.MaxLineWidthAA); 125848b8605Smrg 126b8e80941Smrg if (line.len == 0.0F || IS_INF_OR_NAN(line.len)) 127848b8605Smrg return; 128848b8605Smrg 129848b8605Smrg INIT_SPAN(line.span, GL_LINE); 130848b8605Smrg line.span.arrayMask = SPAN_XY | SPAN_COVERAGE; 131848b8605Smrg line.span.facing = swrast->PointLineFacing; 132848b8605Smrg line.xAdj = line.dx / line.len * line.halfWidth; 133848b8605Smrg line.yAdj = line.dy / line.len * line.halfWidth; 134848b8605Smrg 135848b8605Smrg#ifdef DO_Z 136848b8605Smrg line.span.arrayMask |= SPAN_Z; 137848b8605Smrg compute_plane(line.x0, line.y0, line.x1, line.y1, 138848b8605Smrg v0->attrib[VARYING_SLOT_POS][2], v1->attrib[VARYING_SLOT_POS][2], line.zPlane); 139848b8605Smrg#endif 140848b8605Smrg line.span.arrayMask |= SPAN_RGBA; 141848b8605Smrg if (ctx->Light.ShadeModel == GL_SMOOTH) { 142848b8605Smrg compute_plane(line.x0, line.y0, line.x1, line.y1, 143848b8605Smrg v0->color[RCOMP], v1->color[RCOMP], line.rPlane); 144848b8605Smrg compute_plane(line.x0, line.y0, line.x1, line.y1, 145848b8605Smrg v0->color[GCOMP], v1->color[GCOMP], line.gPlane); 146848b8605Smrg compute_plane(line.x0, line.y0, line.x1, line.y1, 147848b8605Smrg v0->color[BCOMP], v1->color[BCOMP], line.bPlane); 148848b8605Smrg compute_plane(line.x0, line.y0, line.x1, line.y1, 149848b8605Smrg v0->color[ACOMP], v1->color[ACOMP], line.aPlane); 150848b8605Smrg } 151848b8605Smrg else { 152848b8605Smrg constant_plane(v1->color[RCOMP], line.rPlane); 153848b8605Smrg constant_plane(v1->color[GCOMP], line.gPlane); 154848b8605Smrg constant_plane(v1->color[BCOMP], line.bPlane); 155848b8605Smrg constant_plane(v1->color[ACOMP], line.aPlane); 156848b8605Smrg } 157848b8605Smrg#if defined(DO_ATTRIBS) 158848b8605Smrg { 159848b8605Smrg const GLfloat invW0 = v0->attrib[VARYING_SLOT_POS][3]; 160848b8605Smrg const GLfloat invW1 = v1->attrib[VARYING_SLOT_POS][3]; 161848b8605Smrg line.span.arrayMask |= SPAN_LAMBDA; 162848b8605Smrg compute_plane(line.x0, line.y0, line.x1, line.y1, invW0, invW1, line.wPlane); 163848b8605Smrg ATTRIB_LOOP_BEGIN 164848b8605Smrg GLuint c; 165848b8605Smrg if (swrast->_InterpMode[attr] == GL_FLAT) { 166848b8605Smrg for (c = 0; c < 4; c++) { 167848b8605Smrg constant_plane(v1->attrib[attr][c], line.attrPlane[attr][c]); 168848b8605Smrg } 169848b8605Smrg } 170848b8605Smrg else { 171848b8605Smrg for (c = 0; c < 4; c++) { 172848b8605Smrg const GLfloat a0 = v0->attrib[attr][c] * invW0; 173848b8605Smrg const GLfloat a1 = v1->attrib[attr][c] * invW1; 174848b8605Smrg compute_plane(line.x0, line.y0, line.x1, line.y1, a0, a1, 175848b8605Smrg line.attrPlane[attr][c]); 176848b8605Smrg } 177848b8605Smrg } 178848b8605Smrg line.span.arrayAttribs |= BITFIELD64_BIT(attr); 179848b8605Smrg if (attr >= VARYING_SLOT_TEX0 && attr < VARYING_SLOT_VAR0) { 180848b8605Smrg const GLuint u = attr - VARYING_SLOT_TEX0; 181848b8605Smrg const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; 182b8e80941Smrg if (obj) { 183b8e80941Smrg const struct gl_texture_image *texImage = 184b8e80941Smrg _mesa_base_tex_image(obj); 185b8e80941Smrg line.texWidth[attr] = (GLfloat) texImage->Width; 186b8e80941Smrg line.texHeight[attr] = (GLfloat) texImage->Height; 187b8e80941Smrg } 188848b8605Smrg } 189848b8605Smrg ATTRIB_LOOP_END 190848b8605Smrg } 191848b8605Smrg#endif 192848b8605Smrg 193848b8605Smrg tStart = tEnd = 0.0; 194848b8605Smrg inSegment = GL_FALSE; 195848b8605Smrg iLen = (GLint) line.len; 196848b8605Smrg 197848b8605Smrg if (ctx->Line.StippleFlag) { 198848b8605Smrg for (i = 0; i < iLen; i++) { 199848b8605Smrg const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf; 200848b8605Smrg if ((1 << bit) & ctx->Line.StipplePattern) { 201848b8605Smrg /* stipple bit is on */ 202848b8605Smrg const GLfloat t = (GLfloat) i / (GLfloat) line.len; 203848b8605Smrg if (!inSegment) { 204848b8605Smrg /* start new segment */ 205848b8605Smrg inSegment = GL_TRUE; 206848b8605Smrg tStart = t; 207848b8605Smrg } 208848b8605Smrg else { 209848b8605Smrg /* still in the segment, extend it */ 210848b8605Smrg tEnd = t; 211848b8605Smrg } 212848b8605Smrg } 213848b8605Smrg else { 214848b8605Smrg /* stipple bit is off */ 215848b8605Smrg if (inSegment && (tEnd > tStart)) { 216848b8605Smrg /* draw the segment */ 217848b8605Smrg segment(ctx, &line, NAME(plot), tStart, tEnd); 218848b8605Smrg inSegment = GL_FALSE; 219848b8605Smrg } 220848b8605Smrg else { 221848b8605Smrg /* still between segments, do nothing */ 222848b8605Smrg } 223848b8605Smrg } 224848b8605Smrg swrast->StippleCounter++; 225848b8605Smrg } 226848b8605Smrg 227848b8605Smrg if (inSegment) { 228848b8605Smrg /* draw the final segment of the line */ 229848b8605Smrg segment(ctx, &line, NAME(plot), tStart, 1.0F); 230848b8605Smrg } 231848b8605Smrg } 232848b8605Smrg else { 233848b8605Smrg /* non-stippled */ 234848b8605Smrg segment(ctx, &line, NAME(plot), 0.0, 1.0); 235848b8605Smrg } 236848b8605Smrg 237848b8605Smrg _swrast_write_rgba_span(ctx, &(line.span)); 238848b8605Smrg} 239848b8605Smrg 240848b8605Smrg 241848b8605Smrg 242848b8605Smrg 243848b8605Smrg#undef DO_Z 244848b8605Smrg#undef DO_ATTRIBS 245848b8605Smrg#undef NAME 246