diff options
author | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
commit | dd7595a3475407a7fa96a97393bae8c5220e8762 (patch) | |
tree | e341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/evas/src/lib/engines/common/evas_map_image.c | |
parent | Add the skeleton. (diff) | |
download | SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2 SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz |
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to 'libraries/evas/src/lib/engines/common/evas_map_image.c')
-rw-r--r-- | libraries/evas/src/lib/engines/common/evas_map_image.c | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/engines/common/evas_map_image.c b/libraries/evas/src/lib/engines/common/evas_map_image.c new file mode 100644 index 0000000..502b2dc --- /dev/null +++ b/libraries/evas/src/lib/engines/common/evas_map_image.c | |||
@@ -0,0 +1,432 @@ | |||
1 | #include "evas_common.h" | ||
2 | #include "evas_blend_private.h" | ||
3 | |||
4 | #ifdef BUILD_SCALE_SMOOTH | ||
5 | # ifdef BUILD_MMX | ||
6 | # undef SCALE_USING_MMX | ||
7 | # define SCALE_USING_MMX | ||
8 | # endif | ||
9 | #endif | ||
10 | |||
11 | #define FPI 8 | ||
12 | #define FPI1 (1 << (FPI)) | ||
13 | #define FPIH (1 << (FPI - 1)) | ||
14 | |||
15 | #define FPFPI1 (1 << (FP + FPI)) | ||
16 | |||
17 | typedef struct _Line Line; | ||
18 | typedef struct _Span Span; | ||
19 | |||
20 | struct _Span | ||
21 | { | ||
22 | int x1, x2; | ||
23 | FPc o1, o2, z1, z2; | ||
24 | FPc u[2], v[2]; | ||
25 | DATA32 col[2]; | ||
26 | }; | ||
27 | |||
28 | struct _Line | ||
29 | { | ||
30 | Span span[2]; | ||
31 | }; | ||
32 | |||
33 | static FPc | ||
34 | _interp(int x1, int x2, int p, FPc u1, FPc u2) | ||
35 | { | ||
36 | FPc u; | ||
37 | |||
38 | x2 -= x1; | ||
39 | p -= x1; | ||
40 | u = u2 - u1; | ||
41 | u = (u * p) / (x2 + 1); | ||
42 | // FIXME: do z persp | ||
43 | return u1 + u; | ||
44 | } | ||
45 | |||
46 | static DATA32 | ||
47 | _interp_col(int x1, int x2, int p, DATA32 col1, DATA32 col2) | ||
48 | { | ||
49 | x2 -= x1; | ||
50 | p -= x1; | ||
51 | p = (p << 8) / (x2 + 1); | ||
52 | // FIXME: do z persp | ||
53 | return INTERP_256(p, col2, col1); | ||
54 | } | ||
55 | |||
56 | static void | ||
57 | _limit(Span *s, int c1, int c2, int nocol) | ||
58 | { | ||
59 | if (s->x1 < c1) | ||
60 | { | ||
61 | s->u[0] = _interp(s->x1, s->x2, c1, s->u[0], s->u[1]); | ||
62 | s->v[0] = _interp(s->x1, s->x2, c1, s->v[0], s->v[1]); | ||
63 | if (!nocol) | ||
64 | s->col[0] = _interp_col(s->x1, s->x2, c1, s->col[0], s->col[1]); | ||
65 | s->x1 = c1; | ||
66 | s->o1 = c1 << FP; | ||
67 | // FIXME: do s->z1 | ||
68 | } | ||
69 | if (s->x2 > c2) | ||
70 | { | ||
71 | s->u[1] = _interp(s->x1, s->x2, c2, s->u[0], s->u[1]); | ||
72 | s->v[1] = _interp(s->x1, s->x2, c2, s->v[0], s->v[1]); | ||
73 | if (!nocol) | ||
74 | s->col[1] = _interp_col(s->x1, s->x2, c2, s->col[0], s->col[1]); | ||
75 | s->x2 = c2; | ||
76 | s->o2 = c2 << FP; | ||
77 | // FIXME: do s->z2 | ||
78 | } | ||
79 | } | ||
80 | |||
81 | // 12.63 % of time - this can improve | ||
82 | static void | ||
83 | _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy __UNUSED__, int cw, int ch __UNUSED__) | ||
84 | { | ||
85 | int i, y, yp, yy; | ||
86 | int py[4]; | ||
87 | int edge[4][4], edge_num, swapped, order[4]; | ||
88 | FPc uv[4][2], u, v, x, h, t, uu, vv; | ||
89 | DATA32 col[4]; | ||
90 | |||
91 | #if 1 // maybe faster on x86? | ||
92 | for (i = 0; i < 4; i++) py[i] = p[i].y >> FP; | ||
93 | # define PY(x) (py[x]) | ||
94 | #else | ||
95 | # define PY(x) (p[x].y >> FP) | ||
96 | #endif | ||
97 | |||
98 | if ((PY(0) == PY(1)) && (PY(0) == PY(2)) && (PY(0) == PY(3))) | ||
99 | { | ||
100 | int leftp, rightp; | ||
101 | int nocol = 1; | ||
102 | |||
103 | leftp = rightp = 0; | ||
104 | for (i = 1; i < 4; i++) | ||
105 | { | ||
106 | if (p[i].x < p[leftp].x) leftp = i; | ||
107 | if (p[i].x > p[rightp].x) rightp = i; | ||
108 | if (p[i].col != 0xffffffff) nocol = 0; | ||
109 | } | ||
110 | for (y = ystart; y <= yend; y++) | ||
111 | { | ||
112 | yp = y - ystart; | ||
113 | if (y == PY(0)) | ||
114 | { | ||
115 | i = 0; | ||
116 | spans[yp].span[i].x1 = p[leftp].x >> FP; | ||
117 | spans[yp].span[i].o1 = p[leftp].x; | ||
118 | spans[yp].span[i].u[0] = p[leftp].u; | ||
119 | spans[yp].span[i].v[0] = p[leftp].v; | ||
120 | spans[yp].span[i].col[0] = p[leftp].col; | ||
121 | spans[yp].span[i].x2 = p[rightp].x >> FP; | ||
122 | spans[yp].span[i].o2 = p[rightp].x; | ||
123 | spans[yp].span[i].u[1] = p[rightp].u; | ||
124 | spans[yp].span[i].v[1] = p[rightp].v; | ||
125 | spans[yp].span[i].col[1] = p[rightp].col; | ||
126 | if ((spans[yp].span[i].x1 >= (cx + cw)) || | ||
127 | (spans[yp].span[i].x2 < cx)) | ||
128 | spans[yp].span[i].x1 = -1; | ||
129 | else | ||
130 | { | ||
131 | _limit(&(spans[yp].span[i]), cx, cx + cw, nocol); | ||
132 | i++; | ||
133 | spans[yp].span[i].x1 = -1; | ||
134 | } | ||
135 | } | ||
136 | else | ||
137 | spans[yp].span[0].x1 = -1; | ||
138 | } | ||
139 | return; | ||
140 | } | ||
141 | for (y = ystart; y <= yend; y++) | ||
142 | { | ||
143 | int nocol = 1; | ||
144 | |||
145 | yp = y - ystart; | ||
146 | edge_num = 0; | ||
147 | for (i = 0; i < 4; i++) | ||
148 | { | ||
149 | if ((PY(i) <= y) && (PY((i + 1) % 4) > y)) | ||
150 | { | ||
151 | edge[edge_num][0] = i; | ||
152 | edge[edge_num][1] = (i + 1) % 4; | ||
153 | edge_num++; | ||
154 | } | ||
155 | else if ((PY((i + 1) % 4) <= y) && (PY(i) > y)) | ||
156 | { | ||
157 | edge[edge_num][0] = (i + 1) % 4; | ||
158 | edge[edge_num][1] = i; | ||
159 | edge_num++; | ||
160 | } | ||
161 | if (p[i].col != 0xffffffff) nocol = 0; | ||
162 | } | ||
163 | // calculate line x points for each edge | ||
164 | for (i = 0; i < edge_num; i++) | ||
165 | { | ||
166 | int e1 = edge[i][0]; | ||
167 | int e2 = edge[i][1]; | ||
168 | FPc t256; | ||
169 | |||
170 | h = (p[e2].y - p[e1].y) >> FP; // height of edge | ||
171 | if (h < 1) h = 1; | ||
172 | t = (((y << FP) + (FP1 / 2) - 1) - p[e1].y) >> FP; | ||
173 | x = p[e2].x - p[e1].x; | ||
174 | x = p[e1].x + ((x * t) / h); | ||
175 | |||
176 | /* | ||
177 | // FIXME: 3d accuracy here | ||
178 | // XXX t needs adjusting. above its a linear interp point | ||
179 | // only. | ||
180 | // | ||
181 | // // FIXME: do in fixed pt. reduce divides | ||
182 | evas_common_cpu_end_opt(); | ||
183 | // | ||
184 | int foc = 512, z0 = 0, px = 320, py = 240; // FIXME: need from map points | ||
185 | // | ||
186 | float focf, hf; | ||
187 | float z1, z2, y1, y2, dz, dy, zt, dydz, yt; | ||
188 | |||
189 | focf = foc; | ||
190 | hf = h; | ||
191 | |||
192 | // adjust for fixed point and focal length and z0 for map | ||
193 | z1 = (p[e1].z >> FP) - z0 + foc; | ||
194 | z2 = (p[e2].z >> FP) - z0 + foc; | ||
195 | // deltas | ||
196 | dz = z1 - z2; | ||
197 | |||
198 | if (dz != 0) | ||
199 | { | ||
200 | int pt; | ||
201 | |||
202 | // adjust for perspective point (being 0 0) | ||
203 | y1 = (p[e1].y >> FP) - py; | ||
204 | y2 = (p[e2].y >> FP) - py; | ||
205 | |||
206 | // correct for x &y not being in world coords - screen coords | ||
207 | y1 = (y1 * z1) / focf; | ||
208 | y2 = (y2 * z2) / focf; | ||
209 | |||
210 | // deltas | ||
211 | dy = y1 - y2; | ||
212 | |||
213 | yt = y - py; | ||
214 | dydz = dy / dz; | ||
215 | |||
216 | zt = (y2 - (dydz * z2)) / ((yt / focf) - dydz); | ||
217 | |||
218 | pt = t; | ||
219 | t = ((z1 - zt) * hf) / dz; | ||
220 | } | ||
221 | */ | ||
222 | u = p[e2].u - p[e1].u; | ||
223 | uu = u >> FP; | ||
224 | if (uu < 0) uu = -uu; | ||
225 | if (uu == h) | ||
226 | { | ||
227 | yy = ((y << FP) - p[e1].y) >> FP; | ||
228 | if (u > 0) | ||
229 | u = p[e1].u + (yy << FP); | ||
230 | else | ||
231 | u = p[e1].u - (yy << FP) - (FP1 - 1); | ||
232 | } | ||
233 | else | ||
234 | { | ||
235 | if (u >= 0) | ||
236 | u = p[e1].u + ((u * t) / h); | ||
237 | else | ||
238 | u = p[e1].u + (((u * t) - (FP1 / 2)) / h); | ||
239 | } | ||
240 | |||
241 | v = p[e2].v - p[e1].v; | ||
242 | vv = v >> FP; | ||
243 | if (vv < 0) vv = -vv; | ||
244 | if (vv == h) | ||
245 | { | ||
246 | yy = ((y << FP) - p[e1].y) >> FP; | ||
247 | if (v > 0) | ||
248 | v = p[e1].v + (yy << FP); | ||
249 | else | ||
250 | v = p[e1].v - (yy << FP) - (FP1 - 1); | ||
251 | } | ||
252 | else | ||
253 | { | ||
254 | if (v >= 0) | ||
255 | v = p[e1].v + ((v * t) / h); | ||
256 | else | ||
257 | v = p[e1].v + (((v * t) - (FP1 / 2)) / h); | ||
258 | } | ||
259 | |||
260 | // FIXME: 3d accuracy for color too | ||
261 | t256 = (t << 8) / h; // maybe * 255? | ||
262 | col[i] = INTERP_256(t256, p[e2].col, p[e1].col); | ||
263 | |||
264 | // FIXME: store z persp | ||
265 | uv[i][1] = v; | ||
266 | uv[i][0] = u; | ||
267 | edge[i][2] = x >> FP; | ||
268 | edge[i][3] = x; | ||
269 | // also fill in order | ||
270 | order[i] = i; | ||
271 | } | ||
272 | // sort edges from left to right - bubble. its a small list! | ||
273 | do | ||
274 | { | ||
275 | swapped = 0; | ||
276 | for (i = 0; i < (edge_num - 1); i++) | ||
277 | { | ||
278 | if (edge[order[i]][2] > edge[order[i + 1]][2]) | ||
279 | { | ||
280 | t = order[i]; | ||
281 | order[i] = order[i + 1]; | ||
282 | order[i + 1] = t; | ||
283 | swapped = 1; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | while (swapped); | ||
288 | if (edge_num == 2) | ||
289 | { | ||
290 | i = 0; | ||
291 | spans[yp].span[i].x1 = edge[order[0]][2]; | ||
292 | spans[yp].span[i].o1 = edge[order[0]][3]; | ||
293 | spans[yp].span[i].u[0] = uv[order[0]][0]; | ||
294 | spans[yp].span[i].v[0] = uv[order[0]][1]; | ||
295 | spans[yp].span[i].col[0] = col[order[0]]; | ||
296 | |||
297 | spans[yp].span[i].x2 = edge[order[1]][2]; | ||
298 | spans[yp].span[i].o2 = edge[order[1]][3]; | ||
299 | spans[yp].span[i].u[1] = uv[order[1]][0]; | ||
300 | spans[yp].span[i].v[1] = uv[order[1]][1]; | ||
301 | spans[yp].span[i].col[1] = col[order[1]]; | ||
302 | if ((spans[yp].span[i].x1 >= (cx + cw)) || | ||
303 | (spans[yp].span[i].x2 < cx)) | ||
304 | spans[yp].span[i].x1 = -1; | ||
305 | else | ||
306 | { | ||
307 | _limit(&(spans[yp].span[i]), cx, cx + cw, nocol); | ||
308 | i++; | ||
309 | spans[yp].span[i].x1 = -1; | ||
310 | } | ||
311 | } | ||
312 | else if (edge_num == 4) | ||
313 | { | ||
314 | i = 0; | ||
315 | spans[yp].span[i].x1 = edge[order[0]][2]; | ||
316 | spans[yp].span[i].u[0] = uv[order[0]][0]; | ||
317 | spans[yp].span[i].v[0] = uv[order[0]][1]; | ||
318 | spans[yp].span[i].col[0] = col[order[0]]; | ||
319 | |||
320 | spans[yp].span[i].x2 = edge[order[1]][2]; | ||
321 | spans[yp].span[i].u[1] = uv[order[1]][0]; | ||
322 | spans[yp].span[i].v[1] = uv[order[1]][1]; | ||
323 | spans[yp].span[i].col[1] = col[order[1]]; | ||
324 | if ((spans[yp].span[i].x1 >= (cx + cw)) || | ||
325 | (spans[yp].span[i].x2 < cx)) | ||
326 | spans[yp].span[i].x1 = -1; | ||
327 | else | ||
328 | { | ||
329 | _limit(&(spans[yp].span[i]), cx, cx + cw, nocol); | ||
330 | i++; | ||
331 | } | ||
332 | spans[yp].span[i].x1 = edge[order[2]][2]; | ||
333 | spans[yp].span[i].u[0] = uv[order[2]][0]; | ||
334 | spans[yp].span[i].v[0] = uv[order[2]][1]; | ||
335 | spans[yp].span[i].col[0] = col[order[2]]; | ||
336 | |||
337 | spans[yp].span[i].x2 = edge[order[3]][2]; | ||
338 | spans[yp].span[i].u[1] = uv[order[3]][0]; | ||
339 | spans[yp].span[i].v[1] = uv[order[3]][1]; | ||
340 | spans[yp].span[i].col[1] = col[order[3]]; | ||
341 | if ((spans[yp].span[i].x1 >= (cx + cw)) || | ||
342 | (spans[yp].span[i].x2 < cx)) | ||
343 | spans[yp].span[i].x1 = -1; | ||
344 | else | ||
345 | { | ||
346 | int l = cx; | ||
347 | |||
348 | if (i > 0) l = spans[yp].span[i - 1].x2; | ||
349 | _limit(&(spans[yp].span[i]), l, cx + cw, nocol); | ||
350 | } | ||
351 | } | ||
352 | else | ||
353 | spans[yp].span[0].x1 = -1; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | #ifdef BUILD_SCALE_SMOOTH | ||
358 | # ifdef BUILD_MMX | ||
359 | # undef FUNC_NAME | ||
360 | # define FUNC_NAME evas_common_map_rgba_internal_mmx | ||
361 | # undef SCALE_USING_MMX | ||
362 | # define SCALE_USING_MMX | ||
363 | # include "evas_map_image_internal.c" | ||
364 | # endif | ||
365 | # ifdef BUILD_C | ||
366 | # undef FUNC_NAME | ||
367 | # define FUNC_NAME evas_common_map_rgba_internal | ||
368 | # undef SCALE_USING_MMX | ||
369 | # include "evas_map_image_internal.c" | ||
370 | # endif | ||
371 | #endif | ||
372 | |||
373 | EAPI void | ||
374 | evas_common_map_rgba(RGBA_Image *src, RGBA_Image *dst, | ||
375 | RGBA_Draw_Context *dc, | ||
376 | int npoints __UNUSED__, RGBA_Map_Point *p, | ||
377 | int smooth, int level) | ||
378 | { | ||
379 | #ifdef BUILD_MMX | ||
380 | int mmx, sse, sse2; | ||
381 | #endif | ||
382 | Cutout_Rects *rects; | ||
383 | Cutout_Rect *r; | ||
384 | int c, cx, cy, cw, ch; | ||
385 | int i; | ||
386 | |||
387 | if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888) | ||
388 | evas_cache_image_load_data(&src->cache_entry); | ||
389 | evas_common_image_colorspace_normalize(src); | ||
390 | if (!src->image.data) return; | ||
391 | #ifdef BUILD_MMX | ||
392 | evas_common_cpu_can_do(&mmx, &sse, &sse2); | ||
393 | #endif | ||
394 | if ((!dc->cutout.rects) && (!dc->clip.use)) | ||
395 | { | ||
396 | #ifdef BUILD_MMX | ||
397 | if (mmx) | ||
398 | evas_common_map_rgba_internal_mmx(src, dst, dc, p, smooth, level); | ||
399 | else | ||
400 | #endif | ||
401 | #ifdef BUILD_C | ||
402 | evas_common_map_rgba_internal(src, dst, dc, p, smooth, level); | ||
403 | #endif | ||
404 | return; | ||
405 | } | ||
406 | /* save out clip info */ | ||
407 | c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h; | ||
408 | evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h); | ||
409 | /* our clip is 0 size.. abort */ | ||
410 | if ((dc->clip.w <= 0) || (dc->clip.h <= 0)) | ||
411 | { | ||
412 | dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch; | ||
413 | return; | ||
414 | } | ||
415 | rects = evas_common_draw_context_apply_cutouts(dc); | ||
416 | for (i = 0; i < rects->active; ++i) | ||
417 | { | ||
418 | r = rects->rects + i; | ||
419 | evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h); | ||
420 | #ifdef BUILD_MMX | ||
421 | if (mmx) | ||
422 | evas_common_map_rgba_internal_mmx(src, dst, dc, p, smooth, level); | ||
423 | else | ||
424 | #endif | ||
425 | #ifdef BUILD_C | ||
426 | evas_common_map_rgba_internal(src, dst, dc, p, smooth, level); | ||
427 | #endif | ||
428 | } | ||
429 | evas_common_draw_context_apply_clear_cutouts(rects); | ||
430 | /* restore clip info */ | ||
431 | dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch; | ||
432 | } | ||