1 static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex *edge)
4 int32_t x, dx, dy, slope;
6 int r, g, b, dr, dg, db;
7 int32_t rslope, gslope, bslope;
13 int32_t u, v, du, dv, uslope, vslope;
15 int32_t start_idx, end_idx;
18 struct pvertex *tmp = v0;
26 slope = (dx << 8) / dy;
28 r = (v0->r << COLOR_SHIFT);
29 g = (v0->g << COLOR_SHIFT);
30 b = (v0->b << COLOR_SHIFT);
31 dr = (v1->r << COLOR_SHIFT) - r;
32 dg = (v1->g << COLOR_SHIFT) - g;
33 db = (v1->b << COLOR_SHIFT) - b;
34 rslope = (dr << 8) / dy;
35 gslope = (dg << 8) / dy;
36 bslope = (db << 8) / dy;
38 a = (v0->a << COLOR_SHIFT);
39 da = (v1->a << COLOR_SHIFT) - a;
40 aslope = (da << 8) / dy;
41 #endif /* BLEND_ALPHA */
48 uslope = (du << 8) / dy;
49 vslope = (dv << 8) / dy;
52 start_idx = v0->y >> 8;
55 for(i=start_idx; i<end_idx; i++) {
60 /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */
83 return (uint32_t)start_idx | ((uint32_t)(end_idx - 1) << 16);
86 void POLYFILL(struct pvertex *pv, int nverts)
89 int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0;
91 /* the following variables are used for interpolating horizontally accros scanlines */
92 #if defined(GOURAUD) || defined(TEXMAP)
96 /* flat version, just pack the color now */
97 color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b);
100 int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
102 int32_t a, da, aslope;
106 int32_t u, v, du, dv, uslope, vslope;
109 for(i=1; i<nverts; i++) {
110 if(pv[i].y < pv[topidx].y) topidx = i;
111 if(pv[i].y > pv[botidx].y) botidx = i;
115 for(i=0; i<nverts; i++) {
116 int next = NEXTIDX(i);
117 winding += ((pv[next].x - pv[i].x) >> 4) * ((pv[next].y + pv[i].y) >> 4);
120 for(i=0; i<nverts; i++) {
121 int next = NEXTIDX(i);
122 int32_t y0 = pv[i].y;
123 int32_t y1 = pv[next].y;
125 if((y0 >> 8) == (y1 >> 8)) {
129 if(pv[i].x < pv[next].x) {
137 left[idx].x = pv[i0].x;
138 right[idx].x = pv[i1].x;
140 left[idx].r = pv[i0].r << COLOR_SHIFT;
141 left[idx].g = pv[i0].g << COLOR_SHIFT;
142 left[idx].b = pv[i0].b << COLOR_SHIFT;
143 right[idx].r = pv[i1].r << COLOR_SHIFT;
144 right[idx].g = pv[i1].g << COLOR_SHIFT;
145 right[idx].b = pv[i1].b << COLOR_SHIFT;
147 left[idx].a = pv[i0].a << COLOR_SHIFT;
148 right[idx].a = pv[i1].a << COLOR_SHIFT;
149 #endif /* BLEND_ALPHA */
152 left[idx].u = pv[i0].u;
153 left[idx].v = pv[i0].v;
154 right[idx].u = pv[i1].u;
155 right[idx].v = pv[i1].v;
158 if(idx > slbot) slbot = idx;
159 if(idx < sltop) sltop = idx;
162 struct pvertex *edge;
167 edge = y0 > y1 ? left : right;
169 /* counter-clockwise */
170 edge = y0 > y1 ? right : left;
172 res = SCANEDGE(pv + i, pv + next, edge);
173 tmp = (res >> 16) & 0xffff;
174 if(tmp > slbot) slbot = tmp;
175 if((tmp = res & 0xffff) < sltop) {
181 /* calculate the slopes of all attributes across the largest span out
182 * of the three: middle, top, or bottom.
185 #if defined(GOURAUD) || defined(TEXMAP)
186 mid = (sltop + slbot) >> 1;
190 dx = right[mid].x - left[mid].x;
191 if((tmp = right[sltop].x - left[sltop].x) > dx) {
195 if((tmp = right[slbot].x - left[slbot].x) > dx) {
199 if(!dx) dx = 256; /* avoid division by zero */
203 dr = right[mid].r - left[mid].r;
204 dg = right[mid].g - left[mid].g;
205 db = right[mid].b - left[mid].b;
206 rslope = (dr << 8) / dx;
207 gslope = (dg << 8) / dx;
208 bslope = (db << 8) / dx;
210 da = right[mid].a - left[mid].a;
211 aslope = (da << 8) / dx;
212 #endif /* BLEND_ALPHA */
215 du = right[mid].u - left[mid].u;
216 dv = right[mid].v - left[mid].v;
217 uslope = (du << 8) / dx;
218 vslope = (dv << 8) / dx;
220 #endif /* !defined(HIGH_QUALITY) */
222 /* for each scanline ... */
223 for(i=sltop; i<=slbot; i++) {
229 pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8);
237 #endif /* BLEND_ALPHA */
245 #if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP))
246 if(!(dx = right[i].x - left[i].x)) dx = 256;
250 dr = right[i].r - left[i].r;
251 dg = right[i].g - left[i].g;
252 db = right[i].b - left[i].b;
253 rslope = (dr << 8) / dx;
254 gslope = (dg << 8) / dx;
255 bslope = (db << 8) / dx;
257 da = right[i].a - left[i].a;
258 aslope = (da << 8) / dx;
259 #endif /* BLEND_ALPHA */
262 du = right[i].u - left[i].u;
263 dv = right[i].v - left[i].v;
264 uslope = (du << 8) / dx;
265 vslope = (dv << 8) / dx;
267 #endif /* HIGH_QUALITY */
270 /* go across the scanline interpolating if necessary */
271 while(x <= right[i].x) {
272 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
275 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
279 int alpha, inv_alpha;
282 /* we upped the color precision to while interpolating the
283 * edges, now drop the extra bits before packing
285 cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
286 cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
287 cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
294 if(cr > 255) cr = 255;
295 if(cg > 255) cg = 255;
296 if(cb > 255) cb = 255;
297 #endif /* BLEND_ALPHA */
301 int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
302 int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
303 g3d_pixel texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
305 /* This is not correct, should be /255, but it's much faster
306 * to shift by 8 (/256), and won't make a huge difference
308 cr = (cr * G3D_UNPACK_R(texel)) >> 8;
309 cg = (cg * G3D_UNPACK_G(texel)) >> 8;
310 cb = (cb * G3D_UNPACK_B(texel)) >> 8;
312 cr = G3D_UNPACK_R(texel);
313 cg = G3D_UNPACK_G(texel);
314 cb = G3D_UNPACK_B(texel);
321 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
322 #if !defined(GOURAUD) && !defined(TEXMAP)
323 /* flat version: cr,cg,cb are uninitialized so far */
332 alpha = a >> COLOR_SHIFT;
336 inv_alpha = 255 - alpha;
337 cr = (cr * alpha + G3D_UNPACK_R(fbcol) * inv_alpha) >> 8;
338 cg = (cg * alpha + G3D_UNPACK_G(fbcol) * inv_alpha) >> 8;
339 cb = (cb * alpha + G3D_UNPACK_B(fbcol) * inv_alpha) >> 8;
340 #else /* !BLEND_ALPHA (so BLEND_ADD) */
341 cr += G3D_UNPACK_R(fbcol);
342 cg += G3D_UNPACK_R(fbcol);
343 cb += G3D_UNPACK_R(fbcol);
345 if(cr > 255) cr = 255;
346 if(cg > 255) cg = 255;
347 if(cb > 255) cb = 255;
348 #endif /* BLEND(ALPHA|ADD) */
350 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
351 color = G3D_PACK_RGB(cr, cg, cb);
354 #ifdef DEBUG_OVERDRAW
355 *pixptr++ += DEBUG_OVERDRAW;