1 /* $Id: tritemp.h,v 1.17 1998/01/16 03:46:07 brianp Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-1997 Brian Paul
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Revision 1.17 1998/01/16 03:46:07 brianp
27 * fixed a few Windows compilation warnings (Theodore Jump)
29 * Revision 1.16 1997/09/18 01:08:10 brianp
30 * fixed S_SCALE / T_SCALE mix-up
32 * Revision 1.15 1997/08/22 01:53:03 brianp
33 * another attempt at fixing under/overflow errors
35 * Revision 1.14 1997/08/13 02:10:13 brianp
36 * added code to prevent over/underflow (Guido Jansen, Magnus Lundin)
38 * Revision 1.13 1997/06/20 02:52:49 brianp
39 * changed color components from GLfixed to GLubyte
41 * Revision 1.12 1997/03/14 00:25:02 brianp
42 * fixed unitialized memory read, contributed by Tom Schmidt
44 * Revision 1.11 1997/02/09 18:51:10 brianp
45 * fixed typo in texture R interpolation code
47 * Revision 1.10 1996/12/20 23:12:23 brianp
48 * another attempt at preventing color interpolation over/underflow
50 * Revision 1.9 1996/12/18 20:38:25 brianp
51 * commented out unused zp declaration
53 * Revision 1.8 1996/12/12 22:37:49 brianp
54 * projective textures didn't work right
56 * Revision 1.7 1996/11/02 06:17:37 brianp
57 * fixed some float/int roundoff and over/underflow errors (hopefully)
59 * Revision 1.6 1996/10/01 04:13:09 brianp
60 * fixed Z interpolation for >16-bit depth buffer
61 * added color underflow error check
63 * Revision 1.5 1996/09/27 01:32:59 brianp
64 * removed unused variables
66 * Revision 1.4 1996/09/18 01:03:43 brianp
67 * tightened threshold for culling by area
69 * Revision 1.3 1996/09/15 14:19:16 brianp
70 * now use GLframebuffer and GLvisual
72 * Revision 1.2 1996/09/14 06:41:38 brianp
73 * perspective correct texture code wasn't sub-pixel accurate (Doug Rabson)
75 * Revision 1.1 1996/09/13 01:38:16 brianp
82 * Triangle Rasterizer Template
84 * This file is #include'd to generate custom triangle rasterizers.
86 * The following macros may be defined to indicate what auxillary information
87 * must be interplated across the triangle:
88 * INTERP_Z - if defined, interpolate Z values
89 * INTERP_RGB - if defined, interpolate RGB values
90 * INTERP_ALPHA - if defined, interpolate Alpha values
91 * INTERP_INDEX - if defined, interpolate color index values
92 * INTERP_ST - if defined, interpolate integer ST texcoords
93 * (fast, simple 2-D texture mapping)
94 * INTERP_STW - if defined, interpolate float ST texcoords and W
95 * (2-D texture maps with perspective correction)
96 * INTERP_UV - if defined, interpolate float UV texcoords too
97 * (for 3-D, 4-D? texture maps)
99 * When one can directly address pixels in the color buffer the following
100 * macros can be defined and used to compute pixel addresses during
101 * rasterization (see pRow):
102 * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
103 * BYTES_PER_ROW - number of bytes per row in the color buffer
104 * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
105 * Y==0 at bottom of screen and increases upward.
107 * Optionally, one may provide one-time setup code per triangle:
108 * SETUP_CODE - code which is to be executed once per triangle
110 * The following macro MUST be defined:
111 * INNER_LOOP(LEFT,RIGHT,Y) - code to write a span of pixels.
114 * for (x=LEFT; x<RIGHT;x++) {
116 * // increment fixed point interpolants
119 * This code was designed for the origin to be in the lower-left corner.
121 * Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen!
125 /*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
128 GLint v0
, v1
; /* Y(v0) < Y(v1) */
129 GLfloat dx
; /* X(v1) - X(v0) */
130 GLfloat dy
; /* Y(v1) - Y(v0) */
131 GLfixed fdxdy
; /* dx/dy in fixed-point */
132 GLfixed fsx
; /* first sample point x coord */
134 GLfloat adjy
; /* adjust from v[0]->fy to fsy, scaled */
135 GLint lines
; /* number of lines to be sampled on this edge */
136 GLfixed fx0
; /* fixed pt X of lower endpoint */
139 struct vertex_buffer
*VB
= ctx
->VB
;
140 EdgeT eMaj
, eTop
, eBot
;
142 int vMin
, vMid
, vMax
; /* vertex indexes: Y(vMin)<=Y(vMid)<=Y(vMax) */
144 /* find the order of the 3 vertices along the Y axis */
146 GLfloat y0
= VB
->Win
[v0
][1];
147 GLfloat y1
= VB
->Win
[v1
][1];
148 GLfloat y2
= VB
->Win
[v2
][1];
152 vMin
= v0
; vMid
= v1
; vMax
= v2
; /* y0<=y1<=y2 */
155 vMin
= v2
; vMid
= v0
; vMax
= v1
; /* y2<=y0<=y1 */
158 vMin
= v0
; vMid
= v2
; vMax
= v1
; /* y0<=y2<=y1 */
163 vMin
= v1
; vMid
= v0
; vMax
= v2
; /* y1<=y0<=y2 */
166 vMin
= v2
; vMid
= v1
; vMax
= v0
; /* y2<=y1<=y0 */
169 vMin
= v1
; vMid
= v2
; vMax
= v0
; /* y1<=y2<=y0 */
174 /* vertex/edge relationship */
175 eMaj
.v0
= vMin
; eMaj
.v1
= vMax
; /*TODO: .v1's not needed */
176 eTop
.v0
= vMid
; eTop
.v1
= vMax
;
177 eBot
.v0
= vMin
; eBot
.v1
= vMid
;
179 /* compute deltas for each edge: vertex[v1] - vertex[v0] */
180 eMaj
.dx
= VB
->Win
[vMax
][0] - VB
->Win
[vMin
][0];
181 eMaj
.dy
= VB
->Win
[vMax
][1] - VB
->Win
[vMin
][1];
182 eTop
.dx
= VB
->Win
[vMax
][0] - VB
->Win
[vMid
][0];
183 eTop
.dy
= VB
->Win
[vMax
][1] - VB
->Win
[vMid
][1];
184 eBot
.dx
= VB
->Win
[vMid
][0] - VB
->Win
[vMin
][0];
185 eBot
.dy
= VB
->Win
[vMid
][1] - VB
->Win
[vMin
][1];
187 /* compute oneOverArea */
189 GLfloat area
= eMaj
.dx
* eBot
.dy
- eBot
.dx
* eMaj
.dy
;
190 if (area
>-0.05f
&& area
<0.05f
) {
191 return; /* very small; CULLED */
193 oneOverArea
= 1.0F
/ area
;
196 /* Edge setup. For a triangle strip these could be reused... */
198 /* fixed point Y coordinates */
199 GLfixed vMin_fx
= FloatToFixed(VB
->Win
[vMin
][0] + 0.5F
);
200 GLfixed vMin_fy
= FloatToFixed(VB
->Win
[vMin
][1] - 0.5F
);
201 GLfixed vMid_fx
= FloatToFixed(VB
->Win
[vMid
][0] + 0.5F
);
202 GLfixed vMid_fy
= FloatToFixed(VB
->Win
[vMid
][1] - 0.5F
);
203 GLfixed vMax_fy
= FloatToFixed(VB
->Win
[vMax
][1] - 0.5F
);
205 eMaj
.fsy
= FixedCeil(vMin_fy
);
206 eMaj
.lines
= FixedToInt(vMax_fy
+ FIXED_ONE
- FIXED_EPSILON
- eMaj
.fsy
);
207 if (eMaj
.lines
> 0) {
208 GLfloat dxdy
= eMaj
.dx
/ eMaj
.dy
;
209 eMaj
.fdxdy
= SignedFloatToFixed(dxdy
);
210 eMaj
.adjy
= (GLfloat
) (eMaj
.fsy
- vMin_fy
); /* SCALED! */
212 eMaj
.fsx
= eMaj
.fx0
+ (GLfixed
) (eMaj
.adjy
* dxdy
);
218 eTop
.fsy
= FixedCeil(vMid_fy
);
219 eTop
.lines
= FixedToInt(vMax_fy
+ FIXED_ONE
- FIXED_EPSILON
- eTop
.fsy
);
220 if (eTop
.lines
> 0) {
221 GLfloat dxdy
= eTop
.dx
/ eTop
.dy
;
222 eTop
.fdxdy
= SignedFloatToFixed(dxdy
);
223 eTop
.adjy
= (GLfloat
) (eTop
.fsy
- vMid_fy
); /* SCALED! */
225 eTop
.fsx
= eTop
.fx0
+ (GLfixed
) (eTop
.adjy
* dxdy
);
228 eBot
.fsy
= FixedCeil(vMin_fy
);
229 eBot
.lines
= FixedToInt(vMid_fy
+ FIXED_ONE
- FIXED_EPSILON
- eBot
.fsy
);
230 if (eBot
.lines
> 0) {
231 GLfloat dxdy
= eBot
.dx
/ eBot
.dy
;
232 eBot
.fdxdy
= SignedFloatToFixed(dxdy
);
233 eBot
.adjy
= (GLfloat
) (eBot
.fsy
- vMin_fy
); /* SCALED! */
235 eBot
.fsx
= eBot
.fx0
+ (GLfixed
) (eBot
.adjy
* dxdy
);
240 * Conceptually, we view a triangle as two subtriangles
241 * separated by a perfectly horizontal line. The edge that is
242 * intersected by this line is one with maximal absolute dy; we
243 * call it a ``major'' edge. The other two edges are the
244 * ``top'' edge (for the upper subtriangle) and the ``bottom''
245 * edge (for the lower subtriangle). If either of these two
246 * edges is horizontal or very close to horizontal, the
247 * corresponding subtriangle might cover zero sample points;
248 * we take care to handle such cases, for performance as well
251 * By stepping rasterization parameters along the major edge,
252 * we can avoid recomputing them at the discontinuity where
253 * the top and bottom edges meet. However, this forces us to
254 * be able to scan both left-to-right and right-to-left.
255 * Also, we must determine whether the major edge is at the
256 * left or right side of the triangle. We do this by
257 * computing the magnitude of the cross-product of the major
258 * and top edges. Since this magnitude depends on the sine of
259 * the angle between the two edges, its sign tells us whether
260 * we turn to the left or to the right when travelling along
261 * the major edge to the top edge, and from this we infer
262 * whether the major edge is on the left or the right.
264 * Serendipitously, this cross-product magnitude is also a
265 * value we need to compute the iteration parameter
266 * derivatives for the triangle, and it can be used to perform
267 * backface culling because its sign tells us whether the
268 * triangle is clockwise or counterclockwise. In this code we
269 * refer to it as ``area'' because it's also proportional to
270 * the pixel area of the triangle.
274 GLint ltor
; /* true if scanning left-to-right */
276 GLfloat dzdx
, dzdy
; GLfixed fdzdx
;
279 GLfloat drdx
, drdy
; GLfixed fdrdx
;
280 GLfloat dgdx
, dgdy
; GLfixed fdgdx
;
281 GLfloat dbdx
, dbdy
; GLfixed fdbdx
;
284 GLfloat dadx
, dady
; GLfixed fdadx
;
287 GLfloat didx
, didy
; GLfixed fdidx
;
290 GLfloat dsdx
, dsdy
; GLfixed fdsdx
;
291 GLfloat dtdx
, dtdy
; GLfixed fdtdx
;
304 * Execute user-supplied setup code
310 ltor
= (oneOverArea
< 0.0F
);
312 /* compute d?/dx and d?/dy derivatives */
315 GLfloat eMaj_dz
, eBot_dz
;
316 eMaj_dz
= VB
->Win
[vMax
][2] - VB
->Win
[vMin
][2];
317 eBot_dz
= VB
->Win
[vMid
][2] - VB
->Win
[vMin
][2];
318 dzdx
= oneOverArea
* (eMaj_dz
* eBot
.dy
- eMaj
.dy
* eBot_dz
);
319 if (dzdx
>DEPTH_SCALE
|| dzdx
<-DEPTH_SCALE
) {
320 /* probably a sliver triangle */
325 dzdy
= oneOverArea
* (eMaj
.dx
* eBot_dz
- eMaj_dz
* eBot
.dx
);
327 fdzdx
= (GLint
) dzdx
;
332 GLfloat eMaj_dr
, eBot_dr
;
333 eMaj_dr
= (GLint
) VB
->Color
[vMax
][0] - (GLint
) VB
->Color
[vMin
][0];
334 eBot_dr
= (GLint
) VB
->Color
[vMid
][0] - (GLint
) VB
->Color
[vMin
][0];
335 drdx
= oneOverArea
* (eMaj_dr
* eBot
.dy
- eMaj
.dy
* eBot_dr
);
336 fdrdx
= SignedFloatToFixed(drdx
);
337 drdy
= oneOverArea
* (eMaj
.dx
* eBot_dr
- eMaj_dr
* eBot
.dx
);
340 GLfloat eMaj_dg
, eBot_dg
;
341 eMaj_dg
= (GLint
) VB
->Color
[vMax
][1] - (GLint
) VB
->Color
[vMin
][1];
342 eBot_dg
= (GLint
) VB
->Color
[vMid
][1] - (GLint
) VB
->Color
[vMin
][1];
343 dgdx
= oneOverArea
* (eMaj_dg
* eBot
.dy
- eMaj
.dy
* eBot_dg
);
344 fdgdx
= SignedFloatToFixed(dgdx
);
345 dgdy
= oneOverArea
* (eMaj
.dx
* eBot_dg
- eMaj_dg
* eBot
.dx
);
348 GLfloat eMaj_db
, eBot_db
;
349 eMaj_db
= (GLint
) VB
->Color
[vMax
][2] - (GLint
) VB
->Color
[vMin
][2];
350 eBot_db
= (GLint
) VB
->Color
[vMid
][2] - (GLint
) VB
->Color
[vMin
][2];
351 dbdx
= oneOverArea
* (eMaj_db
* eBot
.dy
- eMaj
.dy
* eBot_db
);
352 fdbdx
= SignedFloatToFixed(dbdx
);
353 dbdy
= oneOverArea
* (eMaj
.dx
* eBot_db
- eMaj_db
* eBot
.dx
);
358 GLfloat eMaj_da
, eBot_da
;
359 eMaj_da
= (GLint
) VB
->Color
[vMax
][3] - (GLint
) VB
->Color
[vMin
][3];
360 eBot_da
= (GLint
) VB
->Color
[vMid
][3] - (GLint
) VB
->Color
[vMin
][3];
361 dadx
= oneOverArea
* (eMaj_da
* eBot
.dy
- eMaj
.dy
* eBot_da
);
362 fdadx
= SignedFloatToFixed(dadx
);
363 dady
= oneOverArea
* (eMaj
.dx
* eBot_da
- eMaj_da
* eBot
.dx
);
368 GLfloat eMaj_di
, eBot_di
;
369 eMaj_di
= (GLint
) VB
->Index
[vMax
] - (GLint
) VB
->Index
[vMin
];
370 eBot_di
= (GLint
) VB
->Index
[vMid
] - (GLint
) VB
->Index
[vMin
];
371 didx
= oneOverArea
* (eMaj_di
* eBot
.dy
- eMaj
.dy
* eBot_di
);
372 fdidx
= SignedFloatToFixed(didx
);
373 didy
= oneOverArea
* (eMaj
.dx
* eBot_di
- eMaj_di
* eBot
.dx
);
378 GLfloat eMaj_ds
, eBot_ds
;
379 eMaj_ds
= (VB
->TexCoord
[vMax
][0] - VB
->TexCoord
[vMin
][0]) * S_SCALE
;
380 eBot_ds
= (VB
->TexCoord
[vMid
][0] - VB
->TexCoord
[vMin
][0]) * S_SCALE
;
381 dsdx
= oneOverArea
* (eMaj_ds
* eBot
.dy
- eMaj
.dy
* eBot_ds
);
382 fdsdx
= SignedFloatToFixed(dsdx
);
383 dsdy
= oneOverArea
* (eMaj
.dx
* eBot_ds
- eMaj_ds
* eBot
.dx
);
386 GLfloat eMaj_dt
, eBot_dt
;
387 eMaj_dt
= (VB
->TexCoord
[vMax
][1] - VB
->TexCoord
[vMin
][1]) * T_SCALE
;
388 eBot_dt
= (VB
->TexCoord
[vMid
][1] - VB
->TexCoord
[vMin
][1]) * T_SCALE
;
389 dtdx
= oneOverArea
* (eMaj_dt
* eBot
.dy
- eMaj
.dy
* eBot_dt
);
390 fdtdx
= SignedFloatToFixed(dtdx
);
391 dtdy
= oneOverArea
* (eMaj
.dx
* eBot_dt
- eMaj_dt
* eBot
.dx
);
396 GLfloat wMax
= 1.0F
/ VB
->Clip
[vMax
][3];
397 GLfloat wMin
= 1.0F
/ VB
->Clip
[vMin
][3];
398 GLfloat wMid
= 1.0F
/ VB
->Clip
[vMid
][3];
399 GLfloat eMaj_dw
, eBot_dw
;
400 GLfloat eMaj_ds
, eBot_ds
;
401 GLfloat eMaj_dt
, eBot_dt
;
403 GLfloat eMaj_du
, eBot_du
;
404 GLfloat eMaj_dv
, eBot_dv
;
406 eMaj_dw
= wMax
- wMin
;
407 eBot_dw
= wMid
- wMin
;
408 dwdx
= oneOverArea
* (eMaj_dw
* eBot
.dy
- eMaj
.dy
* eBot_dw
);
409 dwdy
= oneOverArea
* (eMaj
.dx
* eBot_dw
- eMaj_dw
* eBot
.dx
);
411 eMaj_ds
= VB
->TexCoord
[vMax
][0]*wMax
- VB
->TexCoord
[vMin
][0]*wMin
;
412 eBot_ds
= VB
->TexCoord
[vMid
][0]*wMid
- VB
->TexCoord
[vMin
][0]*wMin
;
413 dsdx
= oneOverArea
* (eMaj_ds
* eBot
.dy
- eMaj
.dy
* eBot_ds
);
414 dsdy
= oneOverArea
* (eMaj
.dx
* eBot_ds
- eMaj_ds
* eBot
.dx
);
416 eMaj_dt
= VB
->TexCoord
[vMax
][1]*wMax
- VB
->TexCoord
[vMin
][1]*wMin
;
417 eBot_dt
= VB
->TexCoord
[vMid
][1]*wMid
- VB
->TexCoord
[vMin
][1]*wMin
;
418 dtdx
= oneOverArea
* (eMaj_dt
* eBot
.dy
- eMaj
.dy
* eBot_dt
);
419 dtdy
= oneOverArea
* (eMaj
.dx
* eBot_dt
- eMaj_dt
* eBot
.dx
);
421 eMaj_du
= VB
->TexCoord
[vMax
][2]*wMax
- VB
->TexCoord
[vMin
][2]*wMin
;
422 eBot_du
= VB
->TexCoord
[vMid
][2]*wMid
- VB
->TexCoord
[vMin
][2]*wMin
;
423 dudx
= oneOverArea
* (eMaj_du
* eBot
.dy
- eMaj
.dy
* eBot_du
);
424 dudy
= oneOverArea
* (eMaj
.dx
* eBot_du
- eMaj_du
* eBot
.dx
);
426 /* Note: don't divide V component by W */
427 eMaj_dv
= VB
->TexCoord
[vMax
][3] - VB
->TexCoord
[vMin
][3];
428 eBot_dv
= VB
->TexCoord
[vMid
][3] - VB
->TexCoord
[vMin
][3];
429 dvdx
= oneOverArea
* (eMaj_dv
* eBot
.dy
- eMaj
.dy
* eBot_dv
);
430 dvdy
= oneOverArea
* (eMaj
.dx
* eBot_dv
- eMaj_dv
* eBot
.dx
);
436 * We always sample at pixel centers. However, we avoid
437 * explicit half-pixel offsets in this code by incorporating
438 * the proper offset in each of x and y during the
439 * transformation to window coordinates.
441 * We also apply the usual rasterization rules to prevent
442 * cracks and overlaps. A pixel is considered inside a
443 * subtriangle if it meets all of four conditions: it is on or
444 * to the right of the left edge, strictly to the left of the
445 * right edge, on or below the top edge, and strictly above
446 * the bottom edge. (Some edges may be degenerate.)
448 * The following discussion assumes left-to-right scanning
449 * (that is, the major edge is on the left); the right-to-left
450 * case is a straightforward variation.
452 * We start by finding the half-integral y coordinate that is
453 * at or below the top of the triangle. This gives us the
454 * first scan line that could possibly contain pixels that are
455 * inside the triangle.
457 * Next we creep down the major edge until we reach that y,
458 * and compute the corresponding x coordinate on the edge.
459 * Then we find the half-integral x that lies on or just
460 * inside the edge. This is the first pixel that might lie in
461 * the interior of the triangle. (We won't know for sure
462 * until we check the other edges.)
464 * As we rasterize the triangle, we'll step down the major
465 * edge. For each step in y, we'll move an integer number
466 * of steps in x. There are two possible x step sizes, which
467 * we'll call the ``inner'' step (guaranteed to land on the
468 * edge or inside it) and the ``outer'' step (guaranteed to
469 * land on the edge or outside it). The inner and outer steps
470 * differ by one. During rasterization we maintain an error
471 * term that indicates our distance from the true edge, and
472 * select either the inner step or the outer step, whichever
473 * gets us to the first pixel that falls inside the triangle.
475 * All parameters (z, red, etc.) as well as the buffer
476 * addresses for color and z have inner and outer step values,
477 * so that we can increment them appropriately. This method
478 * eliminates the need to adjust parameters by creeping a
479 * sub-pixel amount into the triangle at each scanline.
484 GLfixed fx
, fxLeftEdge
, fxRightEdge
, fdxLeftEdge
, fdxRightEdge
;
488 GLfixed fError
, fdError
;
494 int dPRowOuter
, dPRowInner
; /* offset in bytes */
498 int dZRowOuter
, dZRowInner
; /* offset in bytes */
499 GLfixed fz
, fdzOuter
, fdzInner
;
502 GLfixed fr
, fdrOuter
, fdrInner
;
503 GLfixed fg
, fdgOuter
, fdgInner
;
504 GLfixed fb
, fdbOuter
, fdbInner
;
507 GLfixed fa
, fdaOuter
, fdaInner
;
510 GLfixed fi
, fdiOuter
, fdiInner
;
513 GLfixed fs
, fdsOuter
, fdsInner
;
514 GLfixed ft
, fdtOuter
, fdtInner
;
517 GLfloat sLeft
, dsOuter
, dsInner
;
518 GLfloat tLeft
, dtOuter
, dtInner
;
519 GLfloat wLeft
, dwOuter
, dwInner
;
522 GLfloat uLeft
, duOuter
, duInner
;
523 GLfloat vLeft
, dvOuter
, dvInner
;
526 for (subTriangle
=0; subTriangle
<=1; subTriangle
++) {
527 EdgeT
*eLeft
, *eRight
;
528 int setupLeft
, setupRight
;
531 if (subTriangle
==0) {
536 lines
= eRight
->lines
;
543 lines
= eLeft
->lines
;
553 lines
= eRight
->lines
;
560 lines
= eLeft
->lines
;
564 if (lines
==0) return;
567 if (setupLeft
&& eLeft
->lines
>0) {
569 GLfixed fsx
= eLeft
->fsx
;
571 fError
= fx
- fsx
- FIXED_ONE
;
572 fxLeftEdge
= fsx
- FIXED_EPSILON
;
573 fdxLeftEdge
= eLeft
->fdxdy
;
574 fdxOuter
= FixedFloor(fdxLeftEdge
- FIXED_EPSILON
);
575 fdError
= fdxOuter
- fdxLeftEdge
+ FIXED_ONE
;
576 idxOuter
= FixedToInt(fdxOuter
);
577 dxOuter
= (float) idxOuter
;
582 adjx
= (float)(fx
- eLeft
->fx0
); /* SCALED! */
583 adjy
= eLeft
->adjy
; /* SCALED! */
589 pRow
= PIXEL_ADDRESS( FixedToInt(fxLeftEdge
), iy
);
590 dPRowOuter
= -((int)BYTES_PER_ROW
) + idxOuter
* sizeof(PIXEL_TYPE
);
591 /* negative because Y=0 at bottom and increases upward */
595 * Now we need the set of parameter (z, color, etc.) values at
596 * the point (fx, fy). This gives us properly-sampled parameter
597 * values that we can step from pixel to pixel. Furthermore,
598 * although we might have intermediate results that overflow
599 * the normal parameter range when we step temporarily outside
600 * the triangle, we shouldn't overflow or underflow for any
601 * pixel that's actually inside the triangle.
607 z0
= VB
->Win
[vLower
][2] + ctx
->PolygonZoffset
;
609 /* interpolate depth values exactly */
610 fz
= (GLint
) (z0
+ dzdx
*FixedToFloat(adjx
) + dzdy
*FixedToFloat(adjy
));
611 fdzOuter
= (GLint
) (dzdy
+ dxOuter
* dzdx
);
612 zRow
= Z_ADDRESS( ctx
, FixedToInt(fxLeftEdge
), iy
);
613 dZRowOuter
= (ctx
->Buffer
->Width
+ idxOuter
) * sizeof(GLdepth
);
617 fr
= (GLfixed
)(IntToFixed(VB
->Color
[vLower
][0]) + drdx
* adjx
+ drdy
* adjy
)
619 fdrOuter
= SignedFloatToFixed(drdy
+ dxOuter
* drdx
);
621 fg
= (GLfixed
)(IntToFixed(VB
->Color
[vLower
][1]) + dgdx
* adjx
+ dgdy
* adjy
)
623 fdgOuter
= SignedFloatToFixed(dgdy
+ dxOuter
* dgdx
);
625 fb
= (GLfixed
)(IntToFixed(VB
->Color
[vLower
][2]) + dbdx
* adjx
+ dbdy
* adjy
)
627 fdbOuter
= SignedFloatToFixed(dbdy
+ dxOuter
* dbdx
);
630 fa
= (GLfixed
)(IntToFixed(VB
->Color
[vLower
][3]) + dadx
* adjx
+ dady
* adjy
)
632 fdaOuter
= SignedFloatToFixed(dady
+ dxOuter
* dadx
);
635 fi
= (GLfixed
)(VB
->Index
[vLower
] * FIXED_SCALE
+ didx
* adjx
636 + didy
* adjy
) + FIXED_HALF
;
637 fdiOuter
= SignedFloatToFixed(didy
+ dxOuter
* didx
);
642 s0
= VB
->TexCoord
[vLower
][0] * S_SCALE
;
643 fs
= (GLfixed
)(s0
* FIXED_SCALE
+ dsdx
* adjx
+ dsdy
* adjy
) + FIXED_HALF
;
644 fdsOuter
= SignedFloatToFixed(dsdy
+ dxOuter
* dsdx
);
645 t0
= VB
->TexCoord
[vLower
][1] * T_SCALE
;
646 ft
= (GLfixed
)(t0
* FIXED_SCALE
+ dtdx
* adjx
+ dtdy
* adjy
) + FIXED_HALF
;
647 fdtOuter
= SignedFloatToFixed(dtdy
+ dxOuter
* dtdx
);
652 GLfloat w0
= 1.0F
/ VB
->Clip
[vLower
][3];
653 GLfloat s0
, t0
, u0
, v0
;
654 wLeft
= w0
+ (dwdx
* adjx
+ dwdy
* adjy
) * (1.0F
/FIXED_SCALE
);
655 dwOuter
= dwdy
+ dxOuter
* dwdx
;
656 s0
= VB
->TexCoord
[vLower
][0] * w0
;
657 sLeft
= s0
+ (dsdx
* adjx
+ dsdy
* adjy
) * (1.0F
/FIXED_SCALE
);
658 dsOuter
= dsdy
+ dxOuter
* dsdx
;
659 t0
= VB
->TexCoord
[vLower
][1] * w0
;
660 tLeft
= t0
+ (dtdx
* adjx
+ dtdy
* adjy
) * (1.0F
/FIXED_SCALE
);
661 dtOuter
= dtdy
+ dxOuter
* dtdx
;
663 u0
= VB
->TexCoord
[vLower
][2] * w0
;
664 uLeft
= u0
+ (dudx
* adjx
+ dudy
* adjy
) * (1.0F
/FIXED_SCALE
);
665 duOuter
= dudy
+ dxOuter
* dudx
;
666 /* Note: don't divide V component by W */
667 v0
= VB
->TexCoord
[vLower
][3];
668 vLeft
= v0
+ (dvdx
* adjx
+ dvdy
* adjy
) * (1.0F
/FIXED_SCALE
);
669 dvOuter
= dvdy
+ dxOuter
* dvdx
;
677 if (setupRight
&& eRight
->lines
>0) {
678 fxRightEdge
= eRight
->fsx
- FIXED_EPSILON
;
679 fdxRightEdge
= eRight
->fdxdy
;
687 /* Rasterize setup */
689 dPRowInner
= dPRowOuter
+ sizeof(PIXEL_TYPE
);
692 dZRowInner
= dZRowOuter
+ sizeof(GLdepth
);
693 fdzInner
= fdzOuter
+ fdzdx
;
696 fdrInner
= fdrOuter
+ fdrdx
;
697 fdgInner
= fdgOuter
+ fdgdx
;
698 fdbInner
= fdbOuter
+ fdbdx
;
701 fdaInner
= fdaOuter
+ fdadx
;
704 fdiInner
= fdiOuter
+ fdidx
;
707 fdsInner
= fdsOuter
+ fdsdx
;
708 fdtInner
= fdtOuter
+ fdtdx
;
711 dwInner
= dwOuter
+ dwdx
;
712 dsInner
= dsOuter
+ dsdx
;
713 dtInner
= dtOuter
+ dtdx
;
715 duInner
= duOuter
+ dudx
;
716 dvInner
= dvOuter
+ dvdx
;
721 /* initialize the span interpolants to the leftmost value */
722 /* ff = fixed-pt fragment */
725 /*GLdepth *zp = zRow;*/
728 GLfixed ffr
= fr
, ffg
= fg
, ffb
= fb
;
737 GLfixed ffs
= fs
, fft
= ft
;
740 GLfloat ss
= sLeft
, tt
= tLeft
, ww
= wLeft
;
743 GLfloat uu
= uLeft
, vv
= vLeft
;
745 GLint left
= FixedToInt(fxLeftEdge
);
746 GLint right
= FixedToInt(fxRightEdge
);
750 /* need this to accomodate round-off errors */
751 GLfixed ffrend
= ffr
+(right
-left
-1)*fdrdx
;
752 GLfixed ffgend
= ffg
+(right
-left
-1)*fdgdx
;
753 GLfixed ffbend
= ffb
+(right
-left
-1)*fdbdx
;
754 if (ffrend
<0) ffr
-= ffrend
;
755 if (ffgend
<0) ffg
-= ffgend
;
756 if (ffbend
<0) ffb
-= ffbend
;
764 GLfixed ffaend
= ffa
+(right
-left
-1)*fdadx
;
765 if (ffaend
<0) ffa
-= ffaend
;
773 INNER_LOOP( left
, right
, iy
);
776 * Advance to the next scan line. Compute the
777 * new edge coordinates, and adjust the
778 * pixel-center x coordinate so that it stays
779 * on or inside the major edge.
784 fxLeftEdge
+= fdxLeftEdge
;
785 fxRightEdge
+= fdxRightEdge
;
792 pRow
= (PIXEL_TYPE
*) ((GLubyte
*)pRow
+ dPRowOuter
);
795 zRow
= (GLdepth
*) ((GLubyte
*)zRow
+ dZRowOuter
);
799 fr
+= fdrOuter
; fg
+= fdgOuter
; fb
+= fdbOuter
;
808 fs
+= fdsOuter
; ft
+= fdtOuter
;
822 pRow
= (PIXEL_TYPE
*) ((GLubyte
*)pRow
+ dPRowInner
);
825 zRow
= (GLdepth
*) ((GLubyte
*)zRow
+ dZRowInner
);
829 fr
+= fdrInner
; fg
+= fdgInner
; fb
+= fdbInner
;
838 fs
+= fdsInner
; ft
+= fdtInner
;
852 } /* for subTriangle */