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;
10 int32_t u, v, du, dv, uslope, vslope;
12 int32_t start_idx, end_idx;
15 struct pvertex *tmp = v0;
23 slope = (dx << 8) / dy;
25 r = (v0->r << COLOR_SHIFT);
26 g = (v0->g << COLOR_SHIFT);
27 b = (v0->b << COLOR_SHIFT);
28 dr = (v1->r << COLOR_SHIFT) - r;
29 dg = (v1->g << COLOR_SHIFT) - g;
30 db = (v1->b << COLOR_SHIFT) - b;
31 rslope = (dr << 8) / dy;
32 gslope = (dg << 8) / dy;
33 bslope = (db << 8) / dy;
40 uslope = (du << 8) / dy;
41 vslope = (dv << 8) / dy;
44 start_idx = v0->y >> 8;
47 for(i=start_idx; i<end_idx; i++) {
51 /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */
67 return (uint32_t)start_idx | ((uint32_t)(end_idx - 1) << 16);
70 void POLYFILL(struct pvertex *pv, int nverts)
73 int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0;
74 struct pvertex *left, *right;
76 /* the following variables are used for interpolating horizontally accros scanlines */
77 #if defined(GOURAUD) || defined(TEXMAP)
81 /* flat version, just pack the color now */
82 color = PACK_RGB16(pv[0].r, pv[0].g, pv[0].b);
85 int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
88 int32_t u, v, du, dv, uslope, vslope;
91 for(i=1; i<nverts; i++) {
92 if(pv[i].y < pv[topidx].y) topidx = i;
93 if(pv[i].y > pv[botidx].y) botidx = i;
97 for(i=0; i<nverts; i++) {
98 int next = NEXTIDX(i);
99 winding += ((pv[next].x - pv[i].x) >> 4) * ((pv[next].y + pv[i].y) >> 4);
102 /* +1 to avoid crashing due to off-by-one rounding errors in the rasterization */
103 left = alloca((pfill_fb.height + 1) * sizeof *left);
104 right = alloca((pfill_fb.height + 1) * sizeof *right);
106 for(i=0; i<nverts; i++) {
107 int next = NEXTIDX(i);
108 int32_t y0 = pv[i].y;
109 int32_t y1 = pv[next].y;
111 if((y0 >> 8) == (y1 >> 8)) {
115 if(pv[i].x < pv[next].x) {
122 left[idx].x = pv[i0].x;
123 right[idx].x = pv[i1].x;
125 left[idx].r = pv[i0].r << COLOR_SHIFT;
126 left[idx].g = pv[i0].g << COLOR_SHIFT;
127 left[idx].b = pv[i0].b << COLOR_SHIFT;
128 right[idx].r = pv[i1].r << COLOR_SHIFT;
129 right[idx].g = pv[i1].g << COLOR_SHIFT;
130 right[idx].b = pv[i1].b << COLOR_SHIFT;
133 left[idx].u = pv[i0].u;
134 left[idx].v = pv[i0].v;
135 right[idx].u = pv[i1].u;
136 right[idx].v = pv[i1].v;
138 if(idx > slbot) slbot = idx;
139 if(idx < sltop) sltop = idx;
142 struct pvertex *edge;
147 edge = y0 > y1 ? left : right;
150 edge = y0 > y1 ? right : left;
152 res = SCANEDGE(pv + i, pv + next, edge);
153 tmp = (res >> 16) & 0xffff;
154 if(tmp > slbot) slbot = tmp;
155 if((tmp = res & 0xffff) < sltop) {
161 /* calculate the slopes of all attributes across the largest span out
162 * of the three: middle, top, or bottom.
165 #if defined(GOURAUD) || defined(TEXMAP)
166 mid = (sltop + slbot) >> 1;
167 dx = right[mid].x - left[mid].x;
168 if((tmp = right[sltop].x - left[sltop].x) > dx) {
172 if((tmp = right[slbot].x - left[slbot].x) > dx) {
176 if(!dx) dx = 256; /* avoid division by zero */
179 dr = right[mid].r - left[mid].r;
180 dg = right[mid].g - left[mid].g;
181 db = right[mid].b - left[mid].b;
182 rslope = (dr << 8) / dx;
183 gslope = (dg << 8) / dx;
184 bslope = (db << 8) / dx;
187 du = right[mid].u - left[mid].u;
188 dv = right[mid].v - left[mid].v;
189 uslope = (du << 8) / dx;
190 vslope = (dv << 8) / dx;
192 #endif /* !defined(HIGH_QUALITY) */
194 /* for each scanline ... */
195 for(i=sltop; i<=slbot; i++) {
200 pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8);
212 #if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP))
213 if(!(dx = right[i].x - left[i].x)) dx = 256;
216 dr = right[i].r - left[i].r;
217 dg = right[i].g - left[i].g;
218 db = right[i].b - left[i].b;
219 rslope = (dr << 8) / dx;
220 gslope = (dg << 8) / dx;
221 bslope = (db << 8) / dx;
224 du = right[i].u - left[i].u;
225 dv = right[i].v - left[i].v;
226 uslope = (du << 8) / dx;
227 vslope = (dv << 8) / dx;
229 #endif /* HIGH_QUALITY */
231 /* go across the scanline interpolating if necessary */
232 while(x <= right[i].x) {
233 #if defined(GOURAUD) || defined(TEXMAP)
237 /* we upped the color precision to while interpolating the
238 * edges, now drop the extra bits before packing
240 cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
241 cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
242 cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
243 if(cr > 255) cr = 255;
244 if(cg > 255) cg = 255;
245 if(cb > 255) cb = 255;
252 int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
253 int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
254 uint16_t texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
256 /* This is not correct, should be /255, but it's much faster
257 * to shift by 8 (/256), and won't make a huge difference
259 cr = (cr * UNPACK_R16(texel)) >> 8;
260 cg = (cg * UNPACK_G16(texel)) >> 8;
261 cb = (cb * UNPACK_B16(texel)) >> 8;
263 cr = UNPACK_R16(texel);
264 cg = UNPACK_G16(texel);
265 cb = UNPACK_B16(texel);
271 #if defined(GOURAUD) || defined(TEXMAP)
272 color = PACK_RGB16(cr, cg, cb);
275 #ifdef DEBUG_OVERDRAW
276 *pixptr++ += DEBUG_OVERDRAW;