setting up to improve the rasterizer
[dosdemo] / src / polyfill.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "polyfill.h"
4 #include "gfxutil.h"
5 #include "demo.h"
6
7 void (*fillfunc[])(struct pvertex*, int) = {
8         polyfill_wire,
9         polyfill_flat,
10         0, 0, 0
11 };
12
13 struct pimage pimg_fb, pimg_texture;
14
15 void polyfill(int mode, struct pvertex *verts, int nverts)
16 {
17 #ifndef NDEBUG
18         if(!fillfunc[mode]) {
19                 fprintf(stderr, "polyfill mode %d not implemented\n", mode);
20                 abort();
21         }
22 #endif
23
24         fillfunc[mode](verts, nverts);
25 }
26
27 void polyfill_wire(struct pvertex *verts, int nverts)
28 {
29         int i, x0, y0, x1, y1;
30         struct pvertex *v = verts;
31         unsigned short color = ((v->r << 8) & 0xf800) |
32                 ((v->g << 3) & 0x7e0) | ((v->b >> 3) & 0x1f);
33
34         for(i=0; i<nverts - 1; i++) {
35                 x0 = v->x >> 8;
36                 y0 = v->y >> 8;
37                 ++v;
38                 x1 = v->x >> 8;
39                 y1 = v->y >> 8;
40                 if(clip_line(&x0, &y0, &x1, &y1, 0, 0, pimg_fb.width, pimg_fb.height)) {
41                         draw_line(x0, y0, x1, y1, color);
42                 }
43         }
44         x0 = verts[0].x >> 8;
45         y0 = verts[0].y >> 8;
46         if(clip_line(&x1, &y1, &x0, &y0, 0, 0, pimg_fb.width, pimg_fb.height)) {
47                 draw_line(x1, y1, x0, y0, color);
48         }
49 }
50
51 #define NEXTIDX(x) (((x) - 1 + nverts) % nverts)
52 #define PREVIDX(x) (((x) + 1) % nverts)
53
54 #define CALC_EDGE(which) \
55         do { \
56                 which##_x = pv[which##_beg].x; \
57                 which##_dx = pv[which##_end].x - pv[which##_beg].x; \
58                 which##_slope = (which##_dx << 8) / which##_dy; \
59         } while(0)
60
61 void polyfill_flat(struct pvertex *pv, int nverts)
62 {
63         int i, sline, x, slen, top = 0;
64         int left_beg, left_end, right_beg, right_end;
65         int32_t left_dy, left_dx, right_dy, right_dx;
66         int32_t left_slope, right_slope;
67         int32_t left_x, right_x, y;
68         uint16_t color = ((pv->r << 8) & 0xf800) | ((pv->g << 3) & 0x7e0) |
69                 ((pv->b >> 3) & 0x1f);
70         uint16_t *pixptr;
71
72         /* find topmost */
73         for(i=1; i<nverts; i++) {
74                 if(pv[i].y < pv[top].y) {
75                         top = i;
76                 }
77         }
78         left_beg = right_beg = top;
79         left_end = PREVIDX(left_beg);
80         right_end = NEXTIDX(right_beg);
81
82         if((left_dy = pv[left_end].y - pv[left_beg].y)) {
83                 CALC_EDGE(left);
84         }
85
86         if((right_dy = pv[right_end].y - pv[right_beg].y)) {
87                 CALC_EDGE(right);
88         }
89
90         y = pv[top].y;
91         sline = pv[top].y >> 8;
92
93         for(;;) {
94                 if(y >= pv[left_end].y) {
95                         while(y >= pv[left_end].y) {
96                                 left_beg = left_end;
97                                 if(left_beg == right_beg) return;
98                                 left_end = PREVIDX(left_end);
99                         }
100
101                         left_dy = pv[left_end].y - pv[left_beg].y;
102                         CALC_EDGE(left);
103                 }
104
105                 if(y >= pv[right_end].y) {
106                         while(y >= pv[right_end].y) {
107                                 right_beg = right_end;
108                                 if(left_beg == right_beg) return;
109                                 right_end = NEXTIDX(right_end);
110                         }
111
112                         right_dy = pv[right_end].y - pv[right_beg].y;
113                         CALC_EDGE(right);
114                 }
115
116                 x = left_x >> 8;
117                 slen = (right_x >> 8) - (left_x >> 8);
118
119                 pixptr = pimg_fb.pixels + sline * pimg_fb.width + x;
120                 for(i=0; i<slen; i++) {
121                         *pixptr++ += 15;
122                 }
123
124                 ++sline;
125                 y += 256;
126                 left_x += left_slope;
127                 right_x += right_slope;
128         }
129 }