060f7d988fcf6af92811fe96e1a7040ccf3ad939
1 /* $Id: s_aatritemp.h,v 1.19 2001/07/13 20:07:37 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * Antialiased Triangle Rasterizer Template
31 * This file is #include'd to generate custom AA triangle rasterizers.
32 * NOTE: this code hasn't been optimized yet. That'll come after it
35 * The following macros may be defined to indicate what auxillary information
36 * must be copmuted across the triangle:
37 * DO_Z - if defined, compute Z values
38 * DO_RGBA - if defined, compute RGBA values
39 * DO_INDEX - if defined, compute color index values
40 * DO_SPEC - if defined, compute specular RGB values
41 * DO_TEX - if defined, compute unit 0 STRQ texcoords
42 * DO_MULTITEX - if defined, compute all unit's STRQ texcoords
45 /*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
47 const GLfloat
*p0
= v0
->win
;
48 const GLfloat
*p1
= v1
->win
;
49 const GLfloat
*p2
= v2
->win
;
50 const SWvertex
*vMin
, *vMid
, *vMax
;
51 GLfloat xMin
, yMin
, xMid
, yMid
, xMax
, yMax
;
52 GLfloat majDx
, majDy
, botDx
, botDy
, topDx
, topDy
;
54 GLboolean majorOnLeft
;
55 GLfloat bf
= SWRAST_CONTEXT(ctx
)->_backface_sign
;
63 GLfloat fog
[MAX_WIDTH
];
68 GLfloat rPlane
[4], gPlane
[4], bPlane
[4], aPlane
[4];
69 DEFMARRAY(GLchan
, rgba
, MAX_WIDTH
, 4); /* mac 32k limitation */
73 GLuint index
[MAX_WIDTH
];
74 GLint icoverageSpan
[MAX_WIDTH
];
75 GLfloat coverageSpan
[MAX_WIDTH
];
77 GLfloat coverageSpan
[MAX_WIDTH
];
80 GLfloat srPlane
[4], sgPlane
[4], sbPlane
[4];
81 DEFMARRAY(GLchan
, spec
, MAX_WIDTH
, 4);
84 GLfloat sPlane
[4], tPlane
[4], uPlane
[4], vPlane
[4];
85 GLfloat texWidth
, texHeight
;
86 DEFARRAY(GLfloat
, s
, MAX_WIDTH
); /* mac 32k limitation */
87 DEFARRAY(GLfloat
, t
, MAX_WIDTH
);
88 DEFARRAY(GLfloat
, u
, MAX_WIDTH
);
89 DEFARRAY(GLfloat
, lambda
, MAX_WIDTH
);
90 #elif defined(DO_MULTITEX)
91 GLfloat sPlane
[MAX_TEXTURE_UNITS
][4];
92 GLfloat tPlane
[MAX_TEXTURE_UNITS
][4];
93 GLfloat uPlane
[MAX_TEXTURE_UNITS
][4];
94 GLfloat vPlane
[MAX_TEXTURE_UNITS
][4];
95 GLfloat texWidth
[MAX_TEXTURE_UNITS
], texHeight
[MAX_TEXTURE_UNITS
];
96 DEFMARRAY(GLfloat
, s
, MAX_TEXTURE_UNITS
, MAX_WIDTH
); /* mac 32k limit */
97 DEFMARRAY(GLfloat
, t
, MAX_TEXTURE_UNITS
, MAX_WIDTH
);
98 DEFMARRAY(GLfloat
, u
, MAX_TEXTURE_UNITS
, MAX_WIDTH
);
99 DEFMARRAY(GLfloat
, lambda
, MAX_TEXTURE_UNITS
, MAX_WIDTH
);
103 CHECKARRAY(rgba
, return); /* mac 32k limitation */
106 CHECKARRAY(spec
, return);
108 #if defined(DO_TEX) || defined(DO_MULTITEX)
109 CHECKARRAY(s
, return);
110 CHECKARRAY(t
, return);
111 CHECKARRAY(u
, return);
112 CHECKARRAY(lambda
, return);
115 /* determine bottom to top order of vertices */
117 GLfloat y0
= v0
->win
[1];
118 GLfloat y1
= v1
->win
[1];
119 GLfloat y2
= v2
->win
[1];
122 vMin
= v0
; vMid
= v1
; vMax
= v2
; /* y0<=y1<=y2 */
125 vMin
= v2
; vMid
= v0
; vMax
= v1
; /* y2<=y0<=y1 */
128 vMin
= v0
; vMid
= v2
; vMax
= v1
; bf
= -bf
; /* y0<=y2<=y1 */
133 vMin
= v1
; vMid
= v0
; vMax
= v2
; bf
= -bf
; /* y1<=y0<=y2 */
136 vMin
= v2
; vMid
= v1
; vMax
= v0
; bf
= -bf
; /* y2<=y1<=y0 */
139 vMin
= v1
; vMid
= v2
; vMax
= v0
; /* y1<=y2<=y0 */
144 xMin
= vMin
->win
[0]; yMin
= vMin
->win
[1];
145 xMid
= vMid
->win
[0]; yMid
= vMid
->win
[1];
146 xMax
= vMax
->win
[0]; yMax
= vMax
->win
[1];
148 /* the major edge is between the top and bottom vertices */
151 /* the bottom edge is between the bottom and mid vertices */
154 /* the top edge is between the top and mid vertices */
158 /* compute clockwise / counter-clockwise orientation and do BF culling */
159 area
= majDx
* botDy
- botDx
* majDy
;
160 /* Do backface culling */
161 if (area
* bf
< 0 || area
* area
< .0025)
163 majorOnLeft
= (GLboolean
) (area
< 0.0F
);
165 #ifndef DO_OCCLUSION_TEST
166 ctx
->OcclusionResult
= GL_TRUE
;
169 assert(majDy
> 0.0F
);
171 /* Plane equation setup:
172 * We evaluate plane equations at window (x,y) coordinates in order
173 * to compute color, Z, fog, texcoords, etc. This isn't terribly
174 * efficient but it's easy and reliable. It also copes with computing
175 * interpolated data just outside the triangle's edges.
178 compute_plane(p0
, p1
, p2
, p0
[2], p1
[2], p2
[2], zPlane
);
181 compute_plane(p0
, p1
, p2
, v0
->fog
, v1
->fog
, v2
->fog
, fogPlane
);
184 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
185 compute_plane(p0
, p1
, p2
, v0
->color
[0], v1
->color
[0], v2
->color
[0], rPlane
);
186 compute_plane(p0
, p1
, p2
, v0
->color
[1], v1
->color
[1], v2
->color
[1], gPlane
);
187 compute_plane(p0
, p1
, p2
, v0
->color
[2], v1
->color
[2], v2
->color
[2], bPlane
);
188 compute_plane(p0
, p1
, p2
, v0
->color
[3], v1
->color
[3], v2
->color
[3], aPlane
);
191 constant_plane(v2
->color
[RCOMP
], rPlane
);
192 constant_plane(v2
->color
[GCOMP
], gPlane
);
193 constant_plane(v2
->color
[BCOMP
], bPlane
);
194 constant_plane(v2
->color
[ACOMP
], aPlane
);
198 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
199 compute_plane(p0
, p1
, p2
, v0
->index
,
200 v1
->index
, v2
->index
, iPlane
);
203 constant_plane(v2
->index
, iPlane
);
207 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
208 compute_plane(p0
, p1
, p2
, v0
->specular
[0], v1
->specular
[0], v2
->specular
[0],srPlane
);
209 compute_plane(p0
, p1
, p2
, v0
->specular
[1], v1
->specular
[1], v2
->specular
[1],sgPlane
);
210 compute_plane(p0
, p1
, p2
, v0
->specular
[2], v1
->specular
[2], v2
->specular
[2],sbPlane
);
213 constant_plane(v2
->specular
[RCOMP
], srPlane
);
214 constant_plane(v2
->specular
[GCOMP
], sgPlane
);
215 constant_plane(v2
->specular
[BCOMP
], sbPlane
);
220 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
221 const struct gl_texture_image
*texImage
= obj
->Image
[obj
->BaseLevel
];
222 const GLfloat invW0
= v0
->win
[3];
223 const GLfloat invW1
= v1
->win
[3];
224 const GLfloat invW2
= v2
->win
[3];
225 const GLfloat s0
= v0
->texcoord
[0][0] * invW0
;
226 const GLfloat s1
= v1
->texcoord
[0][0] * invW1
;
227 const GLfloat s2
= v2
->texcoord
[0][0] * invW2
;
228 const GLfloat t0
= v0
->texcoord
[0][1] * invW0
;
229 const GLfloat t1
= v1
->texcoord
[0][1] * invW1
;
230 const GLfloat t2
= v2
->texcoord
[0][1] * invW2
;
231 const GLfloat r0
= v0
->texcoord
[0][2] * invW0
;
232 const GLfloat r1
= v1
->texcoord
[0][2] * invW1
;
233 const GLfloat r2
= v2
->texcoord
[0][2] * invW2
;
234 const GLfloat q0
= v0
->texcoord
[0][3] * invW0
;
235 const GLfloat q1
= v1
->texcoord
[0][3] * invW1
;
236 const GLfloat q2
= v2
->texcoord
[0][3] * invW2
;
237 compute_plane(p0
, p1
, p2
, s0
, s1
, s2
, sPlane
);
238 compute_plane(p0
, p1
, p2
, t0
, t1
, t2
, tPlane
);
239 compute_plane(p0
, p1
, p2
, r0
, r1
, r2
, uPlane
);
240 compute_plane(p0
, p1
, p2
, q0
, q1
, q2
, vPlane
);
241 texWidth
= (GLfloat
) texImage
->Width
;
242 texHeight
= (GLfloat
) texImage
->Height
;
244 #elif defined(DO_MULTITEX)
247 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
248 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
249 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[u
]._Current
;
250 const struct gl_texture_image
*texImage
= obj
->Image
[obj
->BaseLevel
];
251 const GLfloat invW0
= v0
->win
[3];
252 const GLfloat invW1
= v1
->win
[3];
253 const GLfloat invW2
= v2
->win
[3];
254 const GLfloat s0
= v0
->texcoord
[u
][0] * invW0
;
255 const GLfloat s1
= v1
->texcoord
[u
][0] * invW1
;
256 const GLfloat s2
= v2
->texcoord
[u
][0] * invW2
;
257 const GLfloat t0
= v0
->texcoord
[u
][1] * invW0
;
258 const GLfloat t1
= v1
->texcoord
[u
][1] * invW1
;
259 const GLfloat t2
= v2
->texcoord
[u
][1] * invW2
;
260 const GLfloat r0
= v0
->texcoord
[u
][2] * invW0
;
261 const GLfloat r1
= v1
->texcoord
[u
][2] * invW1
;
262 const GLfloat r2
= v2
->texcoord
[u
][2] * invW2
;
263 const GLfloat q0
= v0
->texcoord
[u
][3] * invW0
;
264 const GLfloat q1
= v1
->texcoord
[u
][3] * invW1
;
265 const GLfloat q2
= v2
->texcoord
[u
][3] * invW2
;
266 compute_plane(p0
, p1
, p2
, s0
, s1
, s2
, sPlane
[u
]);
267 compute_plane(p0
, p1
, p2
, t0
, t1
, t2
, tPlane
[u
]);
268 compute_plane(p0
, p1
, p2
, r0
, r1
, r2
, uPlane
[u
]);
269 compute_plane(p0
, p1
, p2
, q0
, q1
, q2
, vPlane
[u
]);
270 texWidth
[u
] = (GLfloat
) texImage
->Width
;
271 texHeight
[u
] = (GLfloat
) texImage
->Height
;
277 /* Begin bottom-to-top scan over the triangle.
278 * The long edge will either be on the left or right side of the
279 * triangle. We always scan from the long edge toward the shorter
280 * edges, stopping when we find that coverage = 0. If the long edge
281 * is on the left we scan left-to-right. Else, we scan right-to-left.
284 const GLint iyMin
= (GLint
) yMin
;
285 const GLint iyMax
= (GLint
) yMax
+ 1;
286 /* upper edge and lower edge derivatives */
287 const GLfloat topDxDy
= (topDy
!= 0.0F
) ? topDx
/ topDy
: 0.0F
;
288 const GLfloat botDxDy
= (botDy
!= 0.0F
) ? botDx
/ botDy
: 0.0F
;
289 const GLfloat
*pA
, *pB
, *pC
;
290 const GLfloat majDxDy
= majDx
/ majDy
;
291 const GLfloat absMajDxDy
= FABSF(majDxDy
);
292 const GLfloat absTopDxDy
= FABSF(topDxDy
);
293 const GLfloat absBotDxDy
= FABSF(botDxDy
);
295 GLfloat xMaj
= xMin
- (yMin
- (GLfloat
) iyMin
) * majDxDy
;
297 GLfloat xTop
= xMid
- (yMid
- (GLint
) yMid
) * topDxDy
;
306 /* pA, pB, pC are the vertices in counter-clockwise order */
311 xMaj
= xMin
- absMajDxDy
- 1.0;
312 xBot
= xMin
+ absBotDxDy
+ 1.0;
313 xTop
= xMid
+ absTopDxDy
+ 1.0;
319 xMaj
= xMin
+ absMajDxDy
+ 1.0;
320 xBot
= xMin
- absBotDxDy
- 1.0;
321 xTop
= xMid
- absTopDxDy
- 1.0;
324 /* Scan from bottom to top */
325 for (iy
= iyMin
; iy
< iyMax
; iy
++, xMaj
+= majDxDy
) {
328 GLfloat coverage
= 0.0F
;
331 iLeft
= (GLint
) (xMaj
+ 0.0);
334 /* we're in the lower part */
335 iRight
= (GLint
) (xBot
+ 0.0);
339 /* we're in the upper part */
340 iRight
= (GLint
) (xTop
+ 0.0);
345 iRight
= (GLint
) (xMaj
+ 0.0);
348 /* we're in the lower part */
349 iLeft
= (GLint
) (xBot
- 0.0);
353 /* we're in the upper part */
354 iLeft
= (GLint
) (xTop
- 0.0);
360 for (i
= 0; i
< MAX_WIDTH
; i
++) {
361 coverageSpan
[i
] = -1.0;
367 if (iRight
>= ctx
->DrawBuffer
->_Xmax
)
368 iRight
= ctx
->DrawBuffer
->_Xmax
- 1;
370 /*printf("%d: iLeft = %d iRight = %d\n", iy, iLeft, iRight);*/
372 /* The pixels at y in [iLeft, iRight] (inclusive) are candidates */
374 /* scan left to right until we hit 100% coverage or the right edge */
377 coverage
= compute_coveragef(pA
, pB
, pC
, i
, iy
);
378 if (coverage
== 0.0F
) {
380 iLeft
++; /* skip zero coverage pixels */
384 break; /* went past right edge */
388 coverageSpan
[i
- iLeft
] = coverage
;
389 if (coverage
== 1.0F
)
395 assert(coverageSpan
[i
-iLeft
] > 0.0 || iLeft
== iRight
);
397 assert(i
== iRight
|| coverage
== 1.0 || coverage
== 0.0);
399 /* scan right to left until we hit 100% coverage or the left edge */
401 assert(j
- iLeft
>= 0);
403 coverage
= compute_coveragef(pA
, pB
, pC
, j
, iy
);
404 if (coverage
== 0.0F
) {
405 if (j
== iRight
&& j
> i
)
406 iRight
--; /* skip zero coverage pixels */
413 assert(j
- iLeft
>= 0);
414 coverageSpan
[j
- iLeft
] = coverage
;
415 if (coverage
== 1.0F
)
418 /*printf("%d: coverage[%d]' = %g\n", iy, j-iLeft, coverage);*/
422 assert(coverageSpan
[j
-iLeft
] > 0.0 || iRight
<= iLeft
);
424 printf("iLeft=%d i=%d j=%d iRight=%d\n", iLeft
, i
, j
, iRight
);
427 assert(iLeft
< ctx
->DrawBuffer
->_Xmax
);
429 assert(iRight
< ctx
->DrawBuffer
->_Xmax
);
430 assert(iRight
>= iLeft
);
433 /* any pixels left in between must have 100% coverage */
436 coverageSpan
[k
- iLeft
] = 1.0F
;
440 len
= iRight
- iLeft
;
441 /*printf("len = %d\n", len);*/
443 assert(len
< MAX_WIDTH
);
449 for (k
= 0; k
< len
; k
++) {
450 assert(coverageSpan
[k
] > 0.0);
455 * Compute color, texcoords, etc for the span
458 const GLfloat cx
= iLeft
+ 0.5F
, cy
= iy
+ 0.5F
;
460 GLfloat zFrag
= solve_plane(cx
, cy
, zPlane
);
461 const GLfloat zStep
= -zPlane
[0] / zPlane
[2];
464 GLfloat fogFrag
= solve_plane(cx
, cy
, fogPlane
);
465 const GLfloat fogStep
= -fogPlane
[0] / fogPlane
[2];
477 GLfloat sFrag
= solve_plane(cx
, cy
, sPlane
);
478 GLfloat tFrag
= solve_plane(cx
, cy
, tPlane
);
479 GLfloat uFrag
= solve_plane(cx
, cy
, uPlane
);
480 GLfloat vFrag
= solve_plane(cx
, cy
, vPlane
);
481 const GLfloat sStep
= -sPlane
[0] / sPlane
[2];
482 const GLfloat tStep
= -tPlane
[0] / tPlane
[2];
483 const GLfloat uStep
= -uPlane
[0] / uPlane
[2];
484 const GLfloat vStep
= -vPlane
[0] / vPlane
[2];
485 #elif defined(DO_MULTITEX)
489 for (ix
= iLeft
; ix
< iRight
; ix
++) {
490 const GLint k
= ix
- iLeft
;
491 const GLfloat cx
= ix
+ 0.5F
, cy
= iy
+ 0.5F
;
494 z
[k
] = zFrag
; zFrag
+= zStep
;
497 fog
[k
] = fogFrag
; fogFrag
+= fogStep
;
500 rgba
[k
][RCOMP
] = solve_plane_chan(cx
, cy
, rPlane
);
501 rgba
[k
][GCOMP
] = solve_plane_chan(cx
, cy
, gPlane
);
502 rgba
[k
][BCOMP
] = solve_plane_chan(cx
, cy
, bPlane
);
503 rgba
[k
][ACOMP
] = solve_plane_chan(cx
, cy
, aPlane
);
506 index
[k
] = (GLint
) solve_plane(cx
, cy
, iPlane
);
509 spec
[k
][RCOMP
] = solve_plane_chan(cx
, cy
, srPlane
);
510 spec
[k
][GCOMP
] = solve_plane_chan(cx
, cy
, sgPlane
);
511 spec
[k
][BCOMP
] = solve_plane_chan(cx
, cy
, sbPlane
);
514 s
[k
] = sFrag
/ vFrag
;
515 t
[k
] = tFrag
/ vFrag
;
516 u
[k
] = uFrag
/ vFrag
;
517 lambda
[k
] = compute_lambda(sPlane
, tPlane
, 1.0F
/ vFrag
,
518 texWidth
, texHeight
);
523 #elif defined(DO_MULTITEX)
526 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
527 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
528 GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
[unit
]);
529 s
[unit
][k
] = solve_plane(cx
, cy
, sPlane
[unit
]) * invQ
;
530 t
[unit
][k
] = solve_plane(cx
, cy
, tPlane
[unit
]) * invQ
;
531 u
[unit
][k
] = solve_plane(cx
, cy
, uPlane
[unit
]) * invQ
;
532 lambda
[unit
][k
] = compute_lambda(sPlane
[unit
],
533 tPlane
[unit
], invQ
, texWidth
[unit
], texHeight
[unit
]);
542 * Write/process the span of fragments.
545 _mesa_write_multitexture_span(ctx
, len
, iLeft
, iy
, z
, fog
,
546 (const GLfloat (*)[MAX_WIDTH
]) s
,
547 (const GLfloat (*)[MAX_WIDTH
]) t
,
548 (const GLfloat (*)[MAX_WIDTH
]) u
,
549 (GLfloat (*)[MAX_WIDTH
]) lambda
,
552 (const GLchan (*)[4]) spec
,
556 coverageSpan
, GL_POLYGON
);
557 #elif defined(DO_TEX)
558 _mesa_write_texture_span(ctx
, len
, iLeft
, iy
, z
, fog
,
559 s
, t
, u
, lambda
, rgba
,
561 (const GLchan (*)[4]) spec
,
565 coverageSpan
, GL_POLYGON
);
566 #elif defined(DO_RGBA)
567 _mesa_write_rgba_span(ctx
, len
, iLeft
, iy
, z
, fog
, rgba
,
568 coverageSpan
, GL_POLYGON
);
569 #elif defined(DO_INDEX)
570 _mesa_write_index_span(ctx
, len
, iLeft
, iy
, z
, fog
, index
,
571 icoverageSpan
, GL_POLYGON
);
579 UNDEFARRAY(rgba
); /* mac 32k limitation */
584 #if defined(DO_TEX) || defined(DO_MULTITEX)
621 #ifdef DO_OCCLUSION_TEST
622 #undef DO_OCCLUSION_TEST