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