Merge branch 'master' into i915-unification
[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_ATTRIBS - if defined, compute texcoords, varying, etc.
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_ATTRIBS)
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,
140 v0->attrib[FRAG_ATTRIB_FOGC][0],
141 v1->attrib[FRAG_ATTRIB_FOGC][0],
142 v2->attrib[FRAG_ATTRIB_FOGC][0],
143 fogPlane);
144 span.arrayMask |= SPAN_FOG;
145 #endif
146 #ifdef DO_RGBA
147 if (ctx->Light.ShadeModel == GL_SMOOTH) {
148 compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane);
149 compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane);
150 compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane);
151 compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane);
152 }
153 else {
154 constant_plane(v2->color[RCOMP], rPlane);
155 constant_plane(v2->color[GCOMP], gPlane);
156 constant_plane(v2->color[BCOMP], bPlane);
157 constant_plane(v2->color[ACOMP], aPlane);
158 }
159 span.arrayMask |= SPAN_RGBA;
160 #endif
161 #ifdef DO_INDEX
162 if (ctx->Light.ShadeModel == GL_SMOOTH) {
163 compute_plane(p0, p1, p2, (GLfloat) v0->index,
164 v1->index, v2->index, iPlane);
165 }
166 else {
167 constant_plane(v2->index, iPlane);
168 }
169 span.arrayMask |= SPAN_INDEX;
170 #endif
171 #ifdef DO_SPEC
172 if (ctx->Light.ShadeModel == GL_SMOOTH) {
173 compute_plane(p0, p1, p2, v0->specular[RCOMP], v1->specular[RCOMP], v2->specular[RCOMP], srPlane);
174 compute_plane(p0, p1, p2, v0->specular[GCOMP], v1->specular[GCOMP], v2->specular[GCOMP], sgPlane);
175 compute_plane(p0, p1, p2, v0->specular[BCOMP], v1->specular[BCOMP], v2->specular[BCOMP], sbPlane);
176 }
177 else {
178 constant_plane(v2->specular[RCOMP], srPlane);
179 constant_plane(v2->specular[GCOMP], sgPlane);
180 constant_plane(v2->specular[BCOMP], sbPlane);
181 }
182 span.arrayMask |= SPAN_SPEC;
183 #endif
184 #if defined(DO_ATTRIBS)
185 {
186 const GLfloat invW0 = v0->win[3];
187 const GLfloat invW1 = v1->win[3];
188 const GLfloat invW2 = v2->win[3];
189 ATTRIB_LOOP_BEGIN
190 const GLfloat s0 = v0->attrib[attr][0] * invW0;
191 const GLfloat s1 = v1->attrib[attr][0] * invW1;
192 const GLfloat s2 = v2->attrib[attr][0] * invW2;
193 const GLfloat t0 = v0->attrib[attr][1] * invW0;
194 const GLfloat t1 = v1->attrib[attr][1] * invW1;
195 const GLfloat t2 = v2->attrib[attr][1] * invW2;
196 const GLfloat r0 = v0->attrib[attr][2] * invW0;
197 const GLfloat r1 = v1->attrib[attr][2] * invW1;
198 const GLfloat r2 = v2->attrib[attr][2] * invW2;
199 const GLfloat q0 = v0->attrib[attr][3] * invW0;
200 const GLfloat q1 = v1->attrib[attr][3] * invW1;
201 const GLfloat q2 = v2->attrib[attr][3] * invW2;
202 compute_plane(p0, p1, p2, s0, s1, s2, sPlane[attr]);
203 compute_plane(p0, p1, p2, t0, t1, t2, tPlane[attr]);
204 compute_plane(p0, p1, p2, r0, r1, r2, uPlane[attr]);
205 compute_plane(p0, p1, p2, q0, q1, q2, vPlane[attr]);
206 if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) {
207 const GLuint u = attr - FRAG_ATTRIB_TEX0;
208 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current;
209 const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel];
210 texWidth[attr] = (GLfloat) texImage->Width;
211 texHeight[attr] = (GLfloat) texImage->Height;
212 }
213 else {
214 texWidth[attr] = texHeight[attr] = 1.0;
215 }
216 ATTRIB_LOOP_END
217 }
218 span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA | SPAN_VARYING);
219 #endif
220
221 /* Begin bottom-to-top scan over the triangle.
222 * The long edge will either be on the left or right side of the
223 * triangle. We always scan from the long edge toward the shorter
224 * edges, stopping when we find that coverage = 0. If the long edge
225 * is on the left we scan left-to-right. Else, we scan right-to-left.
226 */
227 yMin = vMin->win[1];
228 yMax = vMax->win[1];
229 iyMin = (GLint) yMin;
230 iyMax = (GLint) yMax + 1;
231
232 if (ltor) {
233 /* scan left to right */
234 const GLfloat *pMin = vMin->win;
235 const GLfloat *pMid = vMid->win;
236 const GLfloat *pMax = vMax->win;
237 const GLfloat dxdy = majDx / majDy;
238 const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
239 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
240 GLint iy;
241 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
242 GLint ix, startX = (GLint) (x - xAdj);
243 GLuint count;
244 GLfloat coverage = 0.0F;
245
246 /* skip over fragments with zero coverage */
247 while (startX < MAX_WIDTH) {
248 coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
249 if (coverage > 0.0F)
250 break;
251 startX++;
252 }
253
254 /* enter interior of triangle */
255 ix = startX;
256 count = 0;
257 while (coverage > 0.0F) {
258 /* (cx,cy) = center of fragment */
259 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
260 SWspanarrays *array = span.array;
261 #ifdef DO_INDEX
262 array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy);
263 #else
264 array->coverage[count] = coverage;
265 #endif
266 #ifdef DO_Z
267 array->z[count] = (GLuint) solve_plane(cx, cy, zPlane);
268 #endif
269 #ifdef DO_FOG
270 array->attribs[FRAG_ATTRIB_FOGC][count][0] = solve_plane(cx, cy, fogPlane);
271 #endif
272 #ifdef DO_RGBA
273 array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
274 array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
275 array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
276 array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
277 #endif
278 #ifdef DO_INDEX
279 array->index[count] = (GLint) solve_plane(cx, cy, iPlane);
280 #endif
281 #ifdef DO_SPEC
282 array->spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane);
283 array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
284 array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
285 #endif
286 #if defined(DO_ATTRIBS)
287 ATTRIB_LOOP_BEGIN
288 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]);
289 array->attribs[attr][count][0] = solve_plane(cx, cy, sPlane[attr]) * invQ;
290 array->attribs[attr][count][1] = solve_plane(cx, cy, tPlane[attr]) * invQ;
291 array->attribs[attr][count][2] = solve_plane(cx, cy, uPlane[attr]) * invQ;
292 if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) {
293 const GLuint unit = attr - FRAG_ATTRIB_TEX0;
294 array->lambda[unit][count] = compute_lambda(sPlane[attr], tPlane[attr],
295 vPlane[attr], cx, cy, invQ,
296 texWidth[attr], texHeight[attr]);
297 }
298 ATTRIB_LOOP_END
299 #endif
300 ix++;
301 count++;
302 coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
303 }
304
305 if (ix <= startX)
306 continue;
307
308 span.x = startX;
309 span.y = iy;
310 span.end = (GLuint) ix - (GLuint) startX;
311 ASSERT(span.interpMask == 0);
312 #if defined(DO_RGBA)
313 _swrast_write_rgba_span(ctx, &span);
314 #else
315 _swrast_write_index_span(ctx, &span);
316 #endif
317 }
318 }
319 else {
320 /* scan right to left */
321 const GLfloat *pMin = vMin->win;
322 const GLfloat *pMid = vMid->win;
323 const GLfloat *pMax = vMax->win;
324 const GLfloat dxdy = majDx / majDy;
325 const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
326 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy;
327 GLint iy;
328 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) {
329 GLint ix, left, startX = (GLint) (x + xAdj);
330 GLuint count, n;
331 GLfloat coverage = 0.0F;
332
333 /* make sure we're not past the window edge */
334 if (startX >= ctx->DrawBuffer->_Xmax) {
335 startX = ctx->DrawBuffer->_Xmax - 1;
336 }
337
338 /* skip fragments with zero coverage */
339 while (startX >= 0) {
340 coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
341 if (coverage > 0.0F)
342 break;
343 startX--;
344 }
345
346 /* enter interior of triangle */
347 ix = startX;
348 count = 0;
349 while (coverage > 0.0F) {
350 /* (cx,cy) = center of fragment */
351 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
352 SWspanarrays *array = span.array;
353 #ifdef DO_INDEX
354 array->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy);
355 #else
356 array->coverage[ix] = coverage;
357 #endif
358 #ifdef DO_Z
359 array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane);
360 #endif
361 #ifdef DO_FOG
362 array->attribs[FRAG_ATTRIB_FOGC][ix][0] = solve_plane(cx, cy, fogPlane);
363 #endif
364 #ifdef DO_RGBA
365 array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
366 array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
367 array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
368 array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
369 #endif
370 #ifdef DO_INDEX
371 array->index[ix] = (GLint) solve_plane(cx, cy, iPlane);
372 #endif
373 #ifdef DO_SPEC
374 array->spec[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane);
375 array->spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane);
376 array->spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane);
377 #endif
378 #if defined(DO_ATTRIBS)
379 ATTRIB_LOOP_BEGIN
380 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]);
381 array->attribs[attr][ix][0] = solve_plane(cx, cy, sPlane[attr]) * invQ;
382 array->attribs[attr][ix][1] = solve_plane(cx, cy, tPlane[attr]) * invQ;
383 array->attribs[attr][ix][2] = solve_plane(cx, cy, uPlane[attr]) * invQ;
384 if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) {
385 const GLuint unit = attr - FRAG_ATTRIB_TEX0;
386 array->lambda[unit][ix] = compute_lambda(sPlane[attr],
387 tPlane[attr],
388 vPlane[attr],
389 cx, cy, invQ,
390 texWidth[attr],
391 texHeight[attr]);
392 }
393 ATTRIB_LOOP_END
394 #endif
395 ix--;
396 count++;
397 coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
398 }
399
400 if (startX <= ix)
401 continue;
402
403 n = (GLuint) startX - (GLuint) ix;
404
405 left = ix + 1;
406
407 /* shift all values to the left */
408 /* XXX this is temporary */
409 {
410 SWspanarrays *array = span.array;
411 GLint j;
412 for (j = 0; j < (GLint) n; j++) {
413 #ifdef DO_RGBA
414 COPY_CHAN4(array->rgba[j], array->rgba[j + left]);
415 #endif
416 #ifdef DO_SPEC
417 COPY_CHAN4(array->spec[j], array->spec[j + left]);
418 #endif
419 #ifdef DO_INDEX
420 array->index[j] = array->index[j + left];
421 #endif
422 #ifdef DO_Z
423 array->z[j] = array->z[j + left];
424 #endif
425 #ifdef DO_FOG
426 array->attribs[FRAG_ATTRIB_FOGC][j][0]
427 = array->attribs[FRAG_ATTRIB_FOGC][j + left][0];
428 #endif
429 #if defined(DO_ATTRIBS)
430 array->lambda[0][j] = array->lambda[0][j + left];
431 #endif
432 array->coverage[j] = array->coverage[j + left];
433 }
434 }
435 #ifdef DO_ATTRIBS
436 /* shift texcoords, varying */
437 {
438 SWspanarrays *array = span.array;
439 ATTRIB_LOOP_BEGIN
440 GLint j;
441 for (j = 0; j < (GLint) n; j++) {
442 array->attribs[attr][j][0] = array->attribs[attr][j + left][0];
443 array->attribs[attr][j][1] = array->attribs[attr][j + left][1];
444 array->attribs[attr][j][2] = array->attribs[attr][j + left][2];
445 /*array->lambda[unit][j] = array->lambda[unit][j + left];*/
446 }
447 ATTRIB_LOOP_END
448 }
449 #endif
450
451 span.x = left;
452 span.y = iy;
453 span.end = n;
454 ASSERT(span.interpMask == 0);
455 #if defined(DO_RGBA)
456 _swrast_write_rgba_span(ctx, &span);
457 #else
458 _swrast_write_index_span(ctx, &span);
459 #endif
460 }
461 }
462 }
463
464
465 #ifdef DO_Z
466 #undef DO_Z
467 #endif
468
469 #ifdef DO_FOG
470 #undef DO_FOG
471 #endif
472
473 #ifdef DO_RGBA
474 #undef DO_RGBA
475 #endif
476
477 #ifdef DO_INDEX
478 #undef DO_INDEX
479 #endif
480
481 #ifdef DO_SPEC
482 #undef DO_SPEC
483 #endif
484
485 #ifdef DO_ATTRIBS
486 #undef DO_ATTRIBS
487 #endif
488
489 #ifdef DO_OCCLUSION_TEST
490 #undef DO_OCCLUSION_TEST
491 #endif