void (*fillfunc[])(struct pvertex*, int) = {
polyfill_wire,
- 0, 0, 0, 0
+ polyfill_flat,
+ 0, 0, 0
};
void polyfill(int mode, struct pvertex *verts, int nverts)
void polyfill_wire(struct pvertex *verts, int nverts)
{
- int i;
+ int i, x0, y0, x1, y1;
struct pvertex *v = verts;
unsigned short color = ((v->r << 8) & 0xf800) |
((v->g << 3) & 0x7e0) | ((v->b >> 3) & 0x1f);
- for(i=0; i<nverts; i++) {
- int x0, y0, x1, y1;
+ for(i=0; i<nverts - 1; i++) {
x0 = v->x >> 8;
y0 = v->y >> 8;
++v;
x1 = v->x >> 8;
y1 = v->y >> 8;
- clip_line(&x0, &y0, &x1, &y1, 0, 0, fb_width, fb_height);
- draw_line(x0, y0, x1, y1, color);
+ if(clip_line(&x0, &y0, &x1, &y1, 0, 0, fb_width, fb_height)) {
+ draw_line(x0, y0, x1, y1, color);
+ }
+ }
+ x0 = verts[0].x >> 8;
+ y0 = verts[0].y >> 8;
+ if(clip_line(&x1, &y1, &x0, &y0, 0, 0, fb_width, fb_height)) {
+ draw_line(x1, y1, x0, y0, color);
+ }
+}
+
+#define NEXTIDX(x) ((x) ? (x) - 1 : nverts - 1)
+#define PREVIDX(x) (((x) + 1) % nverts)
+
+#define CALC_EDGE(which) \
+ do { \
+ which##_x = pv[which##_beg].x; \
+ which##_dx = pv[which##_end].x - pv[which##_beg].x; \
+ which##_slope = (which##_dx << 8) / which##_dy; \
+ } while(0)
+
+void polyfill_flat(struct pvertex *pv, int nverts)
+{
+ int i, sline, x, slen, top = 0;
+ int left_beg, left_end, right_beg, right_end;
+ int32_t left_dy, left_dx, right_dy, right_dx;
+ int32_t left_slope, right_slope;
+ int32_t left_x, right_x, y;
+ uint16_t color = ((pv->r << 8) & 0xf800) | ((pv->g << 3) & 0x7e0) |
+ ((pv->b >> 3) & 0x1f);
+ uint16_t *pixptr;
+
+ /* find topmost */
+ for(i=1; i<nverts; i++) {
+ if(pv[i].y < pv[top].y) {
+ top = i;
+ }
+ }
+ left_beg = right_beg = top;
+ left_end = PREVIDX(left_beg);
+ right_end = NEXTIDX(right_beg);
+
+ if((left_dy = pv[left_end].y - pv[left_beg].y)) {
+ CALC_EDGE(left);
+ }
+
+ if((right_dy = pv[right_end].y - pv[right_beg].y)) {
+ CALC_EDGE(right);
+ }
+
+ y = pv[top].y;
+ sline = pv[top].y >> 8;
+
+ for(;;) {
+ if(y >= pv[left_end].y) {
+ while(y >= pv[left_end].y) {
+ left_beg = left_end;
+ if(left_beg == right_beg) return;
+ left_end = PREVIDX(left_end);
+ }
+
+ left_dy = pv[left_end].y - pv[left_beg].y;
+ CALC_EDGE(left);
+ }
+
+ if(y >= pv[right_end].y) {
+ while(y >= pv[right_end].y) {
+ right_beg = right_end;
+ if(left_beg == right_beg) return;
+ right_end = NEXTIDX(right_end);
+ }
+
+ right_dy = pv[right_end].y - pv[right_beg].y;
+ CALC_EDGE(right);
+ }
+
+ x = left_x >> 8;
+ slen = (right_x >> 8) - (left_x >> 8);
+
+ pixptr = (uint16_t*)fb_pixels + sline * fb_width + x;
+ for(i=0; i<slen; i++) {
+ *pixptr++ = color;
+ }
+
+ ++sline;
+ y += 256;
+ left_x += left_slope;
+ right_x += right_slope;
}
}