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 /* flat version, just pack the color now */
106 color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b);
109 int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
111 int32_t a, da, aslope;
115 int32_t u, v, du, dv, uslope, vslope;
118 int32_t z, dz, zslope;
121 for(i=1; i<nverts; i++) {
122 if(pv[i].y < pv[topidx].y) topidx = i;
123 if(pv[i].y > pv[botidx].y) botidx = i;
127 for(i=0; i<nverts; i++) {
128 int next = NEXTIDX(i);
129 winding += ((pv[next].x - pv[i].x) >> 4) * ((pv[next].y + pv[i].y) >> 4);
132 for(i=0; i<nverts; i++) {
133 int next = NEXTIDX(i);
134 int32_t y0 = pv[i].y;
135 int32_t y1 = pv[next].y;
137 if((y0 >> 8) == (y1 >> 8)) {
141 if(pv[i].x < pv[next].x) {
149 left[idx].x = pv[i0].x;
150 right[idx].x = pv[i1].x;
152 left[idx].r = pv[i0].r << COLOR_SHIFT;
153 left[idx].g = pv[i0].g << COLOR_SHIFT;
154 left[idx].b = pv[i0].b << COLOR_SHIFT;
155 right[idx].r = pv[i1].r << COLOR_SHIFT;
156 right[idx].g = pv[i1].g << COLOR_SHIFT;
157 right[idx].b = pv[i1].b << COLOR_SHIFT;
159 left[idx].a = pv[i0].a << COLOR_SHIFT;
160 right[idx].a = pv[i1].a << COLOR_SHIFT;
161 #endif /* BLEND_ALPHA */
164 left[idx].u = pv[i0].u;
165 left[idx].v = pv[i0].v;
166 right[idx].u = pv[i1].u;
167 right[idx].v = pv[i1].v;
170 left[idx].z = pv[i0].z;
171 right[idx].z = pv[i1].z;
174 if(idx > slbot) slbot = idx;
175 if(idx < sltop) sltop = idx;
178 struct pvertex *edge;
183 edge = y0 > y1 ? left : right;
185 /* counter-clockwise */
186 edge = y0 > y1 ? right : left;
188 res = SCANEDGE(pv + i, pv + next, edge);
189 tmp = (res >> 16) & 0xffff;
190 if(tmp > slbot) slbot = tmp;
191 if((tmp = res & 0xffff) < sltop) {
197 /* calculate the slopes of all attributes across the largest span out
198 * of the three: middle, top, or bottom.
201 #if defined(GOURAUD) || defined(TEXMAP)
202 mid = (sltop + slbot) >> 1;
206 dx = right[mid].x - left[mid].x;
207 if((tmp = right[sltop].x - left[sltop].x) > dx) {
211 if((tmp = right[slbot].x - left[slbot].x) > dx) {
215 if(!dx) dx = 256; /* avoid division by zero */
219 dr = right[mid].r - left[mid].r;
220 dg = right[mid].g - left[mid].g;
221 db = right[mid].b - left[mid].b;
222 rslope = (dr << 8) / dx;
223 gslope = (dg << 8) / dx;
224 bslope = (db << 8) / dx;
226 da = right[mid].a - left[mid].a;
227 aslope = (da << 8) / dx;
228 #endif /* BLEND_ALPHA */
231 du = right[mid].u - left[mid].u;
232 dv = right[mid].v - left[mid].v;
233 uslope = (du << 8) / dx;
234 vslope = (dv << 8) / dx;
237 dz = right[mid].z - left[mid].z;
238 zslope = (dz << 8) / dx;
240 #endif /* !defined(HIGH_QUALITY) */
242 /* for each scanline ... */
243 for(i=sltop; i<=slbot; i++) {
252 pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8);
260 #endif /* BLEND_ALPHA */
268 zptr = pfill_zbuf + i * pfill_fb.width + (x >> 8);
272 #if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP) || defined(ZBUF))
273 if(!(dx = right[i].x - left[i].x)) dx = 256;
277 dr = right[i].r - left[i].r;
278 dg = right[i].g - left[i].g;
279 db = right[i].b - left[i].b;
280 rslope = (dr << 8) / dx;
281 gslope = (dg << 8) / dx;
282 bslope = (db << 8) / dx;
284 da = right[i].a - left[i].a;
285 aslope = (da << 8) / dx;
286 #endif /* BLEND_ALPHA */
289 du = right[i].u - left[i].u;
290 dv = right[i].v - left[i].v;
291 uslope = (du << 8) / dx;
292 vslope = (dv << 8) / dx;
295 dz = right[i].z - left[i].z;
296 zslope = (dz << 8) / dx;
298 #endif /* HIGH_QUALITY */
301 /* go across the scanline interpolating if necessary */
302 while(x <= right[i].x) {
303 /*if(x == (180 << 8) && i == 174) {
306 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
309 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
313 int alpha, inv_alpha;
344 /* we upped the color precision to while interpolating the
345 * edges, now drop the extra bits before packing
347 cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
348 cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
349 cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
356 if(cr > 255) cr = 255;
357 if(cg > 255) cg = 255;
358 if(cb > 255) cb = 255;
359 #endif /* BLEND_ALPHA */
363 int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
364 int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
365 g3d_pixel texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
367 /* This is not correct, should be /255, but it's much faster
368 * to shift by 8 (/256), and won't make a huge difference
370 cr = (cr * G3D_UNPACK_R(texel)) >> 8;
371 cg = (cg * G3D_UNPACK_G(texel)) >> 8;
372 cb = (cb * G3D_UNPACK_B(texel)) >> 8;
374 cr = G3D_UNPACK_R(texel);
375 cg = G3D_UNPACK_G(texel);
376 cb = G3D_UNPACK_B(texel);
383 #if defined(BLEND_ALPHA) || defined(BLEND_ADD)
384 #if !defined(GOURAUD) && !defined(TEXMAP)
385 /* flat version: cr,cg,cb are uninitialized so far */
394 alpha = a >> COLOR_SHIFT;
398 inv_alpha = 255 - alpha;
399 cr = (cr * alpha + G3D_UNPACK_R(fbcol) * inv_alpha) >> 8;
400 cg = (cg * alpha + G3D_UNPACK_G(fbcol) * inv_alpha) >> 8;
401 cb = (cb * alpha + G3D_UNPACK_B(fbcol) * inv_alpha) >> 8;
402 #else /* !BLEND_ALPHA (so BLEND_ADD) */
403 cr += G3D_UNPACK_R(fbcol);
404 cg += G3D_UNPACK_R(fbcol);
405 cb += G3D_UNPACK_R(fbcol);
407 if(cr > 255) cr = 255;
408 if(cg > 255) cg = 255;
409 if(cb > 255) cb = 255;
410 #endif /* BLEND(ALPHA|ADD) */
412 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND_ALPHA) || defined(BLEND_ADD)
413 color = G3D_PACK_RGB(cr, cg, cb);
416 #ifdef DEBUG_OVERDRAW
417 *pixptr++ += DEBUG_OVERDRAW;