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;
16 int32_t z, dz, zslope;
18 int32_t start_idx, end_idx;
21 struct pvertex *tmp = v0;
29 slope = (dx << 8) / dy;
31 r = (v0->r << COLOR_SHIFT);
32 g = (v0->g << COLOR_SHIFT);
33 b = (v0->b << COLOR_SHIFT);
34 dr = (v1->r << COLOR_SHIFT) - r;
35 dg = (v1->g << COLOR_SHIFT) - g;
36 db = (v1->b << COLOR_SHIFT) - b;
37 rslope = (dr << 8) / dy;
38 gslope = (dg << 8) / dy;
39 bslope = (db << 8) / dy;
41 a = (v0->a << COLOR_SHIFT);
42 da = (v1->a << COLOR_SHIFT) - a;
43 aslope = (da << 8) / dy;
44 #endif /* BLEND_ALPHA */
51 uslope = (du << 8) / dy;
52 vslope = (dv << 8) / dy;
57 zslope = (dz << 8) / dy;
60 start_idx = v0->y >> 8;
63 for(i=start_idx; i<end_idx; i++) {
68 /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */
92 return (uint32_t)start_idx | ((uint32_t)(end_idx - 1) << 16);
95 void POLYFILL(struct pvertex *pv, int nverts)
98 int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0;
100 /* the following variables are used for interpolating horizontally accros scanlines */
101 #if defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF)
105 #if !defined(GOURAUD) && !defined(TEXMAP)
106 /* flat version, just pack the color now */
107 color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b);
110 int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
112 int32_t a, da, aslope;
116 int32_t u, v, du, dv, uslope, vslope;
119 int32_t z, dz, zslope;
122 for(i=1; i<nverts; i++) {
123 if(pv[i].y < pv[topidx].y) topidx = i;
124 if(pv[i].y > pv[botidx].y) botidx = i;
128 for(i=0; i<nverts; i++) {
129 int next = NEXTIDX(i);
130 winding += ((pv[next].x - pv[i].x) >> 4) * ((pv[next].y + pv[i].y) >> 4);
133 for(i=0; i<nverts; i++) {
134 int next = NEXTIDX(i);
135 int32_t y0 = pv[i].y;
136 int32_t y1 = pv[next].y;
138 if((y0 >> 8) == (y1 >> 8)) {
142 if(pv[i].x < pv[next].x) {
150 left[idx].x = pv[i0].x;
151 right[idx].x = pv[i1].x;
153 left[idx].r = pv[i0].r << COLOR_SHIFT;
154 left[idx].g = pv[i0].g << COLOR_SHIFT;
155 left[idx].b = pv[i0].b << COLOR_SHIFT;
156 right[idx].r = pv[i1].r << COLOR_SHIFT;
157 right[idx].g = pv[i1].g << COLOR_SHIFT;
158 right[idx].b = pv[i1].b << COLOR_SHIFT;
160 left[idx].a = pv[i0].a << COLOR_SHIFT;
161 right[idx].a = pv[i1].a << COLOR_SHIFT;
162 #endif /* BLEND_ALPHA */
165 left[idx].u = pv[i0].u;
166 left[idx].v = pv[i0].v;
167 right[idx].u = pv[i1].u;
168 right[idx].v = pv[i1].v;
171 left[idx].z = pv[i0].z;
172 right[idx].z = pv[i1].z;
175 if(idx > slbot) slbot = idx;
176 if(idx < sltop) sltop = idx;
179 struct pvertex *edge;
184 edge = y0 > y1 ? left : right;
186 /* counter-clockwise */
187 edge = y0 > y1 ? right : left;
189 res = SCANEDGE(pv + i, pv + next, edge);
190 tmp = (res >> 16) & 0xffff;
191 if(tmp > slbot) slbot = tmp;
192 if((tmp = res & 0xffff) < sltop) {
198 /* calculate the slopes of all attributes across the largest span out
199 * of the three: middle, top, or bottom.
202 #if defined(GOURAUD) || defined(TEXMAP)
203 mid = (sltop + slbot) >> 1;
207 dx = right[mid].x - left[mid].x;
208 if((tmp = right[sltop].x - left[sltop].x) > dx) {
212 if((tmp = right[slbot].x - left[slbot].x) > dx) {
216 if(!dx) dx = 256; /* avoid division by zero */
220 dr = right[mid].r - left[mid].r;
221 dg = right[mid].g - left[mid].g;
222 db = right[mid].b - left[mid].b;
223 rslope = (dr << 8) / dx;
224 gslope = (dg << 8) / dx;
225 bslope = (db << 8) / dx;
227 da = right[mid].a - left[mid].a;
228 aslope = (da << 8) / dx;
229 #endif /* BLEND_ALPHA */
232 du = right[mid].u - left[mid].u;
233 dv = right[mid].v - left[mid].v;
234 uslope = (du << 8) / dx;
235 vslope = (dv << 8) / dx;
238 dz = right[mid].z - left[mid].z;
239 zslope = (dz << 8) / dx;
241 #endif /* !defined(HIGH_QUALITY) */
243 /* for each scanline ... */
244 for(i=sltop; i<=slbot; i++) {
253 pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8);
261 #endif /* BLEND_ALPHA */
269 zptr = pfill_zbuf + i * pfill_fb.width + (x >> 8);
273 #if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF))
274 if(!(dx = right[i].x - left[i].x)) dx = 256;
278 dr = right[i].r - left[i].r;
279 dg = right[i].g - left[i].g;
280 db = right[i].b - left[i].b;
281 rslope = (dr << 8) / dx;
282 gslope = (dg << 8) / dx;
283 bslope = (db << 8) / dx;
285 da = right[i].a - left[i].a;
286 aslope = (da << 8) / dx;
287 #endif /* BLEND_ALPHA */
290 du = right[i].u - left[i].u;
291 dv = right[i].v - left[i].v;
292 uslope = (du << 8) / dx;
293 vslope = (dv << 8) / dx;
296 dz = right[i].z - left[i].z;
297 zslope = (dz << 8) / dx;
299 #endif /* HIGH_QUALITY */
302 /* go across the scanline interpolating if necessary */
303 while(x <= right[i].x) {
304 /*if(x == (180 << 8) && i == 174) {
307 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
310 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
314 int alpha, inv_alpha;
345 /* we upped the color precision to while interpolating the
346 * edges, now drop the extra bits before packing
348 cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
349 cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
350 cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
357 if(cr > 255) cr = 255;
358 if(cg > 255) cg = 255;
359 if(cb > 255) cb = 255;
360 #endif /* BLEND_ALPHA */
364 int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
365 int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
366 g3d_pixel texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
368 /* This is not correct, should be /255, but it's much faster
369 * to shift by 8 (/256), and won't make a huge difference
371 cr = (cr * G3D_UNPACK_R(texel)) >> 8;
372 cg = (cg * G3D_UNPACK_G(texel)) >> 8;
373 cb = (cb * G3D_UNPACK_B(texel)) >> 8;
375 cr = G3D_UNPACK_R(texel);
376 cg = G3D_UNPACK_G(texel);
377 cb = G3D_UNPACK_B(texel);
384 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
385 #if !defined(GOURAUD) && !defined(TEXMAP)
386 /* flat version: cr,cg,cb are uninitialized so far */
395 alpha = a >> COLOR_SHIFT;
399 inv_alpha = 255 - alpha;
400 cr = (cr * alpha + G3D_UNPACK_R(fbcol) * inv_alpha) >> 8;
401 cg = (cg * alpha + G3D_UNPACK_G(fbcol) * inv_alpha) >> 8;
402 cb = (cb * alpha + G3D_UNPACK_B(fbcol) * inv_alpha) >> 8;
403 #else /* !BLEND_ALPHA (so BLEND_ADD) */
404 cr += G3D_UNPACK_R(fbcol);
405 cg += G3D_UNPACK_R(fbcol);
406 cb += G3D_UNPACK_R(fbcol);
408 if(cr > 255) cr = 255;
409 if(cg > 255) cg = 255;
410 if(cb > 255) cb = 255;
411 #endif /* BLEND(ALPHA|ADD) */
413 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
414 color = G3D_PACK_RGB(cr, cg, cb);
417 #ifdef DEBUG_OVERDRAW
418 *pixptr++ += DEBUG_OVERDRAW;