s_aalinetemp.h revision 7117f1b4
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.3
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 */
36static void
37NAME(plot)(GLcontext *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#ifdef DO_INDEX
43   const GLfloat coverage = compute_coveragei(line, ix, iy);
44#else
45   const GLfloat coverage = compute_coveragef(line, ix, iy);
46#endif
47   const GLuint i = line->span.end;
48
49   (void) swrast;
50
51   if (coverage == 0.0)
52      return;
53
54   line->span.end++;
55   line->span.array->coverage[i] = coverage;
56   line->span.array->x[i] = ix;
57   line->span.array->y[i] = iy;
58
59   /*
60    * Compute Z, color, texture coords, fog for the fragment by
61    * solving the plane equations at (ix,iy).
62    */
63#ifdef DO_Z
64   line->span.array->z[i] = (GLuint) solve_plane(fx, fy, line->zPlane);
65#endif
66#ifdef DO_FOG
67   line->span.array->attribs[FRAG_ATTRIB_FOGC][i][0] = solve_plane(fx, fy, line->fPlane);
68#endif
69#ifdef DO_RGBA
70   line->span.array->rgba[i][RCOMP] = solve_plane_chan(fx, fy, line->rPlane);
71   line->span.array->rgba[i][GCOMP] = solve_plane_chan(fx, fy, line->gPlane);
72   line->span.array->rgba[i][BCOMP] = solve_plane_chan(fx, fy, line->bPlane);
73   line->span.array->rgba[i][ACOMP] = solve_plane_chan(fx, fy, line->aPlane);
74#endif
75#ifdef DO_INDEX
76   line->span.array->index[i] = (GLint) solve_plane(fx, fy, line->iPlane);
77#endif
78#ifdef DO_SPEC
79   line->span.array->spec[i][RCOMP] = solve_plane_chan(fx, fy, line->srPlane);
80   line->span.array->spec[i][GCOMP] = solve_plane_chan(fx, fy, line->sgPlane);
81   line->span.array->spec[i][BCOMP] = solve_plane_chan(fx, fy, line->sbPlane);
82#endif
83#if defined(DO_ATTRIBS)
84   ATTRIB_LOOP_BEGIN
85      GLfloat (*attribArray)[4] = line->span.array->attribs[attr];
86      GLfloat invQ;
87      if (ctx->FragmentProgram._Active) {
88         invQ = 1.0F;
89      }
90      else {
91         invQ = solve_plane_recip(fx, fy, line->vPlane[attr]);
92      }
93      attribArray[i][0] = solve_plane(fx, fy, line->sPlane[attr]) * invQ;
94      attribArray[i][1] = solve_plane(fx, fy, line->tPlane[attr]) * invQ;
95      attribArray[i][2] = solve_plane(fx, fy, line->uPlane[attr]) * invQ;
96      if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) {
97         const GLuint unit = attr - FRAG_ATTRIB_TEX0;
98         line->span.array->lambda[unit][i]
99            = compute_lambda(line->sPlane[attr],
100                             line->tPlane[attr], invQ,
101                             line->texWidth[attr], line->texHeight[attr]);
102      }
103   ATTRIB_LOOP_END
104#endif
105
106   if (line->span.end == MAX_WIDTH) {
107#if defined(DO_RGBA)
108      _swrast_write_rgba_span(ctx, &(line->span));
109#else
110      _swrast_write_index_span(ctx, &(line->span));
111#endif
112      line->span.end = 0; /* reset counter */
113   }
114}
115
116
117
118/*
119 * Line setup
120 */
121static void
122NAME(line)(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1)
123{
124   SWcontext *swrast = SWRAST_CONTEXT(ctx);
125   GLfloat tStart, tEnd;   /* segment start, end along line length */
126   GLboolean inSegment;
127   GLint iLen, i;
128
129   /* Init the LineInfo struct */
130   struct LineInfo line;
131   line.x0 = v0->win[0];
132   line.y0 = v0->win[1];
133   line.x1 = v1->win[0];
134   line.y1 = v1->win[1];
135   line.dx = line.x1 - line.x0;
136   line.dy = line.y1 - line.y0;
137   line.len = SQRTF(line.dx * line.dx + line.dy * line.dy);
138   line.halfWidth = 0.5F * ctx->Line._Width;
139
140   if (line.len == 0.0 || IS_INF_OR_NAN(line.len))
141      return;
142
143   INIT_SPAN(line.span, GL_LINE, 0, 0, SPAN_XY | SPAN_COVERAGE);
144   line.span.facing = swrast->PointLineFacing;
145
146   line.xAdj = line.dx / line.len * line.halfWidth;
147   line.yAdj = line.dy / line.len * line.halfWidth;
148
149#ifdef DO_Z
150   line.span.arrayMask |= SPAN_Z;
151   compute_plane(line.x0, line.y0, line.x1, line.y1,
152                 v0->win[2], v1->win[2], line.zPlane);
153#endif
154#ifdef DO_FOG
155   line.span.arrayMask |= SPAN_FOG;
156   compute_plane(line.x0, line.y0, line.x1, line.y1,
157                 v0->attrib[FRAG_ATTRIB_FOGC][0],
158                 v1->attrib[FRAG_ATTRIB_FOGC][0],
159                 line.fPlane);
160#endif
161#ifdef DO_RGBA
162   line.span.arrayMask |= SPAN_RGBA;
163   if (ctx->Light.ShadeModel == GL_SMOOTH) {
164      compute_plane(line.x0, line.y0, line.x1, line.y1,
165                    v0->color[RCOMP], v1->color[RCOMP], line.rPlane);
166      compute_plane(line.x0, line.y0, line.x1, line.y1,
167                    v0->color[GCOMP], v1->color[GCOMP], line.gPlane);
168      compute_plane(line.x0, line.y0, line.x1, line.y1,
169                    v0->color[BCOMP], v1->color[BCOMP], line.bPlane);
170      compute_plane(line.x0, line.y0, line.x1, line.y1,
171                    v0->color[ACOMP], v1->color[ACOMP], line.aPlane);
172   }
173   else {
174      constant_plane(v1->color[RCOMP], line.rPlane);
175      constant_plane(v1->color[GCOMP], line.gPlane);
176      constant_plane(v1->color[BCOMP], line.bPlane);
177      constant_plane(v1->color[ACOMP], line.aPlane);
178   }
179#endif
180#ifdef DO_SPEC
181   line.span.arrayMask |= SPAN_SPEC;
182   if (ctx->Light.ShadeModel == GL_SMOOTH) {
183      compute_plane(line.x0, line.y0, line.x1, line.y1,
184                    v0->specular[RCOMP], v1->specular[RCOMP], line.srPlane);
185      compute_plane(line.x0, line.y0, line.x1, line.y1,
186                    v0->specular[GCOMP], v1->specular[GCOMP], line.sgPlane);
187      compute_plane(line.x0, line.y0, line.x1, line.y1,
188                    v0->specular[BCOMP], v1->specular[BCOMP], line.sbPlane);
189   }
190   else {
191      constant_plane(v1->specular[RCOMP], line.srPlane);
192      constant_plane(v1->specular[GCOMP], line.sgPlane);
193      constant_plane(v1->specular[BCOMP], line.sbPlane);
194   }
195#endif
196#ifdef DO_INDEX
197   line.span.arrayMask |= SPAN_INDEX;
198   if (ctx->Light.ShadeModel == GL_SMOOTH) {
199      compute_plane(line.x0, line.y0, line.x1, line.y1,
200                    v0->index, v1->index, line.iPlane);
201   }
202   else {
203      constant_plane(v1->index, line.iPlane);
204   }
205#endif
206#if defined(DO_ATTRIBS)
207   {
208      const GLfloat invW0 = v0->win[3];
209      const GLfloat invW1 = v1->win[3];
210      line.span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA | SPAN_VARYING);
211      ATTRIB_LOOP_BEGIN
212         const GLfloat s0 = v0->attrib[attr][0] * invW0;
213         const GLfloat s1 = v1->attrib[attr][0] * invW1;
214         const GLfloat t0 = v0->attrib[attr][1] * invW0;
215         const GLfloat t1 = v1->attrib[attr][1] * invW1;
216         const GLfloat r0 = v0->attrib[attr][2] * invW0;
217         const GLfloat r1 = v1->attrib[attr][2] * invW1;
218         const GLfloat q0 = v0->attrib[attr][3] * invW0;
219         const GLfloat q1 = v1->attrib[attr][3] * invW1;
220         compute_plane(line.x0, line.y0, line.x1, line.y1, s0, s1, line.sPlane[attr]);
221         compute_plane(line.x0, line.y0, line.x1, line.y1, t0, t1, line.tPlane[attr]);
222         compute_plane(line.x0, line.y0, line.x1, line.y1, r0, r1, line.uPlane[attr]);
223         compute_plane(line.x0, line.y0, line.x1, line.y1, q0, q1, line.vPlane[attr]);
224         if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) {
225            const GLuint u = attr - FRAG_ATTRIB_TEX0;
226            const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
227            const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
228            line.texWidth[attr]  = (GLfloat) texImage->Width;
229            line.texHeight[attr] = (GLfloat) texImage->Height;
230         }
231      ATTRIB_LOOP_END
232   }
233#endif
234
235   tStart = tEnd = 0.0;
236   inSegment = GL_FALSE;
237   iLen = (GLint) line.len;
238
239   if (ctx->Line.StippleFlag) {
240      for (i = 0; i < iLen; i++) {
241         const GLuint bit = (swrast->StippleCounter / ctx->Line.StippleFactor) & 0xf;
242         if ((1 << bit) & ctx->Line.StipplePattern) {
243            /* stipple bit is on */
244            const GLfloat t = (GLfloat) i / (GLfloat) line.len;
245            if (!inSegment) {
246               /* start new segment */
247               inSegment = GL_TRUE;
248               tStart = t;
249            }
250            else {
251               /* still in the segment, extend it */
252               tEnd = t;
253            }
254         }
255         else {
256            /* stipple bit is off */
257            if (inSegment && (tEnd > tStart)) {
258               /* draw the segment */
259               segment(ctx, &line, NAME(plot), tStart, tEnd);
260               inSegment = GL_FALSE;
261            }
262            else {
263               /* still between segments, do nothing */
264            }
265         }
266         swrast->StippleCounter++;
267      }
268
269      if (inSegment) {
270         /* draw the final segment of the line */
271         segment(ctx, &line, NAME(plot), tStart, 1.0F);
272      }
273   }
274   else {
275      /* non-stippled */
276      segment(ctx, &line, NAME(plot), 0.0, 1.0);
277   }
278
279#if defined(DO_RGBA)
280   _swrast_write_rgba_span(ctx, &(line.span));
281#else
282   _swrast_write_index_span(ctx, &(line.span));
283#endif
284}
285
286
287
288
289#undef DO_Z
290#undef DO_FOG
291#undef DO_RGBA
292#undef DO_INDEX
293#undef DO_SPEC
294#undef DO_ATTRIBS
295#undef NAME
296