1 /* $Id: s_aatritemp.h,v 1.23 2001/12/17 04:54:35 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
;
54 GLfloat majDx
, majDy
; /* major (i.e. long) edge dx and dy */
64 GLfloat fog
[MAX_WIDTH
];
69 GLfloat rPlane
[4], gPlane
[4], bPlane
[4], aPlane
[4];
73 GLint icoverageSpan
[MAX_WIDTH
];
75 GLfloat coverageSpan
[MAX_WIDTH
];
78 GLfloat srPlane
[4], sgPlane
[4], sbPlane
[4];
81 GLfloat sPlane
[4], tPlane
[4], uPlane
[4], vPlane
[4];
82 GLfloat texWidth
, texHeight
;
83 #elif defined(DO_MULTITEX)
84 GLfloat sPlane
[MAX_TEXTURE_UNITS
][4];
85 GLfloat tPlane
[MAX_TEXTURE_UNITS
][4];
86 GLfloat uPlane
[MAX_TEXTURE_UNITS
][4];
87 GLfloat vPlane
[MAX_TEXTURE_UNITS
][4];
88 GLfloat texWidth
[MAX_TEXTURE_UNITS
], texHeight
[MAX_TEXTURE_UNITS
];
90 GLfloat bf
= SWRAST_CONTEXT(ctx
)->_backface_sign
;
93 /* determine bottom to top order of vertices */
95 GLfloat y0
= v0
->win
[1];
96 GLfloat y1
= v1
->win
[1];
97 GLfloat y2
= v2
->win
[1];
100 vMin
= v0
; vMid
= v1
; vMax
= v2
; /* y0<=y1<=y2 */
103 vMin
= v2
; vMid
= v0
; vMax
= v1
; /* y2<=y0<=y1 */
106 vMin
= v0
; vMid
= v2
; vMax
= v1
; bf
= -bf
; /* y0<=y2<=y1 */
111 vMin
= v1
; vMid
= v0
; vMax
= v2
; bf
= -bf
; /* y1<=y0<=y2 */
114 vMin
= v2
; vMid
= v1
; vMax
= v0
; bf
= -bf
; /* y2<=y1<=y0 */
117 vMin
= v1
; vMid
= v2
; vMax
= v0
; /* y1<=y2<=y0 */
122 majDx
= vMax
->win
[0] - vMin
->win
[0];
123 majDy
= vMax
->win
[1] - vMin
->win
[1];
126 const GLfloat botDx
= vMid
->win
[0] - vMin
->win
[0];
127 const GLfloat botDy
= vMid
->win
[1] - vMin
->win
[1];
128 const GLfloat area
= majDx
* botDy
- botDx
* majDy
;
129 ltor
= (GLboolean
) (area
< 0.0F
);
130 /* Do backface culling */
131 if (area
* bf
< 0 || area
== 0 || IS_INF_OR_NAN(area
))
135 #ifndef DO_OCCLUSION_TEST
136 ctx
->OcclusionResult
= GL_TRUE
;
139 /* Plane equation setup:
140 * We evaluate plane equations at window (x,y) coordinates in order
141 * to compute color, Z, fog, texcoords, etc. This isn't terribly
142 * efficient but it's easy and reliable.
145 compute_plane(p0
, p1
, p2
, p0
[2], p1
[2], p2
[2], zPlane
);
148 compute_plane(p0
, p1
, p2
, v0
->fog
, v1
->fog
, v2
->fog
, fogPlane
);
151 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
152 compute_plane(p0
, p1
, p2
, v0
->color
[0], v1
->color
[0], v2
->color
[0], rPlane
);
153 compute_plane(p0
, p1
, p2
, v0
->color
[1], v1
->color
[1], v2
->color
[1], gPlane
);
154 compute_plane(p0
, p1
, p2
, v0
->color
[2], v1
->color
[2], v2
->color
[2], bPlane
);
155 compute_plane(p0
, p1
, p2
, v0
->color
[3], v1
->color
[3], v2
->color
[3], aPlane
);
158 constant_plane(v2
->color
[RCOMP
], rPlane
);
159 constant_plane(v2
->color
[GCOMP
], gPlane
);
160 constant_plane(v2
->color
[BCOMP
], bPlane
);
161 constant_plane(v2
->color
[ACOMP
], aPlane
);
165 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
166 compute_plane(p0
, p1
, p2
, (GLfloat
) v0
->index
,
167 (GLfloat
) v1
->index
, (GLfloat
) v2
->index
, iPlane
);
170 constant_plane((GLfloat
) v2
->index
, iPlane
);
174 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
175 compute_plane(p0
, p1
, p2
, v0
->specular
[0], v1
->specular
[0], v2
->specular
[0],srPlane
);
176 compute_plane(p0
, p1
, p2
, v0
->specular
[1], v1
->specular
[1], v2
->specular
[1],sgPlane
);
177 compute_plane(p0
, p1
, p2
, v0
->specular
[2], v1
->specular
[2], v2
->specular
[2],sbPlane
);
180 constant_plane(v2
->specular
[RCOMP
], srPlane
);
181 constant_plane(v2
->specular
[GCOMP
], sgPlane
);
182 constant_plane(v2
->specular
[BCOMP
], sbPlane
);
187 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
188 const struct gl_texture_image
*texImage
= obj
->Image
[obj
->BaseLevel
];
189 const GLfloat invW0
= v0
->win
[3];
190 const GLfloat invW1
= v1
->win
[3];
191 const GLfloat invW2
= v2
->win
[3];
192 const GLfloat s0
= v0
->texcoord
[0][0] * invW0
;
193 const GLfloat s1
= v1
->texcoord
[0][0] * invW1
;
194 const GLfloat s2
= v2
->texcoord
[0][0] * invW2
;
195 const GLfloat t0
= v0
->texcoord
[0][1] * invW0
;
196 const GLfloat t1
= v1
->texcoord
[0][1] * invW1
;
197 const GLfloat t2
= v2
->texcoord
[0][1] * invW2
;
198 const GLfloat r0
= v0
->texcoord
[0][2] * invW0
;
199 const GLfloat r1
= v1
->texcoord
[0][2] * invW1
;
200 const GLfloat r2
= v2
->texcoord
[0][2] * invW2
;
201 const GLfloat q0
= v0
->texcoord
[0][3] * invW0
;
202 const GLfloat q1
= v1
->texcoord
[0][3] * invW1
;
203 const GLfloat q2
= v2
->texcoord
[0][3] * invW2
;
204 compute_plane(p0
, p1
, p2
, s0
, s1
, s2
, sPlane
);
205 compute_plane(p0
, p1
, p2
, t0
, t1
, t2
, tPlane
);
206 compute_plane(p0
, p1
, p2
, r0
, r1
, r2
, uPlane
);
207 compute_plane(p0
, p1
, p2
, q0
, q1
, q2
, vPlane
);
208 texWidth
= (GLfloat
) texImage
->Width
;
209 texHeight
= (GLfloat
) texImage
->Height
;
211 #elif defined(DO_MULTITEX)
214 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
215 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
216 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[u
]._Current
;
217 const struct gl_texture_image
*texImage
= obj
->Image
[obj
->BaseLevel
];
218 const GLfloat invW0
= v0
->win
[3];
219 const GLfloat invW1
= v1
->win
[3];
220 const GLfloat invW2
= v2
->win
[3];
221 const GLfloat s0
= v0
->texcoord
[u
][0] * invW0
;
222 const GLfloat s1
= v1
->texcoord
[u
][0] * invW1
;
223 const GLfloat s2
= v2
->texcoord
[u
][0] * invW2
;
224 const GLfloat t0
= v0
->texcoord
[u
][1] * invW0
;
225 const GLfloat t1
= v1
->texcoord
[u
][1] * invW1
;
226 const GLfloat t2
= v2
->texcoord
[u
][1] * invW2
;
227 const GLfloat r0
= v0
->texcoord
[u
][2] * invW0
;
228 const GLfloat r1
= v1
->texcoord
[u
][2] * invW1
;
229 const GLfloat r2
= v2
->texcoord
[u
][2] * invW2
;
230 const GLfloat q0
= v0
->texcoord
[u
][3] * invW0
;
231 const GLfloat q1
= v1
->texcoord
[u
][3] * invW1
;
232 const GLfloat q2
= v2
->texcoord
[u
][3] * invW2
;
233 compute_plane(p0
, p1
, p2
, s0
, s1
, s2
, sPlane
[u
]);
234 compute_plane(p0
, p1
, p2
, t0
, t1
, t2
, tPlane
[u
]);
235 compute_plane(p0
, p1
, p2
, r0
, r1
, r2
, uPlane
[u
]);
236 compute_plane(p0
, p1
, p2
, q0
, q1
, q2
, vPlane
[u
]);
237 texWidth
[u
] = (GLfloat
) texImage
->Width
;
238 texHeight
[u
] = (GLfloat
) texImage
->Height
;
244 /* Begin bottom-to-top scan over the triangle.
245 * The long edge will either be on the left or right side of the
246 * triangle. We always scan from the long edge toward the shorter
247 * edges, stopping when we find that coverage = 0. If the long edge
248 * is on the left we scan left-to-right. Else, we scan right-to-left.
252 iyMin
= (GLint
) yMin
;
253 iyMax
= (GLint
) yMax
+ 1;
256 /* scan left to right */
257 const GLfloat
*pMin
= vMin
->win
;
258 const GLfloat
*pMid
= vMid
->win
;
259 const GLfloat
*pMax
= vMax
->win
;
260 const GLfloat dxdy
= majDx
/ majDy
;
261 const GLfloat xAdj
= dxdy
< 0.0F
? -dxdy
: 0.0F
;
262 GLfloat x
= pMin
[0] - (yMin
- iyMin
) * dxdy
;
264 for (iy
= iyMin
; iy
< iyMax
; iy
++, x
+= dxdy
) {
265 GLint ix
, startX
= (GLint
) (x
- xAdj
);
267 GLfloat coverage
= 0.0F
;
270 /* skip over fragments with zero coverage */
271 while (startX
< MAX_WIDTH
) {
272 coverage
= compute_coveragef(pMin
, pMid
, pMax
, startX
, iy
);
278 /* enter interior of triangle */
281 while (coverage
> 0.0F
) {
282 /* (cx,cy) = center of fragment */
283 const GLfloat cx
= ix
+ 0.5F
, cy
= iy
+ 0.5F
;
285 icoverageSpan
[count
] = compute_coveragei(pMin
, pMid
, pMax
, ix
, iy
);
287 coverageSpan
[count
] = coverage
;
290 z
[count
] = (GLdepth
) solve_plane(cx
, cy
, zPlane
);
293 fog
[count
] = solve_plane(cx
, cy
, fogPlane
);
296 span
.color
.rgba
[count
][RCOMP
] = solve_plane_chan(cx
, cy
, rPlane
);
297 span
.color
.rgba
[count
][GCOMP
] = solve_plane_chan(cx
, cy
, gPlane
);
298 span
.color
.rgba
[count
][BCOMP
] = solve_plane_chan(cx
, cy
, bPlane
);
299 span
.color
.rgba
[count
][ACOMP
] = solve_plane_chan(cx
, cy
, aPlane
);
302 span
.color
.index
[count
] = (GLint
) solve_plane(cx
, cy
, iPlane
);
305 span
.specular
[count
][RCOMP
] = solve_plane_chan(cx
, cy
, srPlane
);
306 span
.specular
[count
][GCOMP
] = solve_plane_chan(cx
, cy
, sgPlane
);
307 span
.specular
[count
][BCOMP
] = solve_plane_chan(cx
, cy
, sbPlane
);
311 const GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
);
312 span
.texcoords
[0][count
][0] = solve_plane(cx
, cy
, sPlane
) * invQ
;
313 span
.texcoords
[0][count
][1] = solve_plane(cx
, cy
, tPlane
) * invQ
;
314 span
.texcoords
[0][count
][2] = solve_plane(cx
, cy
, uPlane
) * invQ
;
315 span
.lambda
[0][count
] = compute_lambda(sPlane
, tPlane
, invQ
,
316 texWidth
, texHeight
);
318 #elif defined(DO_MULTITEX)
321 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
322 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
323 GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
[unit
]);
324 span
.texcoords
[unit
][count
][0] = solve_plane(cx
, cy
, sPlane
[unit
]) * invQ
;
325 span
.texcoords
[unit
][count
][1] = solve_plane(cx
, cy
, tPlane
[unit
]) * invQ
;
326 span
.texcoords
[unit
][count
][2] = solve_plane(cx
, cy
, uPlane
[unit
]) * invQ
;
327 span
.lambda
[unit
][count
] = compute_lambda(sPlane
[unit
],
328 tPlane
[unit
], invQ
, texWidth
[unit
], texHeight
[unit
]);
335 coverage
= compute_coveragef(pMin
, pMid
, pMax
, ix
, iy
);
341 n
= (GLuint
) ix
- (GLuint
) startX
;
345 _old_write_multitexture_span(ctx
, n
, startX
, iy
, z
, fog
,
347 span
.lambda
, span
.color
.rgba
,
349 coverageSpan
, GL_POLYGON
);
351 _old_write_multitexture_span(ctx
, n
, startX
, iy
, z
, fog
,
353 span
.lambda
, span
.color
.rgba
,
357 #elif defined(DO_TEX)
359 _old_write_texture_span(ctx
, n
, startX
, iy
, z
, fog
,
361 span
.lambda
[0], span
.color
.rgba
,
363 coverageSpan
, GL_POLYGON
);
365 _old_write_texture_span(ctx
, n
, startX
, iy
, z
, fog
,
368 span
.color
.rgba
, NULL
,
369 coverageSpan
, GL_POLYGON
);
371 #elif defined(DO_RGBA)
372 _old_write_rgba_span(ctx
, n
, startX
, iy
, z
, fog
, span
.color
.rgba
,
373 coverageSpan
, GL_POLYGON
);
374 #elif defined(DO_INDEX)
375 _old_write_index_span(ctx
, n
, startX
, iy
, z
, fog
, span
.color
.index
,
376 icoverageSpan
, GL_POLYGON
);
381 /* scan right to left */
382 const GLfloat
*pMin
= vMin
->win
;
383 const GLfloat
*pMid
= vMid
->win
;
384 const GLfloat
*pMax
= vMax
->win
;
385 const GLfloat dxdy
= majDx
/ majDy
;
386 const GLfloat xAdj
= dxdy
> 0 ? dxdy
: 0.0F
;
387 GLfloat x
= pMin
[0] - (yMin
- iyMin
) * dxdy
;
389 for (iy
= iyMin
; iy
< iyMax
; iy
++, x
+= dxdy
) {
390 GLint ix
, left
, startX
= (GLint
) (x
+ xAdj
);
392 GLfloat coverage
= 0.0F
;
394 /* make sure we're not past the window edge */
395 if (startX
>= ctx
->DrawBuffer
->_Xmax
) {
396 startX
= ctx
->DrawBuffer
->_Xmax
- 1;
399 /* skip fragments with zero coverage */
400 while (startX
>= 0) {
401 coverage
= compute_coveragef(pMin
, pMax
, pMid
, startX
, iy
);
407 /* enter interior of triangle */
410 while (coverage
> 0.0F
) {
411 /* (cx,cy) = center of fragment */
412 const GLfloat cx
= ix
+ 0.5F
, cy
= iy
+ 0.5F
;
414 icoverageSpan
[ix
] = compute_coveragei(pMin
, pMid
, pMax
, ix
, iy
);
416 coverageSpan
[ix
] = coverage
;
419 z
[ix
] = (GLdepth
) solve_plane(cx
, cy
, zPlane
);
422 fog
[ix
] = solve_plane(cx
, cy
, fogPlane
);
425 span
.color
.rgba
[ix
][RCOMP
] = solve_plane_chan(cx
, cy
, rPlane
);
426 span
.color
.rgba
[ix
][GCOMP
] = solve_plane_chan(cx
, cy
, gPlane
);
427 span
.color
.rgba
[ix
][BCOMP
] = solve_plane_chan(cx
, cy
, bPlane
);
428 span
.color
.rgba
[ix
][ACOMP
] = solve_plane_chan(cx
, cy
, aPlane
);
431 span
.color
.index
[ix
] = (GLint
) solve_plane(cx
, cy
, iPlane
);
434 span
.specular
[ix
][RCOMP
] = solve_plane_chan(cx
, cy
, srPlane
);
435 span
.specular
[ix
][GCOMP
] = solve_plane_chan(cx
, cy
, sgPlane
);
436 span
.specular
[ix
][BCOMP
] = solve_plane_chan(cx
, cy
, sbPlane
);
440 const GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
);
441 span
.texcoords
[0][ix
][0] = solve_plane(cx
, cy
, sPlane
) * invQ
;
442 span
.texcoords
[0][ix
][1] = solve_plane(cx
, cy
, tPlane
) * invQ
;
443 span
.texcoords
[0][ix
][2] = solve_plane(cx
, cy
, uPlane
) * invQ
;
444 span
.lambda
[0][ix
] = compute_lambda(sPlane
, tPlane
, invQ
,
445 texWidth
, texHeight
);
447 #elif defined(DO_MULTITEX)
450 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
451 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
452 GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
[unit
]);
453 span
.texcoords
[unit
][ix
][0] = solve_plane(cx
, cy
, sPlane
[unit
]) * invQ
;
454 span
.texcoords
[unit
][ix
][1] = solve_plane(cx
, cy
, tPlane
[unit
]) * invQ
;
455 span
.texcoords
[unit
][ix
][2] = solve_plane(cx
, cy
, uPlane
[unit
]) * invQ
;
456 span
.lambda
[unit
][ix
] = compute_lambda(sPlane
[unit
],
467 coverage
= compute_coveragef(pMin
, pMax
, pMid
, ix
, iy
);
473 n
= (GLuint
) startX
- (GLuint
) ix
;
479 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
480 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
482 for (j
= 0; j
< (GLint
) n
; j
++) {
483 span
.texcoords
[unit
][j
][0] = span
.texcoords
[unit
][j
+ left
][0];
484 span
.texcoords
[unit
][j
][1] = span
.texcoords
[unit
][j
+ left
][1];
485 span
.texcoords
[unit
][j
][2] = span
.texcoords
[unit
][j
+ left
][2];
486 span
.lambda
[unit
][j
] = span
.lambda
[unit
][j
+ left
];
492 _old_write_multitexture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
493 span
.texcoords
, span
.lambda
,
494 span
.color
.rgba
+ left
,
495 span
.specular
+ left
,
499 _old_write_multitexture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
500 span
.texcoords
, span
.lambda
,
501 span
.color
.rgba
+ left
, NULL
,
505 #elif defined(DO_TEX)
507 _old_write_texture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
508 span
.texcoords
[0] + left
,
509 span
.lambda
[0] + left
,
510 span
.color
.rgba
+ left
,
511 span
.specular
+ left
, coverageSpan
+ left
,
514 _old_write_texture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
515 span
.texcoords
[0] + left
,
516 span
.lambda
[0] + left
,
517 span
.color
.rgba
+ left
, NULL
,
518 coverageSpan
+ left
, GL_POLYGON
);
520 #elif defined(DO_RGBA)
521 _old_write_rgba_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
522 span
.color
.rgba
+ left
, coverageSpan
+ left
, GL_POLYGON
);
523 #elif defined(DO_INDEX)
524 _old_write_index_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
525 span
.color
.index
+ left
,
526 icoverageSpan
+ left
, GL_POLYGON
);
563 #ifdef DO_OCCLUSION_TEST
564 #undef DO_OCCLUSION_TEST