deepstone

view src/scantmpl.h @ 40:1fa939507d8b

fast floating point->int conversion
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 15 Sep 2017 05:00:37 +0300
parents 17a5107b6fa4
children
line source
1 static void SCAN_EDGE(VERTEX *v0, VERTEX *v1)
2 {
3 int i, start, end;
4 fixed dx, dy, dfdx;
5 #ifdef INTERP_DEPTH
6 fixed z, dz, dfdz;
7 #endif
8 #ifdef INTERP_ENERGY
9 fixed e, de, dfde;
10 #endif
11 #ifdef INTERP_TEX
12 #ifdef TEXMAP_PERSP_CORRECT
13 fixed w, dw, dfdw;
14 #endif
15 fixed u, v, du, dv, dfdu, dfdv;
16 #endif
17 fixed x;
18 VERTEX *edge;
20 dy = v1->pos.y - v0->pos.y;
21 if(dy < FIXED_EPSILON && dy > -FIXED_EPSILON) {
22 return;
23 }
25 dx = v1->pos.x - v0->pos.x;
26 dfdx = fixed_div(dx, dy);
28 #ifdef INTERP_DEPTH
29 dz = v1->pos.z - v0->pos.z;
30 dfdz = fixed_div(dz, dy);
31 #endif
32 #ifdef INTERP_ENERGY
33 de = v1->energy - v0->energy;
34 dfde = fixed_div(de, dy);
35 #endif
36 #ifdef INTERP_TEX
37 #ifdef TEXMAP_PERSP_CORRECT
38 dw = v1->pos.w - v0->pos.w;
39 dfdw = fixed_div(dw, dy);
40 #endif
42 du = v1->tc.x - v0->tc.x;
43 dv = v1->tc.y - v0->tc.y;
44 dfdu = fixed_div(du, dy);
45 dfdv = fixed_div(dv, dy);
46 #endif
48 if(dy < 0) {
49 VERTEX *tmp = v0;
50 v0 = v1;
51 v1 = tmp;
52 edge = (st->ord == MGL_CCW) ? vright : vleft;
53 } else {
54 edge = (st->ord == MGL_CCW) ? vleft : vright;
55 }
57 start = (int)fixed_round(v0->pos.y);
58 end = (int)fixed_round(v1->pos.y);
60 if(start >= 0) {
62 x = v0->pos.x;
63 #ifdef INTERP_DEPTH
64 z = v0->pos.z;
65 #endif
66 #ifdef INTERP_ENERGY
67 e = v0->energy;
68 #endif
69 #ifdef INTERP_TEX
70 #ifdef TEXMAP_PERSP_CORRECT
71 w = v0->pos.w;
72 #endif
73 u = v0->tc.x;
74 v = v0->tc.y;
75 #endif
76 } else {
77 fixed lines = -v0->pos.y;
79 x = v0->pos.x + fixed_mul(dfdx, lines);
80 #ifdef INTERP_DEPTH
81 z = v0->pos.z + fixed_mul(dfdz, lines);
82 #endif
83 #ifdef INTERP_ENERGY
84 e = v0->energy + fixed_mul(dfde, lines);
85 #endif
86 #ifdef INTERP_TEX
87 #ifdef TEXMAP_PERSP_CORRECT
88 w = v0->pos.w + fixed_mul(dfdw, lines);
89 #endif
90 u = v0->tc.x + fixed_mul(dfdu, lines);
91 v = v0->tc.y + fixed_mul(dfdv, lines);
92 #endif
93 start = 0;
94 }
96 if(end >= fb->height) {
97 end = fb->height - 1;
98 }
101 for(i=start; i<end; i++) {
102 edge[i].pos.x = x;
103 x += dfdx;
105 edge[i].cidx = v0->cidx;
106 #ifdef INTERP_DEPTH
107 edge[i].pos.z = z;
108 z += dfdz;
109 #endif
111 #ifdef INTERP_ENERGY
112 edge[i].energy = e;
113 e += dfde;
114 #else
115 edge[i].energy = v0->energy;
116 #endif
118 #ifdef INTERP_TEX
119 #ifdef TEXMAP_PERSP_CORRECT
120 edge[i].pos.w = w;
121 w += dfdw;
122 #endif
124 edge[i].tc.x = u;
125 edge[i].tc.y = v;
126 u += dfdu;
127 v += dfdv;
128 #endif
129 }
130 }
132 static void SCAN_LINE(int y, unsigned char *sline)
133 {
134 int x0, x1, len, tmp, cidx;
135 #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX)
136 int i;
137 fixed x, dx;
138 #endif
139 #ifdef INTERP_DEPTH
140 fixed z, dz, dfdz;
141 #endif
142 #ifdef INTERP_ENERGY
143 fixed e, de, dfde;
144 #endif
145 #ifdef INTERP_TEX
146 unsigned int tx, ty;
147 fixed u, v, du, dv, dfdu, dfdv;
148 fixed w, dw, dfdw;
149 fixed tu, tv;
150 #endif
151 VERTEX *left, *right;
153 x0 = (int)fixed_round(vleft[y].pos.x);
154 x1 = (int)fixed_round(vright[y].pos.x);
156 if(x1 < x0) {
157 if(IS_ENABLED(st->flags, MGL_CULL_FACE)) {
158 return;
159 }
160 tmp = x0;
161 x0 = x1;
162 x1 = tmp;
164 left = vright;
165 right = vleft;
166 } else {
167 left = vleft;
168 right = vright;
169 }
171 if(x1 >= fb->width) {
172 x1 = fb->width - 1;
173 }
175 cidx = left[y].cidx;
176 #if !defined(INTERP_DEPTH) && !defined(INTERP_ENERGY) && !defined(INTERP_TEX)
177 if(x0 < 0) x0 = 0;
178 len = x1 - x0;
179 assert(len >= 0);
180 /* no interpolation at all, just memset the whole scanline */
181 memset(sline + x0, cidx + fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))), len);
182 #else
183 /* otherwise do a loop and interpolate whatever needs interpolating */
184 x = left[y].pos.x;
185 dx = right[y].pos.x - x;
187 if(dx < fixedf(0.5) && dx > -fixedf(0.5)) {
188 return;
189 }
191 if(x0 >= 0) {
192 #ifdef INTERP_DEPTH
193 z = left[y].pos.z;
194 dz = right[y].pos.z - z;
195 dfdz = fixed_div(dz, dx);
196 #endif
197 #ifdef INTERP_ENERGY
198 e = left[y].energy;
199 de = right[y].energy - e;
200 dfde = fixed_div(de, dx);
201 #endif
202 #ifdef INTERP_TEX
203 #ifdef TEXMAP_PERSP_CORRECT
204 w = left[y].pos.w;
205 dw = right[y].pos.w - w;
206 dfdw = fixed_div(dw, dx);
207 #endif
209 u = left[y].tc.x;
210 v = left[y].tc.y;
211 du = right[y].tc.x - u;
212 dv = right[y].tc.y - v;
213 dfdu = fixed_div(du, dx);
214 dfdv = fixed_div(dv, dx);
215 #endif
216 } else {
217 fixed dist = -left[y].pos.x;
219 #ifdef INTERP_DEPTH
220 dz = right[y].pos.z - left[y].pos.z;
221 dfdz = fixed_div(dz, dx);
222 z = left[y].pos.z + fixed_mul(dfdz, dist);
223 #endif
224 #ifdef INTERP_ENERGY
225 de = right[y].energy - left[y].energy;
226 dfde = fixed_div(de, dx);
227 e = left[y].energy + fixed_mul(dfde, dist);
228 #endif
229 #ifdef INTERP_TEX
230 #ifdef TEXMAP_PERSP_CORRECT
231 dw = right[y].pos.w - left[y].pos.w;
232 dfdw = fixed_div(dw, dx);
233 w = left[y].pos.w + fixed_mul(dfdw, dist);
234 #endif
236 du = right[y].tc.x - left[y].tc.x;
237 dv = right[y].tc.y - left[y].tc.y;
238 dfdu = fixed_div(du, dx);
239 dfdv = fixed_div(dv, dx);
240 u = left[y].tc.x + fixed_mul(dfdu, dist);
241 v = left[y].tc.y + fixed_mul(dfdv, dist);
242 #endif
243 x0 = 0;
244 }
246 len = x1 - x0;
248 for(i=0; i<len; i++) {
249 int c = cidx;
251 #ifdef INTERP_DEPTH
252 long pix = (sline + x0 + i) - fb->pixels;
253 #ifdef RAST_FLOAT
254 /*unsigned short zval = (unsigned short)(z * USHRT_MAX);*/
255 float zn = z + 1.0;
256 unsigned short zval = ((*(long*)&zn) & 0x7fffff) >> 7;
257 #else
258 unsigned short zval = (unsigned short)((z >> 1) & 0xffff);
259 #endif
260 unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix);
262 if(z < 0 || z >= fixedi(1) || zval > *zptr) {
263 #ifdef INTERP_TEX
264 u += dfdu;
265 v += dfdv;
266 #ifdef TEXMAP_PERSP_CORRECT
267 w += dfdw;
268 #endif
269 #endif /* INTERP_TEX */
270 #ifdef INTERP_ENERGY
271 e += dfde;
272 #endif
273 z += dfdz;
274 continue;
275 }
277 *zptr = zval;
278 z += dfdz;
279 #endif
280 #ifdef INTERP_TEX
281 #ifdef TEXMAP_PERSP_CORRECT
282 tu = fixed_div(u, w);
283 tv = fixed_div(v, w);
284 #else
285 tu = u;
286 tv = v;
287 #endif
288 tx = (unsigned int)fixed_int(fixed_mul(tu, fixedi(st->tex.width))) & st->tex.xmask;
289 ty = (unsigned int)fixed_int(fixed_mul(tv, fixedi(st->tex.height))) & st->tex.ymask;
290 c = st->tex.pixels[(ty << st->tex.xshift) + tx];
292 u += dfdu;
293 v += dfdv;
294 #ifdef TEXMAP_PERSP_CORRECT
295 w += dfdw;
296 #endif
297 #endif /* INTERP_TEX */
298 #ifdef INTERP_ENERGY
299 c += fixed_int(fixed_mul(e, fixedi(st->col_range)));
300 e += dfde;
301 #else
302 c += fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range)));
303 #endif
304 sline[x0 + i] = c;
305 }
306 #endif /* flat */
307 }