7 static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);
8 static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);
9 static void fillspan(unsigned char *dest, int x, int len);
11 void g3d_polyfill(struct g3d_vertex *verts)
13 int i, topidx, botidx, mididx;
15 int32_t v01x, v01y, v02x, v02y;
16 struct g3d_vertex vtmp;
18 /* calculate winding */
19 v01x = verts[1].x - verts[0].x;
20 v01y = verts[1].y - verts[0].y;
21 v02x = verts[2].x - verts[0].x;
22 v02y = verts[2].y - verts[0].y;
23 if(!((v01x * v02y - v02x * v01y) & 0x80000000)) {
29 if(verts[i].y < verts[topidx].y) {
32 if(verts[i].y > verts[botidx].y) {
36 mididx = topidx + 1; if(mididx > 2) mididx = 0;
37 if(mididx == botidx) {
38 if(++mididx > 2) mididx = 0;
41 dy = verts[botidx].y - verts[topidx].y;
44 dx = verts[botidx].x - verts[topidx].x;
45 dym = verts[mididx].y - verts[topidx].y;
46 vtmp.x = muldiv(dx, dym, dy) + verts[topidx].x; /* dx * dym / dy + vtop.x */
47 vtmp.y = verts[mididx].y;
49 if(verts[topidx].y != verts[mididx].y) {
50 filltop(verts + topidx, verts + mididx, &vtmp);
52 if(verts[mididx].y != verts[botidx].y) {
53 fillbot(verts + mididx, &vtmp, verts + botidx);
57 static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
59 struct g3d_vertex *vtmp;
60 int x, line, lasty, len;
61 int32_t xl, xr, dxl, dxr, slopel, sloper, dy;
62 int32_t y0, y1, yoffs;
74 slopel = (dxl << 8) / dy;
75 sloper = (dxr << 8) / dy;
77 y0 = (v0->y + 0x100) & 0xffffff00; /* start from the next scanline */
78 yoffs = y0 - v0->y; /* offset of the next scanline */
79 xl = v0->x + ((yoffs * slopel) >> 8);
80 xr = v0->x + ((yoffs * sloper) >> 8);
84 if(lasty >= YRES) lasty = YRES - 1;
87 fbptr = g3d_fbpixels + line * (XRES >> 2);
89 while(line <= lasty) {
91 len = ((xr + 0x100) >> 8) - (xl >> 8);
92 if(len > 0) fillspan(fbptr, x, len);
103 static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
105 struct g3d_vertex *vtmp;
106 int x, line, lasty, len;
107 int32_t xl, xr, dxl, dxr, slopel, sloper, dy;
108 int32_t y0, y1, yoffs;
109 unsigned char *fbptr;
120 slopel = (dxl << 8) / dy;
121 sloper = (dxr << 8) / dy;
123 y0 = (v0->y + 0x100) & 0xffffff00; /* start from the next scanline */
124 yoffs = y0 - v0->y; /* offset of the next scanline */
125 xl = v0->x + ((yoffs * slopel) >> 8);
126 xr = v1->x + ((yoffs * sloper) >> 8);
130 if(lasty >= YRES) lasty = YRES - 1;
133 fbptr = g3d_fbpixels + line * (XRES >> 2);
135 while(line <= lasty) {
137 len = ((xr + 0x100) >> 8) - (xl >> 8);
138 if(len > 0) fillspan(fbptr, x, len);
149 static void fillspan(unsigned char *dest, int x, int len)
151 unsigned int mask = 0xf;
156 if(len < 4) mask >>= 4 - len;
158 /* handle the start of the span. The x offset alignment affects:
159 * 1. which bitplane to start from, adjust the plane mask accordingly.
160 * 2. how many pixels we write, adjust remaining length accordingly.
163 vid_setmask(mask << align);
164 *dest++ = g3d_curcidx;
167 /* the middle part of the span is all written 4 pixels at a time by
168 * enabling all 4 bit planes.
173 *dest++ = g3d_curcidx;
178 /* handle any leftovers at the end */
180 mask = 0xf >> (4 - len);