backported build fixes and warnings cleanup from dos
[dosdemo] / src / polytmpl.h
1 static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex *edge)
2 {
3         int i;
4         int32_t x, dx, dy, slope;
5 #ifdef GOURAUD
6         int r, g, b, dr, dg, db;
7         int32_t rslope, gslope, bslope;
8 #ifdef BLEND
9         int32_t a, da, aslope;
10 #endif
11 #endif  /* GOURAUD */
12 #ifdef TEXMAP
13         int32_t u, v, du, dv, uslope, vslope;
14 #endif
15         int32_t start_idx, end_idx;
16
17         if(v0->y > v1->y) {
18                 struct pvertex *tmp = v0;
19                 v0 = v1;
20                 v1 = tmp;
21         }
22
23         x = v0->x;
24         dy = v1->y - v0->y;
25         dx = v1->x - v0->x;
26         slope = (dx << 8) / dy;
27 #ifdef GOURAUD
28         r = (v0->r << COLOR_SHIFT);
29         g = (v0->g << COLOR_SHIFT);
30         b = (v0->b << COLOR_SHIFT);
31         dr = (v1->r << COLOR_SHIFT) - r;
32         dg = (v1->g << COLOR_SHIFT) - g;
33         db = (v1->b << COLOR_SHIFT) - b;
34         rslope = (dr << 8) / dy;
35         gslope = (dg << 8) / dy;
36         bslope = (db << 8) / dy;
37 #ifdef BLEND
38         a = (v0->a << COLOR_SHIFT);
39         da = (v1->a << COLOR_SHIFT) - a;
40         aslope = (da << 8) / dy;
41 #endif  /* BLEND */
42 #endif  /* GOURAUD */
43 #ifdef TEXMAP
44         u = v0->u;
45         v = v0->v;
46         du = v1->u - v0->u;
47         dv = v1->v - v0->v;
48         uslope = (du << 8) / dy;
49         vslope = (dv << 8) / dy;
50 #endif
51
52         start_idx = v0->y >> 8;
53         end_idx = v1->y >> 8;
54
55         for(i=start_idx; i<end_idx; i++) {
56                 edge[i].x = x;
57                 x += slope;
58 #ifdef GOURAUD
59                 /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */
60                 edge[i].r = r;
61                 edge[i].g = g;
62                 edge[i].b = b;
63                 r += rslope;
64                 g += gslope;
65                 b += bslope;
66 #ifdef BLEND
67                 edge[i].a = a;
68                 a += aslope;
69 #endif
70 #endif  /* GOURAUD */
71 #ifdef TEXMAP
72                 edge[i].u = u;
73                 edge[i].v = v;
74                 u += uslope;
75                 v += vslope;
76 #endif
77         }
78
79         return (uint32_t)start_idx | ((uint32_t)(end_idx - 1) << 16);
80 }
81
82 void POLYFILL(struct pvertex *pv, int nverts)
83 {
84         int i, winding;
85         int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0;
86         struct pvertex *left, *right;
87         g3d_pixel color;
88         /* the following variables are used for interpolating horizontally accros scanlines */
89 #if defined(GOURAUD) || defined(TEXMAP)
90         int mid;
91         int32_t dx, tmp;
92 #else
93         /* flat version, just pack the color now */
94         color = G3D_PACK_RGB(pv[0].r, pv[0].g, pv[0].b);
95 #endif
96 #ifdef GOURAUD
97         int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
98 #ifdef BLEND
99         int32_t a, da, aslope;
100 #endif
101 #endif
102 #ifdef TEXMAP
103         int32_t u, v, du, dv, uslope, vslope;
104 #endif
105
106         for(i=1; i<nverts; i++) {
107                 if(pv[i].y < pv[topidx].y) topidx = i;
108                 if(pv[i].y > pv[botidx].y) botidx = i;
109         }
110
111         winding = 0;
112         for(i=0; i<nverts; i++) {
113                 int next = NEXTIDX(i);
114                 winding += ((pv[next].x - pv[i].x) >> 4) * ((pv[next].y + pv[i].y) >> 4);
115         }
116
117         /* +1 to avoid crashing due to off-by-one rounding errors in the rasterization */
118         left = alloca((pfill_fb.height + 1) * sizeof *left);
119         right = alloca((pfill_fb.height + 1) * sizeof *right);
120
121         for(i=0; i<nverts; i++) {
122                 int next = NEXTIDX(i);
123                 int32_t y0 = pv[i].y;
124                 int32_t y1 = pv[next].y;
125
126                 if((y0 >> 8) == (y1 >> 8)) {
127                         /*if(y0 > y1) {*/
128                                 int i0, i1;
129                                 int idx = y0 >> 8;
130                                 if(pv[i].x < pv[next].x) {
131                                         i0 = i;
132                                         i1 = next;
133                                 } else {
134                                         i0 = next;
135                                         i1 = i;
136                                 }
137                                 left[idx].x = pv[i0].x;
138                                 right[idx].x = pv[i1].x;
139 #ifdef GOURAUD
140                                 left[idx].r = pv[i0].r << COLOR_SHIFT;
141                                 left[idx].g = pv[i0].g << COLOR_SHIFT;
142                                 left[idx].b = pv[i0].b << COLOR_SHIFT;
143                                 right[idx].r = pv[i1].r << COLOR_SHIFT;
144                                 right[idx].g = pv[i1].g << COLOR_SHIFT;
145                                 right[idx].b = pv[i1].b << COLOR_SHIFT;
146 #ifdef BLEND
147                                 left[idx].a = pv[i0].a << COLOR_SHIFT;
148                                 right[idx].a = pv[i1].a << COLOR_SHIFT;
149 #endif  /* BLEND */
150 #endif
151 #ifdef TEXMAP
152                                 left[idx].u = pv[i0].u;
153                                 left[idx].v = pv[i0].v;
154                                 right[idx].u = pv[i1].u;
155                                 right[idx].v = pv[i1].v;
156 #endif
157                                 if(idx > slbot) slbot = idx;
158                                 if(idx < sltop) sltop = idx;
159                         /*}*/
160                 } else {
161                         struct pvertex *edge;
162                         uint32_t res, tmp;
163
164                         if(winding < 0) {
165                                 /* clockwise */
166                                 edge = y0 > y1 ? left : right;
167                         } else {
168                                 /* counter-clockwise */
169                                 edge = y0 > y1 ? right : left;
170                         }
171                         res = SCANEDGE(pv + i, pv + next, edge);
172                         tmp = (res >> 16) & 0xffff;
173                         if(tmp > slbot) slbot = tmp;
174                         if((tmp = res & 0xffff) < sltop) {
175                                 sltop = tmp;
176                         }
177                 }
178         }
179
180         /* calculate the slopes of all attributes across the largest span out
181          * of the three: middle, top, or bottom.
182          */
183 #ifndef HIGH_QUALITY
184 #if defined(GOURAUD) || defined(TEXMAP)
185         mid = (sltop + slbot) >> 1;
186         dx = right[mid].x - left[mid].x;
187         if((tmp = right[sltop].x - left[sltop].x) > dx) {
188                 dx = tmp;
189                 mid = sltop;
190         }
191         if((tmp = right[slbot].x - left[slbot].x) > dx) {
192                 dx = tmp;
193                 mid = slbot;
194         }
195         if(!dx) dx = 256;       /* avoid division by zero */
196 #endif
197 #ifdef GOURAUD
198         dr = right[mid].r - left[mid].r;
199         dg = right[mid].g - left[mid].g;
200         db = right[mid].b - left[mid].b;
201         rslope = (dr << 8) / dx;
202         gslope = (dg << 8) / dx;
203         bslope = (db << 8) / dx;
204 #ifdef BLEND
205         da = right[mid].a - left[mid].a;
206         aslope = (da << 8) / dx;
207 #endif  /* BLEND */
208 #endif
209 #ifdef TEXMAP
210         du = right[mid].u - left[mid].u;
211         dv = right[mid].v - left[mid].v;
212         uslope = (du << 8) / dx;
213         vslope = (dv << 8) / dx;
214 #endif
215 #endif  /* !defined(HIGH_QUALITY) */
216
217         /* for each scanline ... */
218         for(i=sltop; i<=slbot; i++) {
219                 g3d_pixel *pixptr;
220                 int32_t x;
221
222                 x = left[i].x;
223                 pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8);
224
225 #ifdef GOURAUD
226                 r = left[i].r;
227                 g = left[i].g;
228                 b = left[i].b;
229 #ifdef BLEND
230                 a = left[i].a;
231 #endif  /* BLEND */
232 #endif
233 #ifdef TEXMAP
234                 u = left[i].u;
235                 v = left[i].v;
236 #endif
237
238 #if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP))
239                 if(!(dx = right[i].x - left[i].x)) dx = 256;
240
241 #ifdef GOURAUD
242                 dr = right[i].r - left[i].r;
243                 dg = right[i].g - left[i].g;
244                 db = right[i].b - left[i].b;
245                 rslope = (dr << 8) / dx;
246                 gslope = (dg << 8) / dx;
247                 bslope = (db << 8) / dx;
248 #ifdef BLEND
249                 da = right[i].a - left[i].a;
250                 aslope = (da << 8) / dx;
251 #endif  /* BLEND */
252 #endif  /* GOURAUD */
253 #ifdef TEXMAP
254                 du = right[i].u - left[i].u;
255                 dv = right[i].v - left[i].v;
256                 uslope = (du << 8) / dx;
257                 vslope = (dv << 8) / dx;
258 #endif
259 #endif  /* HIGH_QUALITY */
260
261                 /* go across the scanline interpolating if necessary */
262                 while(x <= right[i].x) {
263 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND)
264                         int cr, cg, cb;
265 #endif
266 #ifdef BLEND
267                         g3d_pixel fbcol;
268                         int alpha, inv_alpha;
269 #endif
270 #ifdef GOURAUD
271                         /* we upped the color precision to while interpolating the
272                          * edges, now drop the extra bits before packing
273                          */
274                         cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
275                         cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
276                         cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
277                         r += rslope;
278                         g += gslope;
279                         b += bslope;
280 #ifdef BLEND
281                         a += aslope;
282 #else
283                         if(cr > 255) cr = 255;
284                         if(cg > 255) cg = 255;
285                         if(cb > 255) cb = 255;
286 #endif  /* BLEND */
287 #endif  /* GOURAUD */
288 #ifdef TEXMAP
289                         {
290                                 int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
291                                 int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
292                                 g3d_pixel texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
293 #ifdef GOURAUD
294                                 /* This is not correct, should be /255, but it's much faster
295                                  * to shift by 8 (/256), and won't make a huge difference
296                                  */
297                                 cr = (cr * G3D_UNPACK_R(texel)) >> 8;
298                                 cg = (cg * G3D_UNPACK_G(texel)) >> 8;
299                                 cb = (cb * G3D_UNPACK_B(texel)) >> 8;
300 #else
301                                 cr = G3D_UNPACK_R(texel);
302                                 cg = G3D_UNPACK_G(texel);
303                                 cb = G3D_UNPACK_B(texel);
304 #endif
305                         }
306                         u += uslope;
307                         v += vslope;
308 #endif
309
310 #ifdef BLEND
311 #if !defined(GOURAUD) && !defined(TEXMAP)
312                         /* flat version: cr,cg,cb are uninitialized so far */
313                         cr = pv[0].r;
314                         cg = pv[0].g;
315                         cb = pv[0].b;
316 #endif
317 #ifdef GOURAUD
318                         alpha = a >> COLOR_SHIFT;
319 #else
320                         alpha = pv[0].a;
321 #endif
322                         fbcol = *pixptr;
323                         inv_alpha = 255 - alpha;
324                         cr = (cr * alpha + G3D_UNPACK_R(fbcol) * inv_alpha) >> 8;
325                         cg = (cg * alpha + G3D_UNPACK_G(fbcol) * inv_alpha) >> 8;
326                         cb = (cb * alpha + G3D_UNPACK_B(fbcol) * inv_alpha) >> 8;
327                         if(cr > 255) cr = 255;
328                         if(cg > 255) cg = 255;
329                         if(cb > 255) cb = 255;
330 #endif  /* BLEND */
331
332 #if defined(GOURAUD) || defined(TEXMAP) || defined(BLEND)
333                         color = G3D_PACK_RGB(cr, cg, cb);
334 #endif
335
336 #ifdef DEBUG_OVERDRAW
337                         *pixptr++ += DEBUG_OVERDRAW;
338 #else
339                         *pixptr++ = color;
340 #endif
341                         x += 256;
342                 }
343         }
344 }
345