1 /* $Id: s_aatritemp.h,v 1.13 2001/05/10 18:01:19 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
;
56 GLfloat zPlane
[4]; /* Z (depth) */
59 GLfloat fog
[MAX_WIDTH
];
62 GLfloat rPlane
[4], gPlane
[4], bPlane
[4], aPlane
[4]; /* color */
63 GLchan rgba
[MAX_WIDTH
][4];
66 GLfloat iPlane
[4]; /* color index */
67 GLuint index
[MAX_WIDTH
];
70 GLfloat srPlane
[4], sgPlane
[4], sbPlane
[4]; /* spec color */
71 GLchan spec
[MAX_WIDTH
][4];
74 GLfloat sPlane
[4], tPlane
[4], uPlane
[4], vPlane
[4];
75 GLfloat texWidth
, texHeight
;
76 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], u
[MAX_WIDTH
];
77 GLfloat lambda
[MAX_WIDTH
];
78 #elif defined(DO_MULTITEX)
79 GLfloat sPlane
[MAX_TEXTURE_UNITS
][4];
80 GLfloat tPlane
[MAX_TEXTURE_UNITS
][4];
81 GLfloat uPlane
[MAX_TEXTURE_UNITS
][4];
82 GLfloat vPlane
[MAX_TEXTURE_UNITS
][4];
83 GLfloat texWidth
[MAX_TEXTURE_UNITS
], texHeight
[MAX_TEXTURE_UNITS
];
84 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
85 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
86 GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
87 GLfloat lambda
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
89 GLfloat bf
= SWRAST_CONTEXT(ctx
)->_backface_sign
;
91 /* determine bottom to top order of vertices */
93 GLfloat y0
= v0
->win
[1];
94 GLfloat y1
= v1
->win
[1];
95 GLfloat y2
= v2
->win
[1];
98 vMin
= v0
; vMid
= v1
; vMax
= v2
; /* y0<=y1<=y2 */
101 vMin
= v2
; vMid
= v0
; vMax
= v1
; /* y2<=y0<=y1 */
104 vMin
= v0
; vMid
= v2
; vMax
= v1
; bf
= -bf
; /* y0<=y2<=y1 */
109 vMin
= v1
; vMid
= v0
; vMax
= v2
; bf
= -bf
; /* y1<=y0<=y2 */
112 vMin
= v2
; vMid
= v1
; vMax
= v0
; bf
= -bf
; /* y2<=y1<=y0 */
115 vMin
= v1
; vMid
= v2
; vMax
= v0
; /* y1<=y2<=y0 */
120 majDx
= vMax
->win
[0] - vMin
->win
[0];
121 majDy
= vMax
->win
[1] - vMin
->win
[1];
124 const GLfloat botDx
= vMid
->win
[0] - vMin
->win
[0];
125 const GLfloat botDy
= vMid
->win
[1] - vMin
->win
[1];
126 const GLfloat area
= majDx
* botDy
- botDx
* majDy
;
127 ltor
= (GLboolean
) (area
< 0.0F
);
128 /* Do backface culling */
129 if (area
* bf
< 0 || area
* area
< .0025)
133 #ifndef DO_OCCLUSION_TEST
134 ctx
->OcclusionResult
= GL_TRUE
;
139 compute_plane(p0
, p1
, p2
, p0
[2], p1
[2], p2
[2], zPlane
);
140 compute_plane(p0
, p1
, p2
,
147 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
148 compute_plane(p0
, p1
, p2
, v0
->color
[0], v1
->color
[0], v2
->color
[0], rPlane
);
149 compute_plane(p0
, p1
, p2
, v0
->color
[1], v1
->color
[1], v2
->color
[1], gPlane
);
150 compute_plane(p0
, p1
, p2
, v0
->color
[2], v1
->color
[2], v2
->color
[2], bPlane
);
151 compute_plane(p0
, p1
, p2
, v0
->color
[3], v1
->color
[3], v2
->color
[3], aPlane
);
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
);
161 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
162 compute_plane(p0
, p1
, p2
, v0
->index
,
163 v1
->index
, v2
->index
, iPlane
);
166 constant_plane(v2
->index
, iPlane
);
170 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
171 compute_plane(p0
, p1
, p2
, v0
->specular
[0], v1
->specular
[0], v2
->specular
[0],srPlane
);
172 compute_plane(p0
, p1
, p2
, v0
->specular
[1], v1
->specular
[1], v2
->specular
[1],sgPlane
);
173 compute_plane(p0
, p1
, p2
, v0
->specular
[2], v1
->specular
[2], v2
->specular
[2],sbPlane
);
177 constant_plane(v2
->specular
[RCOMP
], srPlane
);
178 constant_plane(v2
->specular
[GCOMP
], sgPlane
);
179 constant_plane(v2
->specular
[BCOMP
], sbPlane
);
184 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
185 const struct gl_texture_image
*texImage
= obj
->Image
[obj
->BaseLevel
];
186 const GLfloat invW0
= v0
->win
[3];
187 const GLfloat invW1
= v1
->win
[3];
188 const GLfloat invW2
= v2
->win
[3];
189 const GLfloat s0
= v0
->texcoord
[0][0] * invW0
;
190 const GLfloat s1
= v1
->texcoord
[0][0] * invW1
;
191 const GLfloat s2
= v2
->texcoord
[0][0] * invW2
;
192 const GLfloat t0
= v0
->texcoord
[0][1] * invW0
;
193 const GLfloat t1
= v1
->texcoord
[0][1] * invW1
;
194 const GLfloat t2
= v2
->texcoord
[0][1] * invW2
;
195 const GLfloat r0
= v0
->texcoord
[0][2] * invW0
;
196 const GLfloat r1
= v1
->texcoord
[0][2] * invW1
;
197 const GLfloat r2
= v2
->texcoord
[0][2] * invW2
;
198 const GLfloat q0
= v0
->texcoord
[0][3] * invW0
;
199 const GLfloat q1
= v1
->texcoord
[0][3] * invW1
;
200 const GLfloat q2
= v2
->texcoord
[0][3] * invW2
;
201 compute_plane(p0
, p1
, p2
, s0
, s1
, s2
, sPlane
);
202 compute_plane(p0
, p1
, p2
, t0
, t1
, t2
, tPlane
);
203 compute_plane(p0
, p1
, p2
, r0
, r1
, r2
, uPlane
);
204 compute_plane(p0
, p1
, p2
, q0
, q1
, q2
, vPlane
);
205 texWidth
= (GLfloat
) texImage
->Width
;
206 texHeight
= (GLfloat
) texImage
->Height
;
208 #elif defined(DO_MULTITEX)
211 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
212 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
213 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[u
]._Current
;
214 const struct gl_texture_image
*texImage
= obj
->Image
[obj
->BaseLevel
];
215 const GLfloat invW0
= v0
->win
[3];
216 const GLfloat invW1
= v1
->win
[3];
217 const GLfloat invW2
= v2
->win
[3];
218 const GLfloat s0
= v0
->texcoord
[u
][0] * invW0
;
219 const GLfloat s1
= v1
->texcoord
[u
][0] * invW1
;
220 const GLfloat s2
= v2
->texcoord
[u
][0] * invW2
;
221 const GLfloat t0
= v0
->texcoord
[u
][1] * invW0
;
222 const GLfloat t1
= v1
->texcoord
[u
][1] * invW1
;
223 const GLfloat t2
= v2
->texcoord
[u
][1] * invW2
;
224 const GLfloat r0
= v0
->texcoord
[u
][2] * invW0
;
225 const GLfloat r1
= v1
->texcoord
[u
][2] * invW1
;
226 const GLfloat r2
= v2
->texcoord
[u
][2] * invW2
;
227 const GLfloat q0
= v0
->texcoord
[u
][3] * invW0
;
228 const GLfloat q1
= v1
->texcoord
[u
][3] * invW1
;
229 const GLfloat q2
= v2
->texcoord
[u
][3] * invW2
;
230 compute_plane(p0
, p1
, p2
, s0
, s1
, s2
, sPlane
[u
]);
231 compute_plane(p0
, p1
, p2
, t0
, t1
, t2
, tPlane
[u
]);
232 compute_plane(p0
, p1
, p2
, r0
, r1
, r2
, uPlane
[u
]);
233 compute_plane(p0
, p1
, p2
, q0
, q1
, q2
, vPlane
[u
]);
234 texWidth
[u
] = (GLfloat
) texImage
->Width
;
235 texHeight
[u
] = (GLfloat
) texImage
->Height
;
244 iyMax
= (int) yMax
+ 1;
247 /* scan left to right */
248 const float *pMin
= vMin
->win
;
249 const float *pMid
= vMid
->win
;
250 const float *pMax
= vMax
->win
;
251 const float dxdy
= majDx
/ majDy
;
252 const float xAdj
= dxdy
< 0.0F
? -dxdy
: 0.0F
;
253 float x
= vMin
->win
[0] - (yMin
- iyMin
) * dxdy
;
255 for (iy
= iyMin
; iy
< iyMax
; iy
++, x
+= dxdy
) {
256 GLint ix
, startX
= (GLint
) (x
- xAdj
);
258 GLfloat coverage
= 0.0F
;
259 /* skip over fragments with zero coverage */
260 while (startX
< MAX_WIDTH
) {
261 coverage
= compute_coveragef(pMin
, pMid
, pMax
, startX
, iy
);
267 /* enter interior of triangle */
270 while (coverage
> 0.0F
) {
271 /* (cx,cy) = center of fragment */
272 const GLfloat cx
= ix
+ 0.5F
, cy
= iy
+ 0.5F
;
274 z
[count
] = (GLdepth
) solve_plane(cx
, cy
, zPlane
);
275 fog
[count
] = solve_plane(cx
, cy
, fogPlane
);
278 rgba
[count
][RCOMP
] = solve_plane_chan(cx
, cy
, rPlane
);
279 rgba
[count
][GCOMP
] = solve_plane_chan(cx
, cy
, gPlane
);
280 rgba
[count
][BCOMP
] = solve_plane_chan(cx
, cy
, bPlane
);
281 rgba
[count
][ACOMP
] = (GLchan
) (solve_plane_chan(cx
, cy
, aPlane
) * coverage
);
285 GLint frac
= compute_coveragei(pMin
, pMid
, pMax
, ix
, iy
);
286 GLint indx
= (GLint
) solve_plane(cx
, cy
, iPlane
);
287 index
[count
] = (indx
& ~0xf) | frac
;
291 spec
[count
][RCOMP
] = solve_plane_chan(cx
, cy
, srPlane
);
292 spec
[count
][GCOMP
] = solve_plane_chan(cx
, cy
, sgPlane
);
293 spec
[count
][BCOMP
] = solve_plane_chan(cx
, cy
, sbPlane
);
297 const GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
);
298 s
[count
] = solve_plane(cx
, cy
, sPlane
) * invQ
;
299 t
[count
] = solve_plane(cx
, cy
, tPlane
) * invQ
;
300 u
[count
] = solve_plane(cx
, cy
, uPlane
) * invQ
;
301 lambda
[count
] = compute_lambda(sPlane
, tPlane
, invQ
,
302 texWidth
, texHeight
);
304 #elif defined(DO_MULTITEX)
307 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
308 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
309 GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
[unit
]);
310 s
[unit
][count
] = solve_plane(cx
, cy
, sPlane
[unit
]) * invQ
;
311 t
[unit
][count
] = solve_plane(cx
, cy
, tPlane
[unit
]) * invQ
;
312 u
[unit
][count
] = solve_plane(cx
, cy
, uPlane
[unit
]) * invQ
;
313 lambda
[unit
][count
] = compute_lambda(sPlane
[unit
],
314 tPlane
[unit
], invQ
, texWidth
[unit
], texHeight
[unit
]);
321 coverage
= compute_coveragef(pMin
, pMid
, pMax
, ix
, iy
);
327 n
= (GLuint
) ix
- (GLuint
) startX
;
331 _mesa_write_multitexture_span(ctx
, n
, startX
, iy
, z
, fog
,
332 (const GLfloat (*)[MAX_WIDTH
]) s
,
333 (const GLfloat (*)[MAX_WIDTH
]) t
,
334 (const GLfloat (*)[MAX_WIDTH
]) u
,
335 (GLfloat (*)[MAX_WIDTH
]) lambda
,
336 rgba
, (const GLchan (*)[4]) spec
,
339 _mesa_write_multitexture_span(ctx
, n
, startX
, iy
, z
, fog
,
340 (const GLfloat (*)[MAX_WIDTH
]) s
,
341 (const GLfloat (*)[MAX_WIDTH
]) t
,
342 (const GLfloat (*)[MAX_WIDTH
]) u
,
343 lambda
, rgba
, NULL
, GL_POLYGON
);
345 #elif defined(DO_TEX)
347 _mesa_write_texture_span(ctx
, n
, startX
, iy
, z
, fog
,
348 s
, t
, u
, lambda
, rgba
,
349 (const GLchan (*)[4]) spec
, GL_POLYGON
);
351 _mesa_write_texture_span(ctx
, n
, startX
, iy
, z
, fog
,
353 rgba
, NULL
, GL_POLYGON
);
355 #elif defined(DO_RGBA)
356 _mesa_write_rgba_span(ctx
, n
, startX
, iy
, z
, fog
, rgba
, GL_POLYGON
);
357 #elif defined(DO_INDEX)
358 _mesa_write_index_span(ctx
, n
, startX
, iy
, z
, fog
, index
, GL_POLYGON
);
363 /* scan right to left */
364 const GLfloat
*pMin
= vMin
->win
;
365 const GLfloat
*pMid
= vMid
->win
;
366 const GLfloat
*pMax
= vMax
->win
;
367 const GLfloat dxdy
= majDx
/ majDy
;
368 const GLfloat xAdj
= dxdy
> 0 ? dxdy
: 0.0F
;
369 GLfloat x
= vMin
->win
[0] - (yMin
- iyMin
) * dxdy
;
371 for (iy
= iyMin
; iy
< iyMax
; iy
++, x
+= dxdy
) {
372 GLint ix
, left
, startX
= (GLint
) (x
+ xAdj
);
374 GLfloat coverage
= 0.0F
;
376 /* make sure we're not past the window edge */
377 if (startX
>= ctx
->DrawBuffer
->_Xmax
) {
378 startX
= ctx
->DrawBuffer
->_Xmax
- 1;
381 /* skip fragments with zero coverage */
382 while (startX
>= 0) {
383 coverage
= compute_coveragef(pMin
, pMax
, pMid
, startX
, iy
);
389 /* enter interior of triangle */
392 while (coverage
> 0.0F
) {
393 /* (cx,cy) = center of fragment */
394 const GLfloat cx
= ix
+ 0.5F
, cy
= iy
+ 0.5F
;
396 z
[ix
] = (GLdepth
) solve_plane(cx
, cy
, zPlane
);
397 fog
[ix
] = solve_plane(cx
, cy
, fogPlane
);
400 rgba
[ix
][RCOMP
] = solve_plane_chan(cx
, cy
, rPlane
);
401 rgba
[ix
][GCOMP
] = solve_plane_chan(cx
, cy
, gPlane
);
402 rgba
[ix
][BCOMP
] = solve_plane_chan(cx
, cy
, bPlane
);
403 rgba
[ix
][ACOMP
] = (GLchan
) (solve_plane_chan(cx
, cy
, aPlane
) * coverage
);
407 GLint frac
= compute_coveragei(pMin
, pMax
, pMid
, ix
, iy
);
408 GLint indx
= (GLint
) solve_plane(cx
, cy
, iPlane
);
409 index
[ix
] = (indx
& ~0xf) | frac
;
413 spec
[ix
][RCOMP
] = solve_plane_chan(cx
, cy
, srPlane
);
414 spec
[ix
][GCOMP
] = solve_plane_chan(cx
, cy
, sgPlane
);
415 spec
[ix
][BCOMP
] = solve_plane_chan(cx
, cy
, sbPlane
);
419 const GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
);
420 s
[ix
] = solve_plane(cx
, cy
, sPlane
) * invQ
;
421 t
[ix
] = solve_plane(cx
, cy
, tPlane
) * invQ
;
422 u
[ix
] = solve_plane(cx
, cy
, uPlane
) * invQ
;
423 lambda
[ix
] = compute_lambda(sPlane
, tPlane
, invQ
,
424 texWidth
, texHeight
);
426 #elif defined(DO_MULTITEX)
429 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
430 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
431 GLfloat invQ
= solve_plane_recip(cx
, cy
, vPlane
[unit
]);
432 s
[unit
][ix
] = solve_plane(cx
, cy
, sPlane
[unit
]) * invQ
;
433 t
[unit
][ix
] = solve_plane(cx
, cy
, tPlane
[unit
]) * invQ
;
434 u
[unit
][ix
] = solve_plane(cx
, cy
, uPlane
[unit
]) * invQ
;
435 lambda
[unit
][ix
] = compute_lambda(sPlane
[unit
],
436 tPlane
[unit
], invQ
, texWidth
[unit
], texHeight
[unit
]);
443 coverage
= compute_coveragef(pMin
, pMax
, pMid
, ix
, iy
);
449 n
= (GLuint
) startX
- (GLuint
) ix
;
455 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++) {
456 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
) {
458 for (j
= 0; j
< (GLint
) n
; j
++) {
459 s
[unit
][j
] = s
[unit
][j
+ left
];
460 t
[unit
][j
] = t
[unit
][j
+ left
];
461 u
[unit
][j
] = u
[unit
][j
+ left
];
462 lambda
[unit
][j
] = lambda
[unit
][j
+ left
];
468 _mesa_write_multitexture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
469 (const GLfloat (*)[MAX_WIDTH
]) s
,
470 (const GLfloat (*)[MAX_WIDTH
]) t
,
471 (const GLfloat (*)[MAX_WIDTH
]) u
,
473 (const GLchan (*)[4]) (spec
+ left
),
476 _mesa_write_multitexture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
477 (const GLfloat (*)[MAX_WIDTH
]) s
,
478 (const GLfloat (*)[MAX_WIDTH
]) t
,
479 (const GLfloat (*)[MAX_WIDTH
]) u
,
481 rgba
+ left
, NULL
, GL_POLYGON
);
483 #elif defined(DO_TEX)
485 _mesa_write_texture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
486 s
+ left
, t
+ left
, u
+ left
,
487 lambda
+ left
, rgba
+ left
,
488 (const GLchan (*)[4]) (spec
+ left
),
491 _mesa_write_texture_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
493 u
+ left
, lambda
+ left
,
494 rgba
+ left
, NULL
, GL_POLYGON
);
496 #elif defined(DO_RGBA)
497 _mesa_write_rgba_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
498 rgba
+ left
, GL_POLYGON
);
499 #elif defined(DO_INDEX)
500 _mesa_write_index_span(ctx
, n
, left
, iy
, z
+ left
, fog
+ left
,
501 index
+ left
, GL_POLYGON
);
532 #ifdef DO_OCCLUSION_TEST
533 #undef DO_OCCLUSION_TEST