f6c8e68a9b7942118b7e02581834c2ba298fee2d
[mesa.git] / src / mesa / swrast / s_aatritemp.h
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 Triangle Rasterizer Template
28 *
29 * This file is #include'd to generate custom AA triangle rasterizers.
30 * NOTE: this code hasn't been optimized yet. That'll come after it
31 * works correctly.
32 *
33 * The following macros may be defined to indicate what auxillary information
34 * must be copmuted across the triangle:
35 * DO_Z - if defined, compute Z values
36 * DO_RGBA - if defined, compute RGBA values
37 * DO_INDEX - if defined, compute color index values
38 * DO_SPEC - if defined, compute specular RGB values
39 * DO_TEXVAR - if defined, compute texcoords, varying
40 */
41
42 /*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
43 {
44 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
45 const GLfloat *p0 = v0->win;
46 const GLfloat *p1 = v1->win;
47 const GLfloat *p2 = v2->win;
48 const SWvertex *vMin, *vMid, *vMax;
49 GLint iyMin, iyMax;
50 GLfloat yMin, yMax;
51 GLboolean ltor;
52 GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */
53
54 SWspan span;
55
56 #ifdef DO_Z
57 GLfloat zPlane[4];
58 #endif
59 #ifdef DO_FOG
60 GLfloat fogPlane[4];
61 #else
62 GLfloat *fog = NULL;
63 #endif
64 #ifdef DO_RGBA
65 GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
66 #endif
67 #ifdef DO_INDEX
68 GLfloat iPlane[4];
69 #endif
70 #ifdef DO_SPEC
71 GLfloat srPlane[4], sgPlane[4], sbPlane[4];
72 #endif
73 #if defined(DO_TEXVAR)
74 GLfloat sPlane[FRAG_ATTRIB_MAX][4]; /* texture S */
75 GLfloat tPlane[FRAG_ATTRIB_MAX][4]; /* texture T */
76 GLfloat uPlane[FRAG_ATTRIB_MAX][4]; /* texture R */
77 GLfloat vPlane[FRAG_ATTRIB_MAX][4]; /* texture Q */
78 GLfloat texWidth[FRAG_ATTRIB_MAX];
79 GLfloat texHeight[FRAG_ATTRIB_MAX];
80 #endif
81 GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
82
83 (void) swrast;
84
85 INIT_SPAN(span, GL_POLYGON, 0, 0, SPAN_COVERAGE);
86
87 /* determine bottom to top order of vertices */
88 {
89 GLfloat y0 = v0->win[1];
90 GLfloat y1 = v1->win[1];
91 GLfloat y2 = v2->win[1];
92 if (y0 <= y1) {
93 if (y1 <= y2) {
94 vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */
95 }
96 else if (y2 <= y0) {
97 vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */
98 }
99 else {
100 vMin = v0; vMid = v2; vMax = v1; bf = -bf; /* y0<=y2<=y1 */
101 }
102 }
103 else {
104 if (y0 <= y2) {
105 vMin = v1; vMid = v0; vMax = v2; bf = -bf; /* y1<=y0<=y2 */
106 }
107 else if (y2 <= y1) {
108 vMin = v2; vMid = v1; vMax = v0; bf = -bf; /* y2<=y1<=y0 */
109 }
110 else {
111 vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */
112 }
113 }
114 }
115
116 majDx = vMax->win[0] - vMin->win[0];
117 majDy = vMax->win[1] - vMin->win[1];
118
119 {
120 const GLfloat botDx = vMid->win[0] - vMin->win[0];
121 const GLfloat botDy = vMid->win[1] - vMin->win[1];
122 const GLfloat area = majDx * botDy - botDx * majDy;
123 /* Do backface culling */
124 if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area))
125 return;
126 ltor = (GLboolean) (area < 0.0F);
127 }
128
129 /* Plane equation setup:
130 * We evaluate plane equations at window (x,y) coordinates in order
131 * to compute color, Z, fog, texcoords, etc. This isn't terribly
132 * efficient but it's easy and reliable.
133 */
134 #ifdef DO_Z
135 compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
136 span.arrayMask |= SPAN_Z;
137 #endif
138 #ifdef DO_FOG
139 compute_plane(p0, p1, p2, v0->fog, v1->fog, v2->fog, fogPlane);
140 span.arrayMask |= SPAN_FOG;
141 #endif
142 #ifdef DO_RGBA
143 if (ctx->Light.ShadeModel == GL_SMOOTH) {
144 compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane);
145 compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane);
146 compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane);
147 compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane);
148 }
149 else {
150 constant_plane(v2->color[RCOMP], rPlane);
151 constant_plane(v2->color[GCOMP], gPlane);
152 constant_plane(v2->color[BCOMP], bPlane);
153 constant_plane(v2->color[ACOMP], aPlane);
154 }
155 span.arrayMask |= SPAN_RGBA;
156 #endif
157 #ifdef DO_INDEX
158 if (ctx->Light.ShadeModel == GL_SMOOTH) {
159 compute_plane(p0, p1, p2, (GLfloat) v0->index,
160 v1->index, v2->index, iPlane);
161 }
162 else {
163 constant_plane(v2->index, iPlane);
164 }
165 span.arrayMask |= SPAN_INDEX;
166 #endif
167 #ifdef DO_SPEC
168 if (ctx->Light.ShadeModel == GL_SMOOTH) {
169 compute_plane(p0, p1, p2, v0->specular[RCOMP], v1->specular[RCOMP], v2->specular[RCOMP], srPlane);
170 compute_plane(p0, p1, p2, v0->specular[GCOMP], v1->specular[GCOMP], v2->specular[GCOMP], sgPlane);
171 compute_plane(p0, p1, p2, v0->specular[BCOMP], v1->specular[BCOMP], v2->specular[BCOMP], sbPlane);
172 }
173 else {
174 constant_plane(v2->specular[RCOMP], srPlane);
175 constant_plane(v2->specular[GCOMP], sgPlane);
176 constant_plane(v2->specular[BCOMP], sbPlane);
177 }
178 span.arrayMask |= SPAN_SPEC;
179 #endif
180 #if defined(DO_TEXVAR)
181 {
182 const GLfloat invW0 = v0->win[3];
183 const GLfloat invW1 = v1->win[3];
184 const GLfloat invW2 = v2->win[3];
185 ATTRIB_LOOP_BEGIN
186 const GLfloat s0 = v0->attrib[attr][0] * invW0;
187 const GLfloat s1 = v1->attrib[attr][0] * invW1;
188 const GLfloat s2 = v2->attrib[attr][0] * invW2;
189 const GLfloat t0 = v0->attrib[attr][1] * invW0;
190 const GLfloat t1 = v1->attrib[attr][1] * invW1;
191 const GLfloat t2 = v2->attrib[attr][1] * invW2;
192 const GLfloat r0 = v0->attrib[attr][2] * invW0;
193 const GLfloat r1 = v1->attrib[attr][2] * invW1;
194 const GLfloat r2 = v2->attrib[attr][2] * invW2;
195 const GLfloat q0 = v0->attrib[attr][3] * invW0;
196 const GLfloat q1 = v1->attrib[attr][3] * invW1;
197 const GLfloat q2 = v2->attrib[attr][3] * invW2;
198 compute_plane(p0, p1, p2, s0, s1, s2, sPlane[attr]);
199 compute_plane(p0, p1, p2, t0, t1, t2, tPlane[attr]);
200 compute_plane(p0, p1, p2, r0, r1, r2, uPlane[attr]);
201 compute_plane(p0, p1, p2, q0, q1, q2, vPlane[attr]);
202 if (attr < FRAG_ATTRIB_VAR0) {
203 const GLuint u = attr - FRAG_ATTRIB_TEX0;
204 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
205 const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
206 texWidth[attr] = (GLfloat) texImage->Width;
207 texHeight[attr] = (GLfloat) texImage->Height;
208 }
209 else {
210 texWidth[attr] = texHeight[attr] = 1.0;
211 }
212 ATTRIB_LOOP_END
213 }
214 span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA | SPAN_VARYING);
215 #endif
216
217 /* Begin bottom-to-top scan over the triangle.
218 * The long edge will either be on the left or right side of the
219 * triangle. We always scan from the long edge toward the shorter
220 * edges, stopping when we find that coverage = 0. If the long edge
221 * is on the left we scan left-to-right. Else, we scan right-to-left.
222 */
223 yMin = vMin->win[1];
224 yMax = vMax->win[1];
225 iyMin = (GLint) yMin;
226 iyMax = (GLint) yMax + 1;
227
228 if (ltor) {
229 /* scan left to right */
230 const GLfloat *pMin = vMin->win;
231 const GLfloat *pMid = vMid->win;
232 const GLfloat *pMax = vMax->win;
233 const GLfloat dxdy = majDx / majDy;
234 const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
235 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
236 GLint iy;
237 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
238 GLint ix, startX = (GLint) (x - xAdj);
239 GLuint count;
240 GLfloat coverage = 0.0F;
241
242 /* skip over fragments with zero coverage */
243 while (startX < MAX_WIDTH) {
244 coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
245 if (coverage > 0.0F)
246 break;
247 startX++;
248 }
249
250 /* enter interior of triangle */
251 ix = startX;
252 count = 0;
253 while (coverage > 0.0F) {
254 /* (cx,cy) = center of fragment */
255 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
256 SWspanarrays *array = span.array;
257 #ifdef DO_INDEX
258 array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy);
259 #else
260 array->coverage[count] = coverage;
261 #endif
262 #ifdef DO_Z
263 array->z[count] = (GLuint) solve_plane(cx, cy, zPlane);
264 #endif
265 #ifdef DO_FOG
266 array->attribs[FRAG_ATTRIB_FOGC][count][0] = solve_plane(cx, cy, fogPlane);
267 #endif
268 #ifdef DO_RGBA
269 array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
270 array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
271 array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
272 array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
273 #endif
274 #ifdef DO_INDEX
275 array->index[count] = (GLint) solve_plane(cx, cy, iPlane);
276 #endif
277 #ifdef DO_SPEC
278 array->spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane);
279 array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
280 array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
281 #endif
282 #if defined(DO_TEXVAR)
283 ATTRIB_LOOP_BEGIN
284 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]);
285 array->attribs[attr][count][0] = solve_plane(cx, cy, sPlane[attr]) * invQ;
286 array->attribs[attr][count][1] = solve_plane(cx, cy, tPlane[attr]) * invQ;
287 array->attribs[attr][count][2] = solve_plane(cx, cy, uPlane[attr]) * invQ;
288 if (attr < FRAG_ATTRIB_VAR0) {
289 const GLuint unit = attr - FRAG_ATTRIB_TEX0;
290 array->lambda[unit][count] = compute_lambda(sPlane[attr], tPlane[attr],
291 vPlane[attr], cx, cy, invQ,
292 texWidth[attr], texHeight[attr]);
293 }
294 ATTRIB_LOOP_END
295 #endif
296 ix++;
297 count++;
298 coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
299 }
300
301 if (ix <= startX)
302 continue;
303
304 span.x = startX;
305 span.y = iy;
306 span.end = (GLuint) ix - (GLuint) startX;
307 ASSERT(span.interpMask == 0);
308 #if defined(DO_RGBA)
309 _swrast_write_rgba_span(ctx, &span);
310 #else
311 _swrast_write_index_span(ctx, &span);
312 #endif
313 }
314 }
315 else {
316 /* scan right to left */
317 const GLfloat *pMin = vMin->win;
318 const GLfloat *pMid = vMid->win;
319 const GLfloat *pMax = vMax->win;
320 const GLfloat dxdy = majDx / majDy;
321 const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
322 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
323 GLint iy;
324 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
325 GLint ix, left, startX = (GLint) (x + xAdj);
326 GLuint count, n;
327 GLfloat coverage = 0.0F;
328
329 /* make sure we're not past the window edge */
330 if (startX >= ctx->DrawBuffer->_Xmax) {
331 startX = ctx->DrawBuffer->_Xmax - 1;
332 }
333
334 /* skip fragments with zero coverage */
335 while (startX >= 0) {
336 coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
337 if (coverage > 0.0F)
338 break;
339 startX--;
340 }
341
342 /* enter interior of triangle */
343 ix = startX;
344 count = 0;
345 while (coverage > 0.0F) {
346 /* (cx,cy) = center of fragment */
347 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
348 SWspanarrays *array = span.array;
349 #ifdef DO_INDEX
350 array->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy);
351 #else
352 array->coverage[ix] = coverage;
353 #endif
354 #ifdef DO_Z
355 array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane);
356 #endif
357 #ifdef DO_FOG
358 array->attribs[FRAG_ATTRIB_FOGC][ix][0] = solve_plane(cx, cy, fogPlane);
359 #endif
360 #ifdef DO_RGBA
361 array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
362 array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
363 array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
364 array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
365 #endif
366 #ifdef DO_INDEX
367 array->index[ix] = (GLint) solve_plane(cx, cy, iPlane);
368 #endif
369 #ifdef DO_SPEC
370 array->spec[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane);
371 array->spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
372 array->spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
373 #endif
374 #if defined(DO_TEXVAR)
375 ATTRIB_LOOP_BEGIN
376 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]);
377 array->attribs[attr][ix][0] = solve_plane(cx, cy, sPlane[attr]) * invQ;
378 array->attribs[attr][ix][1] = solve_plane(cx, cy, tPlane[attr]) * invQ;
379 array->attribs[attr][ix][2] = solve_plane(cx, cy, uPlane[attr]) * invQ;
380 if (attr < FRAG_ATTRIB_VAR0) {
381 const GLuint unit = attr - FRAG_ATTRIB_TEX0;
382 array->lambda[unit][ix] = compute_lambda(sPlane[attr],
383 tPlane[attr],
384 vPlane[attr],
385 cx, cy, invQ,
386 texWidth[attr],
387 texHeight[attr]);
388 }
389 ATTRIB_LOOP_END
390 #endif
391 ix--;
392 count++;
393 coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
394 }
395
396 if (startX <= ix)
397 continue;
398
399 n = (GLuint) startX - (GLuint) ix;
400
401 left = ix + 1;
402
403 /* shift all values to the left */
404 /* XXX this is temporary */
405 {
406 SWspanarrays *array = span.array;
407 GLint j;
408 for (j = 0; j < (GLint) n; j++) {
409 #ifdef DO_RGBA
410 COPY_CHAN4(array->rgba[j], array->rgba[j + left]);
411 #endif
412 #ifdef DO_SPEC
413 COPY_CHAN4(array->spec[j], array->spec[j + left]);
414 #endif
415 #ifdef DO_INDEX
416 array->index[j] = array->index[j + left];
417 #endif
418 #ifdef DO_Z
419 array->z[j] = array->z[j + left];
420 #endif
421 #ifdef DO_FOG
422 array->attribs[FRAG_ATTRIB_FOGC][j][0]
423 = array->attribs[FRAG_ATTRIB_FOGC][j + left][0];
424 #endif
425 #if defined(DO_TEXVAR)
426 array->lambda[0][j] = array->lambda[0][j + left];
427 #endif
428 array->coverage[j] = array->coverage[j + left];
429 }
430 }
431 #ifdef DO_TEXVAR
432 /* shift texcoords, varying */
433 {
434 SWspanarrays *array = span.array;
435 ATTRIB_LOOP_BEGIN
436 GLint j;
437 for (j = 0; j < (GLint) n; j++) {
438 array->attribs[attr][j][0] = array->attribs[attr][j + left][0];
439 array->attribs[attr][j][1] = array->attribs[attr][j + left][1];
440 array->attribs[attr][j][2] = array->attribs[attr][j + left][2];
441 /*array->lambda[unit][j] = array->lambda[unit][j + left];*/
442 }
443 ATTRIB_LOOP_END
444 }
445 #endif
446
447 span.x = left;
448 span.y = iy;
449 span.end = n;
450 ASSERT(span.interpMask == 0);
451 #if defined(DO_RGBA)
452 _swrast_write_rgba_span(ctx, &span);
453 #else
454 _swrast_write_index_span(ctx, &span);
455 #endif
456 }
457 }
458 }
459
460
461 #ifdef DO_Z
462 #undef DO_Z
463 #endif
464
465 #ifdef DO_FOG
466 #undef DO_FOG
467 #endif
468
469 #ifdef DO_RGBA
470 #undef DO_RGBA
471 #endif
472
473 #ifdef DO_INDEX
474 #undef DO_INDEX
475 #endif
476
477 #ifdef DO_SPEC
478 #undef DO_SPEC
479 #endif
480
481 #ifdef DO_TEXVAR
482 #undef DO_TEXVAR
483 #endif
484
485 #ifdef DO_OCCLUSION_TEST
486 #undef DO_OCCLUSION_TEST
487 #endif