Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
22 | * OTHER DEALINGS IN THE SOFTWARE. |
||
23 | */ |
||
24 | |||
25 | /* |
||
26 | * Triangle Rasterizer Template |
||
27 | * |
||
28 | * This file is #include'd to generate custom triangle rasterizers. |
||
29 | * |
||
30 | * The following macros may be defined to indicate what auxillary information |
||
31 | * must be interpolated across the triangle: |
||
32 | * INTERP_Z - if defined, interpolate integer Z values |
||
33 | * INTERP_RGB - if defined, interpolate integer RGB values |
||
34 | * INTERP_ALPHA - if defined, interpolate integer Alpha values |
||
35 | * INTERP_INT_TEX - if defined, interpolate integer ST texcoords |
||
36 | * (fast, simple 2-D texture mapping, without |
||
37 | * perspective correction) |
||
38 | * INTERP_ATTRIBS - if defined, interpolate arbitrary attribs (texcoords, |
||
39 | * varying vars, etc) This also causes W to be |
||
40 | * computed for perspective correction). |
||
41 | * |
||
42 | * When one can directly address pixels in the color buffer the following |
||
43 | * macros can be defined and used to compute pixel addresses during |
||
44 | * rasterization (see pRow): |
||
45 | * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint) |
||
46 | * BYTES_PER_ROW - number of bytes per row in the color buffer |
||
47 | * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where |
||
48 | * Y==0 at bottom of screen and increases upward. |
||
49 | * |
||
50 | * Similarly, for direct depth buffer access, this type is used for depth |
||
51 | * buffer addressing (see zRow): |
||
52 | * DEPTH_TYPE - either GLushort or GLuint |
||
53 | * |
||
54 | * Optionally, one may provide one-time setup code per triangle: |
||
55 | * SETUP_CODE - code which is to be executed once per triangle |
||
56 | * |
||
57 | * The following macro MUST be defined: |
||
58 | * RENDER_SPAN(span) - code to write a span of pixels. |
||
59 | * |
||
60 | * This code was designed for the origin to be in the lower-left corner. |
||
61 | * |
||
62 | * Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen! |
||
63 | * |
||
64 | * |
||
65 | * Some notes on rasterization accuracy: |
||
66 | * |
||
67 | * This code uses fixed point arithmetic (the GLfixed type) to iterate |
||
68 | * over the triangle edges and interpolate ancillary data (such as Z, |
||
69 | * color, secondary color, etc). The number of fractional bits in |
||
70 | * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the |
||
71 | * accuracy of rasterization. |
||
72 | * |
||
73 | * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest |
||
74 | * 1/16 of a pixel. If we're walking up a long, nearly vertical edge |
||
75 | * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in |
||
76 | * GLfixed to walk the edge without error. If the maximum viewport |
||
77 | * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits. |
||
78 | * |
||
79 | * Historically, Mesa has used 11 fractional bits in GLfixed, snaps |
||
80 | * vertices to 1/16 pixel and allowed a maximum viewport height of 2K |
||
81 | * pixels. 11 fractional bits is actually insufficient for accurately |
||
82 | * rasterizing some triangles. More recently, the maximum viewport |
||
83 | * height was increased to 4K pixels. Thus, Mesa should be using 16 |
||
84 | * fractional bits in GLfixed. Unfortunately, there may be some issues |
||
85 | * with setting FIXED_FRAC_BITS=16, such as multiplication overflow. |
||
86 | * This will have to be examined in some detail... |
||
87 | * |
||
88 | * For now, if you find rasterization errors, particularly with tall, |
||
89 | * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing |
||
90 | * SUB_PIXEL_BITS. |
||
91 | */ |
||
92 | |||
93 | |||
94 | /* |
||
95 | * Some code we unfortunately need to prevent negative interpolated colors. |
||
96 | */ |
||
97 | #ifndef CLAMP_INTERPOLANT |
||
98 | #define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \ |
||
99 | do { \ |
||
100 | GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \ |
||
101 | if (endVal < 0) { \ |
||
102 | span.CHANNEL -= endVal; \ |
||
103 | } \ |
||
104 | if (span.CHANNEL < 0) { \ |
||
105 | span.CHANNEL = 0; \ |
||
106 | } \ |
||
107 | } while (0) |
||
108 | #endif |
||
109 | |||
110 | |||
111 | static void NAME(struct gl_context *ctx, const SWvertex *v0, |
||
112 | const SWvertex *v1, |
||
113 | const SWvertex *v2 ) |
||
114 | { |
||
115 | typedef struct { |
||
116 | const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */ |
||
117 | GLfloat dx; /* X(v1) - X(v0) */ |
||
118 | GLfloat dy; /* Y(v1) - Y(v0) */ |
||
119 | GLfloat dxdy; /* dx/dy */ |
||
120 | GLfixed fdxdy; /* dx/dy in fixed-point */ |
||
121 | GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */ |
||
122 | GLfixed fsx; /* first sample point x coord */ |
||
123 | GLfixed fsy; |
||
124 | GLfixed fx0; /* fixed pt X of lower endpoint */ |
||
125 | GLint lines; /* number of lines to be sampled on this edge */ |
||
126 | } EdgeT; |
||
127 | |||
128 | const SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
129 | #ifdef INTERP_Z |
||
130 | const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; |
||
131 | const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0; |
||
132 | const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF; |
||
133 | #define FixedToDepth(F) ((F) >> fixedToDepthShift) |
||
134 | #endif |
||
135 | EdgeT eMaj, eTop, eBot; |
||
136 | GLfloat oneOverArea; |
||
137 | const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */ |
||
138 | GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign; |
||
139 | const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */ |
||
140 | GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy; |
||
141 | |||
142 | SWspan span; |
||
143 | |||
144 | (void) swrast; |
||
145 | |||
146 | INIT_SPAN(span, GL_POLYGON); |
||
147 | span.y = 0; /* silence warnings */ |
||
148 | |||
149 | #ifdef INTERP_Z |
||
150 | (void) fixedToDepthShift; |
||
151 | #endif |
||
152 | |||
153 | /* |
||
154 | printf("%s()\n", __FUNCTION__); |
||
155 | printf(" %g, %g, %g\n", |
||
156 | v0->attrib[VARYING_SLOT_POS][0], |
||
157 | v0->attrib[VARYING_SLOT_POS][1], |
||
158 | v0->attrib[VARYING_SLOT_POS][2]); |
||
159 | printf(" %g, %g, %g\n", |
||
160 | v1->attrib[VARYING_SLOT_POS][0], |
||
161 | v1->attrib[VARYING_SLOT_POS][1], |
||
162 | v1->attrib[VARYING_SLOT_POS][2]); |
||
163 | printf(" %g, %g, %g\n", |
||
164 | v2->attrib[VARYING_SLOT_POS][0], |
||
165 | v2->attrib[VARYING_SLOT_POS][1], |
||
166 | v2->attrib[VARYING_SLOT_POS][2]); |
||
167 | */ |
||
168 | |||
169 | /* Compute fixed point x,y coords w/ half-pixel offsets and snapping. |
||
170 | * And find the order of the 3 vertices along the Y axis. |
||
171 | */ |
||
172 | { |
||
173 | const GLfixed fy0 = FloatToFixed(v0->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask; |
||
174 | const GLfixed fy1 = FloatToFixed(v1->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask; |
||
175 | const GLfixed fy2 = FloatToFixed(v2->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask; |
||
176 | if (fy0 <= fy1) { |
||
177 | if (fy1 <= fy2) { |
||
178 | /* y0 <= y1 <= y2 */ |
||
179 | vMin = v0; vMid = v1; vMax = v2; |
||
180 | vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2; |
||
181 | } |
||
182 | else if (fy2 <= fy0) { |
||
183 | /* y2 <= y0 <= y1 */ |
||
184 | vMin = v2; vMid = v0; vMax = v1; |
||
185 | vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1; |
||
186 | } |
||
187 | else { |
||
188 | /* y0 <= y2 <= y1 */ |
||
189 | vMin = v0; vMid = v2; vMax = v1; |
||
190 | vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1; |
||
191 | bf = -bf; |
||
192 | } |
||
193 | } |
||
194 | else { |
||
195 | if (fy0 <= fy2) { |
||
196 | /* y1 <= y0 <= y2 */ |
||
197 | vMin = v1; vMid = v0; vMax = v2; |
||
198 | vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2; |
||
199 | bf = -bf; |
||
200 | } |
||
201 | else if (fy2 <= fy1) { |
||
202 | /* y2 <= y1 <= y0 */ |
||
203 | vMin = v2; vMid = v1; vMax = v0; |
||
204 | vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0; |
||
205 | bf = -bf; |
||
206 | } |
||
207 | else { |
||
208 | /* y1 <= y2 <= y0 */ |
||
209 | vMin = v1; vMid = v2; vMax = v0; |
||
210 | vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0; |
||
211 | } |
||
212 | } |
||
213 | |||
214 | /* fixed point X coords */ |
||
215 | vMin_fx = FloatToFixed(vMin->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask; |
||
216 | vMid_fx = FloatToFixed(vMid->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask; |
||
217 | vMax_fx = FloatToFixed(vMax->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask; |
||
218 | } |
||
219 | |||
220 | /* vertex/edge relationship */ |
||
221 | eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */ |
||
222 | eTop.v0 = vMid; eTop.v1 = vMax; |
||
223 | eBot.v0 = vMin; eBot.v1 = vMid; |
||
224 | |||
225 | /* compute deltas for each edge: vertex[upper] - vertex[lower] */ |
||
226 | eMaj.dx = FixedToFloat(vMax_fx - vMin_fx); |
||
227 | eMaj.dy = FixedToFloat(vMax_fy - vMin_fy); |
||
228 | eTop.dx = FixedToFloat(vMax_fx - vMid_fx); |
||
229 | eTop.dy = FixedToFloat(vMax_fy - vMid_fy); |
||
230 | eBot.dx = FixedToFloat(vMid_fx - vMin_fx); |
||
231 | eBot.dy = FixedToFloat(vMid_fy - vMin_fy); |
||
232 | |||
233 | /* compute area, oneOverArea and perform backface culling */ |
||
234 | { |
||
235 | const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy; |
||
236 | |||
237 | if (IS_INF_OR_NAN(area) || area == 0.0F) |
||
238 | return; |
||
239 | |||
240 | if (area * bf * swrast->_BackfaceCullSign < 0.0) |
||
241 | return; |
||
242 | |||
243 | oneOverArea = 1.0F / area; |
||
244 | |||
245 | /* 0 = front, 1 = back */ |
||
246 | span.facing = oneOverArea * bf > 0.0F; |
||
247 | } |
||
248 | |||
249 | /* Edge setup. For a triangle strip these could be reused... */ |
||
250 | { |
||
251 | eMaj.fsy = FixedCeil(vMin_fy); |
||
252 | eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy)); |
||
253 | if (eMaj.lines > 0) { |
||
254 | eMaj.dxdy = eMaj.dx / eMaj.dy; |
||
255 | eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy); |
||
256 | eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */ |
||
257 | eMaj.fx0 = vMin_fx; |
||
258 | eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy); |
||
259 | } |
||
260 | else { |
||
261 | return; /*CULLED*/ |
||
262 | } |
||
263 | |||
264 | eTop.fsy = FixedCeil(vMid_fy); |
||
265 | eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy)); |
||
266 | if (eTop.lines > 0) { |
||
267 | eTop.dxdy = eTop.dx / eTop.dy; |
||
268 | eTop.fdxdy = SignedFloatToFixed(eTop.dxdy); |
||
269 | eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */ |
||
270 | eTop.fx0 = vMid_fx; |
||
271 | eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy); |
||
272 | } |
||
273 | |||
274 | eBot.fsy = FixedCeil(vMin_fy); |
||
275 | eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy)); |
||
276 | if (eBot.lines > 0) { |
||
277 | eBot.dxdy = eBot.dx / eBot.dy; |
||
278 | eBot.fdxdy = SignedFloatToFixed(eBot.dxdy); |
||
279 | eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */ |
||
280 | eBot.fx0 = vMin_fx; |
||
281 | eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy); |
||
282 | } |
||
283 | } |
||
284 | |||
285 | /* |
||
286 | * Conceptually, we view a triangle as two subtriangles |
||
287 | * separated by a perfectly horizontal line. The edge that is |
||
288 | * intersected by this line is one with maximal absolute dy; we |
||
289 | * call it a ``major'' edge. The other two edges are the |
||
290 | * ``top'' edge (for the upper subtriangle) and the ``bottom'' |
||
291 | * edge (for the lower subtriangle). If either of these two |
||
292 | * edges is horizontal or very close to horizontal, the |
||
293 | * corresponding subtriangle might cover zero sample points; |
||
294 | * we take care to handle such cases, for performance as well |
||
295 | * as correctness. |
||
296 | * |
||
297 | * By stepping rasterization parameters along the major edge, |
||
298 | * we can avoid recomputing them at the discontinuity where |
||
299 | * the top and bottom edges meet. However, this forces us to |
||
300 | * be able to scan both left-to-right and right-to-left. |
||
301 | * Also, we must determine whether the major edge is at the |
||
302 | * left or right side of the triangle. We do this by |
||
303 | * computing the magnitude of the cross-product of the major |
||
304 | * and top edges. Since this magnitude depends on the sine of |
||
305 | * the angle between the two edges, its sign tells us whether |
||
306 | * we turn to the left or to the right when travelling along |
||
307 | * the major edge to the top edge, and from this we infer |
||
308 | * whether the major edge is on the left or the right. |
||
309 | * |
||
310 | * Serendipitously, this cross-product magnitude is also a |
||
311 | * value we need to compute the iteration parameter |
||
312 | * derivatives for the triangle, and it can be used to perform |
||
313 | * backface culling because its sign tells us whether the |
||
314 | * triangle is clockwise or counterclockwise. In this code we |
||
315 | * refer to it as ``area'' because it's also proportional to |
||
316 | * the pixel area of the triangle. |
||
317 | */ |
||
318 | |||
319 | { |
||
320 | GLint scan_from_left_to_right; /* true if scanning left-to-right */ |
||
321 | |||
322 | /* |
||
323 | * Execute user-supplied setup code |
||
324 | */ |
||
325 | #ifdef SETUP_CODE |
||
326 | SETUP_CODE |
||
327 | #endif |
||
328 | |||
329 | scan_from_left_to_right = (oneOverArea < 0.0F); |
||
330 | |||
331 | |||
332 | /* compute d?/dx and d?/dy derivatives */ |
||
333 | #ifdef INTERP_Z |
||
334 | span.interpMask |= SPAN_Z; |
||
335 | { |
||
336 | GLfloat eMaj_dz = vMax->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2]; |
||
337 | GLfloat eBot_dz = vMid->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2]; |
||
338 | span.attrStepX[VARYING_SLOT_POS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz); |
||
339 | if (span.attrStepX[VARYING_SLOT_POS][2] > maxDepth || |
||
340 | span.attrStepX[VARYING_SLOT_POS][2] < -maxDepth) { |
||
341 | /* probably a sliver triangle */ |
||
342 | span.attrStepX[VARYING_SLOT_POS][2] = 0.0; |
||
343 | span.attrStepY[VARYING_SLOT_POS][2] = 0.0; |
||
344 | } |
||
345 | else { |
||
346 | span.attrStepY[VARYING_SLOT_POS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx); |
||
347 | } |
||
348 | if (depthBits <= 16) |
||
349 | span.zStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_POS][2]); |
||
350 | else |
||
351 | span.zStep = (GLint) span.attrStepX[VARYING_SLOT_POS][2]; |
||
352 | } |
||
353 | #endif |
||
354 | #ifdef INTERP_RGB |
||
355 | span.interpMask |= SPAN_RGBA; |
||
356 | if (ctx->Light.ShadeModel == GL_SMOOTH) { |
||
357 | GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]); |
||
358 | GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]); |
||
359 | GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]); |
||
360 | GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]); |
||
361 | GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]); |
||
362 | GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]); |
||
363 | # ifdef INTERP_ALPHA |
||
364 | GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]); |
||
365 | GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]); |
||
366 | # endif |
||
367 | span.attrStepX[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr); |
||
368 | span.attrStepY[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx); |
||
369 | span.attrStepX[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg); |
||
370 | span.attrStepY[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx); |
||
371 | span.attrStepX[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db); |
||
372 | span.attrStepY[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx); |
||
373 | span.redStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][0]); |
||
374 | span.greenStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][1]); |
||
375 | span.blueStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][2]); |
||
376 | # ifdef INTERP_ALPHA |
||
377 | span.attrStepX[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da); |
||
378 | span.attrStepY[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx); |
||
379 | span.alphaStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][3]); |
||
380 | # endif /* INTERP_ALPHA */ |
||
381 | } |
||
382 | else { |
||
383 | ASSERT(ctx->Light.ShadeModel == GL_FLAT); |
||
384 | span.interpMask |= SPAN_FLAT; |
||
385 | span.attrStepX[VARYING_SLOT_COL0][0] = span.attrStepY[VARYING_SLOT_COL0][0] = 0.0F; |
||
386 | span.attrStepX[VARYING_SLOT_COL0][1] = span.attrStepY[VARYING_SLOT_COL0][1] = 0.0F; |
||
387 | span.attrStepX[VARYING_SLOT_COL0][2] = span.attrStepY[VARYING_SLOT_COL0][2] = 0.0F; |
||
388 | span.redStep = 0; |
||
389 | span.greenStep = 0; |
||
390 | span.blueStep = 0; |
||
391 | # ifdef INTERP_ALPHA |
||
392 | span.attrStepX[VARYING_SLOT_COL0][3] = span.attrStepY[VARYING_SLOT_COL0][3] = 0.0F; |
||
393 | span.alphaStep = 0; |
||
394 | # endif |
||
395 | } |
||
396 | #endif /* INTERP_RGB */ |
||
397 | #ifdef INTERP_INT_TEX |
||
398 | { |
||
399 | GLfloat eMaj_ds = (vMax->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE; |
||
400 | GLfloat eBot_ds = (vMid->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE; |
||
401 | GLfloat eMaj_dt = (vMax->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE; |
||
402 | GLfloat eBot_dt = (vMid->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE; |
||
403 | span.attrStepX[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds); |
||
404 | span.attrStepY[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx); |
||
405 | span.attrStepX[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt); |
||
406 | span.attrStepY[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx); |
||
407 | span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][0]); |
||
408 | span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][1]); |
||
409 | } |
||
410 | #endif |
||
411 | #ifdef INTERP_ATTRIBS |
||
412 | { |
||
413 | /* attrib[VARYING_SLOT_POS][3] is 1/W */ |
||
414 | const GLfloat wMax = vMax->attrib[VARYING_SLOT_POS][3]; |
||
415 | const GLfloat wMin = vMin->attrib[VARYING_SLOT_POS][3]; |
||
416 | const GLfloat wMid = vMid->attrib[VARYING_SLOT_POS][3]; |
||
417 | { |
||
418 | const GLfloat eMaj_dw = wMax - wMin; |
||
419 | const GLfloat eBot_dw = wMid - wMin; |
||
420 | span.attrStepX[VARYING_SLOT_POS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw); |
||
421 | span.attrStepY[VARYING_SLOT_POS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx); |
||
422 | } |
||
423 | ATTRIB_LOOP_BEGIN |
||
424 | if (swrast->_InterpMode[attr] == GL_FLAT) { |
||
425 | ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0); |
||
426 | ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0); |
||
427 | } |
||
428 | else { |
||
429 | GLuint c; |
||
430 | for (c = 0; c < 4; c++) { |
||
431 | GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin; |
||
432 | GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin; |
||
433 | span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da); |
||
434 | span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx); |
||
435 | } |
||
436 | } |
||
437 | ATTRIB_LOOP_END |
||
438 | } |
||
439 | #endif |
||
440 | |||
441 | /* |
||
442 | * We always sample at pixel centers. However, we avoid |
||
443 | * explicit half-pixel offsets in this code by incorporating |
||
444 | * the proper offset in each of x and y during the |
||
445 | * transformation to window coordinates. |
||
446 | * |
||
447 | * We also apply the usual rasterization rules to prevent |
||
448 | * cracks and overlaps. A pixel is considered inside a |
||
449 | * subtriangle if it meets all of four conditions: it is on or |
||
450 | * to the right of the left edge, strictly to the left of the |
||
451 | * right edge, on or below the top edge, and strictly above |
||
452 | * the bottom edge. (Some edges may be degenerate.) |
||
453 | * |
||
454 | * The following discussion assumes left-to-right scanning |
||
455 | * (that is, the major edge is on the left); the right-to-left |
||
456 | * case is a straightforward variation. |
||
457 | * |
||
458 | * We start by finding the half-integral y coordinate that is |
||
459 | * at or below the top of the triangle. This gives us the |
||
460 | * first scan line that could possibly contain pixels that are |
||
461 | * inside the triangle. |
||
462 | * |
||
463 | * Next we creep down the major edge until we reach that y, |
||
464 | * and compute the corresponding x coordinate on the edge. |
||
465 | * Then we find the half-integral x that lies on or just |
||
466 | * inside the edge. This is the first pixel that might lie in |
||
467 | * the interior of the triangle. (We won't know for sure |
||
468 | * until we check the other edges.) |
||
469 | * |
||
470 | * As we rasterize the triangle, we'll step down the major |
||
471 | * edge. For each step in y, we'll move an integer number |
||
472 | * of steps in x. There are two possible x step sizes, which |
||
473 | * we'll call the ``inner'' step (guaranteed to land on the |
||
474 | * edge or inside it) and the ``outer'' step (guaranteed to |
||
475 | * land on the edge or outside it). The inner and outer steps |
||
476 | * differ by one. During rasterization we maintain an error |
||
477 | * term that indicates our distance from the true edge, and |
||
478 | * select either the inner step or the outer step, whichever |
||
479 | * gets us to the first pixel that falls inside the triangle. |
||
480 | * |
||
481 | * All parameters (z, red, etc.) as well as the buffer |
||
482 | * addresses for color and z have inner and outer step values, |
||
483 | * so that we can increment them appropriately. This method |
||
484 | * eliminates the need to adjust parameters by creeping a |
||
485 | * sub-pixel amount into the triangle at each scanline. |
||
486 | */ |
||
487 | |||
488 | { |
||
489 | GLint subTriangle; |
||
490 | GLfixed fxLeftEdge = 0, fxRightEdge = 0; |
||
491 | GLfixed fdxLeftEdge = 0, fdxRightEdge = 0; |
||
492 | GLfixed fError = 0, fdError = 0; |
||
493 | #ifdef PIXEL_ADDRESS |
||
494 | PIXEL_TYPE *pRow = NULL; |
||
495 | GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */ |
||
496 | #endif |
||
497 | #ifdef INTERP_Z |
||
498 | # ifdef DEPTH_TYPE |
||
499 | struct gl_renderbuffer *zrb |
||
500 | = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; |
||
501 | DEPTH_TYPE *zRow = NULL; |
||
502 | GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */ |
||
503 | # endif |
||
504 | GLuint zLeft = 0; |
||
505 | GLfixed fdzOuter = 0, fdzInner; |
||
506 | #endif |
||
507 | #ifdef INTERP_RGB |
||
508 | GLint rLeft = 0, fdrOuter = 0, fdrInner; |
||
509 | GLint gLeft = 0, fdgOuter = 0, fdgInner; |
||
510 | GLint bLeft = 0, fdbOuter = 0, fdbInner; |
||
511 | #endif |
||
512 | #ifdef INTERP_ALPHA |
||
513 | GLint aLeft = 0, fdaOuter = 0, fdaInner; |
||
514 | #endif |
||
515 | #ifdef INTERP_INT_TEX |
||
516 | GLfixed sLeft=0, dsOuter=0, dsInner; |
||
517 | GLfixed tLeft=0, dtOuter=0, dtInner; |
||
518 | #endif |
||
519 | #ifdef INTERP_ATTRIBS |
||
520 | GLfloat wLeft = 0, dwOuter = 0, dwInner; |
||
521 | GLfloat attrLeft[VARYING_SLOT_MAX][4]; |
||
522 | GLfloat daOuter[VARYING_SLOT_MAX][4], daInner[VARYING_SLOT_MAX][4]; |
||
523 | #endif |
||
524 | |||
525 | for (subTriangle=0; subTriangle<=1; subTriangle++) { |
||
526 | EdgeT *eLeft, *eRight; |
||
527 | int setupLeft, setupRight; |
||
528 | int lines; |
||
529 | |||
530 | if (subTriangle==0) { |
||
531 | /* bottom half */ |
||
532 | if (scan_from_left_to_right) { |
||
533 | eLeft = &eMaj; |
||
534 | eRight = &eBot; |
||
535 | lines = eRight->lines; |
||
536 | setupLeft = 1; |
||
537 | setupRight = 1; |
||
538 | } |
||
539 | else { |
||
540 | eLeft = &eBot; |
||
541 | eRight = &eMaj; |
||
542 | lines = eLeft->lines; |
||
543 | setupLeft = 1; |
||
544 | setupRight = 1; |
||
545 | } |
||
546 | } |
||
547 | else { |
||
548 | /* top half */ |
||
549 | if (scan_from_left_to_right) { |
||
550 | eLeft = &eMaj; |
||
551 | eRight = &eTop; |
||
552 | lines = eRight->lines; |
||
553 | setupLeft = 0; |
||
554 | setupRight = 1; |
||
555 | } |
||
556 | else { |
||
557 | eLeft = &eTop; |
||
558 | eRight = &eMaj; |
||
559 | lines = eLeft->lines; |
||
560 | setupLeft = 1; |
||
561 | setupRight = 0; |
||
562 | } |
||
563 | if (lines == 0) |
||
564 | return; |
||
565 | } |
||
566 | |||
567 | if (setupLeft && eLeft->lines > 0) { |
||
568 | const SWvertex *vLower = eLeft->v0; |
||
569 | const GLfixed fsy = eLeft->fsy; |
||
570 | const GLfixed fsx = eLeft->fsx; /* no fractional part */ |
||
571 | const GLfixed fx = FixedCeil(fsx); /* no fractional part */ |
||
572 | const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */ |
||
573 | const GLfixed adjy = (GLfixed) eLeft->adjy; /* SCALED! */ |
||
574 | GLint idxOuter; |
||
575 | GLfloat dxOuter; |
||
576 | GLfixed fdxOuter; |
||
577 | |||
578 | fError = fx - fsx - FIXED_ONE; |
||
579 | fxLeftEdge = fsx - FIXED_EPSILON; |
||
580 | fdxLeftEdge = eLeft->fdxdy; |
||
581 | fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON); |
||
582 | fdError = fdxOuter - fdxLeftEdge + FIXED_ONE; |
||
583 | idxOuter = FixedToInt(fdxOuter); |
||
584 | dxOuter = (GLfloat) idxOuter; |
||
585 | span.y = FixedToInt(fsy); |
||
586 | |||
587 | /* silence warnings on some compilers */ |
||
588 | (void) dxOuter; |
||
589 | (void) adjx; |
||
590 | (void) adjy; |
||
591 | (void) vLower; |
||
592 | |||
593 | #ifdef PIXEL_ADDRESS |
||
594 | { |
||
595 | pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y); |
||
596 | dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE); |
||
597 | /* negative because Y=0 at bottom and increases upward */ |
||
598 | } |
||
599 | #endif |
||
600 | /* |
||
601 | * Now we need the set of parameter (z, color, etc.) values at |
||
602 | * the point (fx, fsy). This gives us properly-sampled parameter |
||
603 | * values that we can step from pixel to pixel. Furthermore, |
||
604 | * although we might have intermediate results that overflow |
||
605 | * the normal parameter range when we step temporarily outside |
||
606 | * the triangle, we shouldn't overflow or underflow for any |
||
607 | * pixel that's actually inside the triangle. |
||
608 | */ |
||
609 | |||
610 | #ifdef INTERP_Z |
||
611 | { |
||
612 | GLfloat z0 = vLower->attrib[VARYING_SLOT_POS][2]; |
||
613 | if (depthBits <= 16) { |
||
614 | /* interpolate fixed-pt values */ |
||
615 | GLfloat tmp = (z0 * FIXED_SCALE |
||
616 | + span.attrStepX[VARYING_SLOT_POS][2] * adjx |
||
617 | + span.attrStepY[VARYING_SLOT_POS][2] * adjy) + FIXED_HALF; |
||
618 | if (tmp < MAX_GLUINT / 2) |
||
619 | zLeft = (GLfixed) tmp; |
||
620 | else |
||
621 | zLeft = MAX_GLUINT / 2; |
||
622 | fdzOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_POS][2] + |
||
623 | dxOuter * span.attrStepX[VARYING_SLOT_POS][2]); |
||
624 | } |
||
625 | else { |
||
626 | /* interpolate depth values w/out scaling */ |
||
627 | zLeft = (GLuint) (z0 + span.attrStepX[VARYING_SLOT_POS][2] * FixedToFloat(adjx) |
||
628 | + span.attrStepY[VARYING_SLOT_POS][2] * FixedToFloat(adjy)); |
||
629 | fdzOuter = (GLint) (span.attrStepY[VARYING_SLOT_POS][2] + |
||
630 | dxOuter * span.attrStepX[VARYING_SLOT_POS][2]); |
||
631 | } |
||
632 | # ifdef DEPTH_TYPE |
||
633 | zRow = (DEPTH_TYPE *) |
||
634 | _swrast_pixel_address(zrb, FixedToInt(fxLeftEdge), span.y); |
||
635 | dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE); |
||
636 | # endif |
||
637 | } |
||
638 | #endif |
||
639 | #ifdef INTERP_RGB |
||
640 | if (ctx->Light.ShadeModel == GL_SMOOTH) { |
||
641 | rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP]) |
||
642 | + span.attrStepX[VARYING_SLOT_COL0][0] * adjx |
||
643 | + span.attrStepY[VARYING_SLOT_COL0][0] * adjy) + FIXED_HALF; |
||
644 | gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP]) |
||
645 | + span.attrStepX[VARYING_SLOT_COL0][1] * adjx |
||
646 | + span.attrStepY[VARYING_SLOT_COL0][1] * adjy) + FIXED_HALF; |
||
647 | bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP]) |
||
648 | + span.attrStepX[VARYING_SLOT_COL0][2] * adjx |
||
649 | + span.attrStepY[VARYING_SLOT_COL0][2] * adjy) + FIXED_HALF; |
||
650 | fdrOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][0] |
||
651 | + dxOuter * span.attrStepX[VARYING_SLOT_COL0][0]); |
||
652 | fdgOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][1] |
||
653 | + dxOuter * span.attrStepX[VARYING_SLOT_COL0][1]); |
||
654 | fdbOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][2] |
||
655 | + dxOuter * span.attrStepX[VARYING_SLOT_COL0][2]); |
||
656 | # ifdef INTERP_ALPHA |
||
657 | aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP]) |
||
658 | + span.attrStepX[VARYING_SLOT_COL0][3] * adjx |
||
659 | + span.attrStepY[VARYING_SLOT_COL0][3] * adjy) + FIXED_HALF; |
||
660 | fdaOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][3] |
||
661 | + dxOuter * span.attrStepX[VARYING_SLOT_COL0][3]); |
||
662 | # endif |
||
663 | } |
||
664 | else { |
||
665 | ASSERT(ctx->Light.ShadeModel == GL_FLAT); |
||
666 | rLeft = ChanToFixed(v2->color[RCOMP]); |
||
667 | gLeft = ChanToFixed(v2->color[GCOMP]); |
||
668 | bLeft = ChanToFixed(v2->color[BCOMP]); |
||
669 | fdrOuter = fdgOuter = fdbOuter = 0; |
||
670 | # ifdef INTERP_ALPHA |
||
671 | aLeft = ChanToFixed(v2->color[ACOMP]); |
||
672 | fdaOuter = 0; |
||
673 | # endif |
||
674 | } |
||
675 | #endif /* INTERP_RGB */ |
||
676 | |||
677 | |||
678 | #ifdef INTERP_INT_TEX |
||
679 | { |
||
680 | GLfloat s0, t0; |
||
681 | s0 = vLower->attrib[VARYING_SLOT_TEX0][0] * S_SCALE; |
||
682 | sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][0] * adjx |
||
683 | + span.attrStepY[VARYING_SLOT_TEX0][0] * adjy) + FIXED_HALF; |
||
684 | dsOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][0] |
||
685 | + dxOuter * span.attrStepX[VARYING_SLOT_TEX0][0]); |
||
686 | |||
687 | t0 = vLower->attrib[VARYING_SLOT_TEX0][1] * T_SCALE; |
||
688 | tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][1] * adjx |
||
689 | + span.attrStepY[VARYING_SLOT_TEX0][1] * adjy) + FIXED_HALF; |
||
690 | dtOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][1] |
||
691 | + dxOuter * span.attrStepX[VARYING_SLOT_TEX0][1]); |
||
692 | } |
||
693 | #endif |
||
694 | #ifdef INTERP_ATTRIBS |
||
695 | { |
||
696 | const GLuint attr = VARYING_SLOT_POS; |
||
697 | wLeft = vLower->attrib[VARYING_SLOT_POS][3] |
||
698 | + (span.attrStepX[attr][3] * adjx |
||
699 | + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE); |
||
700 | dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3]; |
||
701 | } |
||
702 | ATTRIB_LOOP_BEGIN |
||
703 | const GLfloat invW = vLower->attrib[VARYING_SLOT_POS][3]; |
||
704 | if (swrast->_InterpMode[attr] == GL_FLAT) { |
||
705 | GLuint c; |
||
706 | for (c = 0; c < 4; c++) { |
||
707 | attrLeft[attr][c] = v2->attrib[attr][c] * invW; |
||
708 | daOuter[attr][c] = 0.0; |
||
709 | } |
||
710 | } |
||
711 | else { |
||
712 | GLuint c; |
||
713 | for (c = 0; c < 4; c++) { |
||
714 | const GLfloat a = vLower->attrib[attr][c] * invW; |
||
715 | attrLeft[attr][c] = a + ( span.attrStepX[attr][c] * adjx |
||
716 | + span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE); |
||
717 | daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c]; |
||
718 | } |
||
719 | } |
||
720 | ATTRIB_LOOP_END |
||
721 | #endif |
||
722 | } /*if setupLeft*/ |
||
723 | |||
724 | |||
725 | if (setupRight && eRight->lines>0) { |
||
726 | fxRightEdge = eRight->fsx - FIXED_EPSILON; |
||
727 | fdxRightEdge = eRight->fdxdy; |
||
728 | } |
||
729 | |||
730 | if (lines==0) { |
||
731 | continue; |
||
732 | } |
||
733 | |||
734 | |||
735 | /* Rasterize setup */ |
||
736 | #ifdef PIXEL_ADDRESS |
||
737 | dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE); |
||
738 | #endif |
||
739 | #ifdef INTERP_Z |
||
740 | # ifdef DEPTH_TYPE |
||
741 | dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE); |
||
742 | # endif |
||
743 | fdzInner = fdzOuter + span.zStep; |
||
744 | #endif |
||
745 | #ifdef INTERP_RGB |
||
746 | fdrInner = fdrOuter + span.redStep; |
||
747 | fdgInner = fdgOuter + span.greenStep; |
||
748 | fdbInner = fdbOuter + span.blueStep; |
||
749 | #endif |
||
750 | #ifdef INTERP_ALPHA |
||
751 | fdaInner = fdaOuter + span.alphaStep; |
||
752 | #endif |
||
753 | #ifdef INTERP_INT_TEX |
||
754 | dsInner = dsOuter + span.intTexStep[0]; |
||
755 | dtInner = dtOuter + span.intTexStep[1]; |
||
756 | #endif |
||
757 | #ifdef INTERP_ATTRIBS |
||
758 | dwInner = dwOuter + span.attrStepX[VARYING_SLOT_POS][3]; |
||
759 | ATTRIB_LOOP_BEGIN |
||
760 | GLuint c; |
||
761 | for (c = 0; c < 4; c++) { |
||
762 | daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c]; |
||
763 | } |
||
764 | ATTRIB_LOOP_END |
||
765 | #endif |
||
766 | |||
767 | while (lines > 0) { |
||
768 | /* initialize the span interpolants to the leftmost value */ |
||
769 | /* ff = fixed-pt fragment */ |
||
770 | const GLint right = FixedToInt(fxRightEdge); |
||
771 | span.x = FixedToInt(fxLeftEdge); |
||
772 | if (right <= span.x) |
||
773 | span.end = 0; |
||
774 | else |
||
775 | span.end = right - span.x; |
||
776 | |||
777 | #ifdef INTERP_Z |
||
778 | span.z = zLeft; |
||
779 | #endif |
||
780 | #ifdef INTERP_RGB |
||
781 | span.red = rLeft; |
||
782 | span.green = gLeft; |
||
783 | span.blue = bLeft; |
||
784 | #endif |
||
785 | #ifdef INTERP_ALPHA |
||
786 | span.alpha = aLeft; |
||
787 | #endif |
||
788 | #ifdef INTERP_INT_TEX |
||
789 | span.intTex[0] = sLeft; |
||
790 | span.intTex[1] = tLeft; |
||
791 | #endif |
||
792 | |||
793 | #ifdef INTERP_ATTRIBS |
||
794 | span.attrStart[VARYING_SLOT_POS][3] = wLeft; |
||
795 | ATTRIB_LOOP_BEGIN |
||
796 | GLuint c; |
||
797 | for (c = 0; c < 4; c++) { |
||
798 | span.attrStart[attr][c] = attrLeft[attr][c]; |
||
799 | } |
||
800 | ATTRIB_LOOP_END |
||
801 | #endif |
||
802 | |||
803 | /* This is where we actually generate fragments */ |
||
804 | /* XXX the test for span.y > 0 _shouldn't_ be needed but |
||
805 | * it fixes a problem on 64-bit Opterons (bug 4842). |
||
806 | */ |
||
807 | if (span.end > 0 && span.y >= 0) { |
||
808 | const GLint len = span.end - 1; |
||
809 | (void) len; |
||
810 | #ifdef INTERP_RGB |
||
811 | CLAMP_INTERPOLANT(red, redStep, len); |
||
812 | CLAMP_INTERPOLANT(green, greenStep, len); |
||
813 | CLAMP_INTERPOLANT(blue, blueStep, len); |
||
814 | #endif |
||
815 | #ifdef INTERP_ALPHA |
||
816 | CLAMP_INTERPOLANT(alpha, alphaStep, len); |
||
817 | #endif |
||
818 | { |
||
819 | RENDER_SPAN( span ); |
||
820 | } |
||
821 | } |
||
822 | |||
823 | /* |
||
824 | * Advance to the next scan line. Compute the |
||
825 | * new edge coordinates, and adjust the |
||
826 | * pixel-center x coordinate so that it stays |
||
827 | * on or inside the major edge. |
||
828 | */ |
||
829 | span.y++; |
||
830 | lines--; |
||
831 | |||
832 | fxLeftEdge += fdxLeftEdge; |
||
833 | fxRightEdge += fdxRightEdge; |
||
834 | |||
835 | fError += fdError; |
||
836 | if (fError >= 0) { |
||
837 | fError -= FIXED_ONE; |
||
838 | |||
839 | #ifdef PIXEL_ADDRESS |
||
840 | pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter); |
||
841 | #endif |
||
842 | #ifdef INTERP_Z |
||
843 | # ifdef DEPTH_TYPE |
||
844 | zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter); |
||
845 | # endif |
||
846 | zLeft += fdzOuter; |
||
847 | #endif |
||
848 | #ifdef INTERP_RGB |
||
849 | rLeft += fdrOuter; |
||
850 | gLeft += fdgOuter; |
||
851 | bLeft += fdbOuter; |
||
852 | #endif |
||
853 | #ifdef INTERP_ALPHA |
||
854 | aLeft += fdaOuter; |
||
855 | #endif |
||
856 | #ifdef INTERP_INT_TEX |
||
857 | sLeft += dsOuter; |
||
858 | tLeft += dtOuter; |
||
859 | #endif |
||
860 | #ifdef INTERP_ATTRIBS |
||
861 | wLeft += dwOuter; |
||
862 | ATTRIB_LOOP_BEGIN |
||
863 | GLuint c; |
||
864 | for (c = 0; c < 4; c++) { |
||
865 | attrLeft[attr][c] += daOuter[attr][c]; |
||
866 | } |
||
867 | ATTRIB_LOOP_END |
||
868 | #endif |
||
869 | } |
||
870 | else { |
||
871 | #ifdef PIXEL_ADDRESS |
||
872 | pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner); |
||
873 | #endif |
||
874 | #ifdef INTERP_Z |
||
875 | # ifdef DEPTH_TYPE |
||
876 | zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner); |
||
877 | # endif |
||
878 | zLeft += fdzInner; |
||
879 | #endif |
||
880 | #ifdef INTERP_RGB |
||
881 | rLeft += fdrInner; |
||
882 | gLeft += fdgInner; |
||
883 | bLeft += fdbInner; |
||
884 | #endif |
||
885 | #ifdef INTERP_ALPHA |
||
886 | aLeft += fdaInner; |
||
887 | #endif |
||
888 | #ifdef INTERP_INT_TEX |
||
889 | sLeft += dsInner; |
||
890 | tLeft += dtInner; |
||
891 | #endif |
||
892 | #ifdef INTERP_ATTRIBS |
||
893 | wLeft += dwInner; |
||
894 | ATTRIB_LOOP_BEGIN |
||
895 | GLuint c; |
||
896 | for (c = 0; c < 4; c++) { |
||
897 | attrLeft[attr][c] += daInner[attr][c]; |
||
898 | } |
||
899 | ATTRIB_LOOP_END |
||
900 | #endif |
||
901 | } |
||
902 | } /*while lines>0*/ |
||
903 | |||
904 | } /* for subTriangle */ |
||
905 | |||
906 | } |
||
907 | } |
||
908 | } |
||
909 | |||
910 | #undef SETUP_CODE |
||
911 | #undef RENDER_SPAN |
||
912 | |||
913 | #undef PIXEL_TYPE |
||
914 | #undef BYTES_PER_ROW |
||
915 | #undef PIXEL_ADDRESS |
||
916 | #undef DEPTH_TYPE |
||
917 | |||
918 | #undef INTERP_Z |
||
919 | #undef INTERP_RGB |
||
920 | #undef INTERP_ALPHA |
||
921 | #undef INTERP_INT_TEX |
||
922 | #undef INTERP_ATTRIBS |
||
923 | |||
924 | #undef S_SCALE |
||
925 | #undef T_SCALE |
||
926 | |||
927 | #undef FixedToDepth |
||
928 | |||
929 | #undef NAME>>>=>>>>>=>=1;>>=>>>>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>><>=Y(vMax)>=Y(vMid)<=Y(vMax)>=>>>> |