move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_scale_smooth.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #include "evas_common.h"
6 #include "evas_scale_smooth.h"
7 #include "evas_blend_private.h"
8
9
10 static DATA32 **scale_calc_y_points(DATA32 *src, int sw, int sh, int dh);
11 static int     *scale_calc_x_points(int sw, int dw);
12 static int     *scale_calc_a_points(int s, int d);
13
14 static DATA32 **
15 scale_calc_y_points(DATA32 *src, int sw, int sh, int dh)
16 {
17    DATA32 **p;
18    int i, val, inc;
19
20    p = malloc((dh + 1) * sizeof(DATA32 *));
21    if (!p) return NULL;
22    val = 0;
23    inc = (sh << 16) / dh;
24    for (i = 0; i < dh; i++)
25      {
26         p[i] = src + ((val >> 16) * sw);
27         val += inc;
28      }
29    p[i] = p[i - 1];
30    return p;
31 }
32
33 static int *
34 scale_calc_x_points(int sw, int dw)
35 {
36    int *p;
37    int i, val, inc;
38
39    p = malloc((dw + 1) * sizeof(int));
40    if (!p) return NULL;
41    val = 0;
42    inc = (sw << 16) / dw;
43    for (i = 0; i < dw; i++)
44      {
45         p[i] = val >> 16;
46         val += inc;
47      }
48    p[i] = p[i - 1];
49    return p;
50 }
51
52 static int *
53 scale_calc_a_points(int s, int d)
54 {
55    int *p;
56    int i, val, inc;
57
58    p = malloc(d * sizeof(int));
59    if (!p) return NULL;
60    if (d >= s)
61      {
62         val = 0;
63         inc = (s << 16) / d;
64         for (i = 0; i < d; i++)
65           {
66              p[i] = (val >> 8) - ((val >> 8) & 0xffffff00);
67              if ((val >> 16) >= (s - 1)) p[i] = 0;
68              val += inc;
69           }
70      }
71    else
72      {
73         int ap, Cp;
74
75         val = 0;
76         inc = (s << 16) / d;
77         Cp = ((d << 14) / s) + 1;
78         for (i = 0; i < d; i++)
79           {
80              ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
81              p[i] = ap | (Cp << 16);
82              val += inc;
83           }
84      }
85 //   sleep(1);
86    return p;
87 }
88
89 #ifdef BUILD_SCALE_SMOOTH
90 #ifdef BUILD_C
91 EAPI void
92 evas_common_scale_rgba_mipmap_down_2x2_c(DATA32 *src, DATA32 *dst, int src_w, int src_h)
93 {
94    int x, y, dst_w, dst_h;
95    DATA32 *src_ptr, *src_ptr2, *dst_ptr;
96
97    dst_w = src_w >> 1;
98    dst_h = src_h >> 1;
99
100    if (dst_w < 1) dst_w = 1;
101    if (dst_h < 1) dst_h = 1;
102
103    src_ptr = src;
104    src_ptr2 = src + src_w;
105    dst_ptr = dst;
106    for (y = 0; y < dst_h; y++)
107      {
108         src_ptr = src + (y * src_w * 2);
109         src_ptr2 = src_ptr + src_w;
110         for (x = 0; x < dst_w; x++)
111           {
112              R_VAL(dst_ptr) = (R_VAL(src_ptr) + R_VAL(src_ptr + 1) + R_VAL(src_ptr2) + R_VAL(src_ptr2 + 1)) >> 2;
113              G_VAL(dst_ptr) = (G_VAL(src_ptr) + G_VAL(src_ptr + 1) + G_VAL(src_ptr2) + G_VAL(src_ptr2 + 1)) >> 2;
114              B_VAL(dst_ptr) = (B_VAL(src_ptr) + B_VAL(src_ptr + 1) + B_VAL(src_ptr2) + B_VAL(src_ptr2 + 1)) >> 2;
115              A_VAL(dst_ptr) = (A_VAL(src_ptr) + A_VAL(src_ptr + 1) + A_VAL(src_ptr2) + A_VAL(src_ptr2 + 1)) >> 2;
116
117              src_ptr+=2;
118              src_ptr2+=2;
119              dst_ptr++;
120           }
121      }
122 }
123 #endif
124 #endif
125
126 #ifdef BUILD_SCALE_SMOOTH
127 #ifdef BUILD_C
128 EAPI void
129 evas_common_scale_rgba_mipmap_down_2x1_c(DATA32 *src, DATA32 *dst, int src_w, int src_h)
130 {
131    int x, y, dst_w, dst_h;
132    DATA32 *src_ptr, *dst_ptr;
133
134    dst_w = src_w >> 1;
135    dst_h = src_h >> 1;
136
137    if (dst_w < 1) dst_w = 1;
138    if (dst_h < 1) dst_h = 1;
139
140    src_ptr = src;
141    dst_ptr = dst;
142    for (y = 0; y < dst_h; y++)
143      {
144         src_ptr = src + (y * src_w * 2);
145         for (x = 0; x < dst_w; x++)
146           {
147              R_VAL(dst_ptr) = (R_VAL(src_ptr) + R_VAL(src_ptr + 1)) >> 1;
148              G_VAL(dst_ptr) = (G_VAL(src_ptr) + G_VAL(src_ptr + 1)) >> 1;
149              B_VAL(dst_ptr) = (B_VAL(src_ptr) + B_VAL(src_ptr + 1)) >> 1;
150              A_VAL(dst_ptr) = (A_VAL(src_ptr) + A_VAL(src_ptr + 1)) >> 1;
151
152              src_ptr+=2;
153              dst_ptr++;
154           }
155      }
156 }
157 #endif
158 #endif
159
160 #ifdef BUILD_SCALE_SMOOTH
161 #ifdef BUILD_C
162 EAPI void
163 evas_common_scale_rgba_mipmap_down_1x2_c(DATA32 *src, DATA32 *dst, int src_w, int src_h)
164 {
165    int x, y, dst_w, dst_h;
166    DATA32 *src_ptr, *src_ptr2, *dst_ptr;
167
168    dst_w = src_w >> 1;
169    dst_h = src_h >> 1;
170
171    if (dst_w < 1) dst_w = 1;
172    if (dst_h < 1) dst_h = 1;
173
174    src_ptr = src;
175    src_ptr2 = src + src_w;
176    dst_ptr = dst;
177    for (y = 0; y < dst_h; y++)
178      {
179         src_ptr = src + (y * src_w * 2);
180         src_ptr2 = src_ptr + src_w;
181         for (x = 0; x < dst_w; x++)
182           {
183              R_VAL(dst_ptr) = (R_VAL(src_ptr) + R_VAL(src_ptr2)) >> 1;
184              G_VAL(dst_ptr) = (G_VAL(src_ptr) + G_VAL(src_ptr2)) >> 1;
185              B_VAL(dst_ptr) = (B_VAL(src_ptr) + B_VAL(src_ptr2)) >> 1;
186              A_VAL(dst_ptr) = (A_VAL(src_ptr) + A_VAL(src_ptr2)) >> 1;
187
188              src_ptr+=2;
189              src_ptr2+=2;
190              dst_ptr++;
191           }
192      }
193 }
194 #endif
195 #endif
196
197 #ifdef BUILD_SCALE_SMOOTH
198 #ifdef BUILD_C
199 EAPI void
200 evas_common_scale_rgb_mipmap_down_2x2_c(DATA32 *src, DATA32 *dst, int src_w, int src_h)
201 {
202    int x, y, dst_w, dst_h;
203    DATA32 *src_ptr, *src_ptr2, *dst_ptr;
204
205    dst_w = src_w >> 1;
206    dst_h = src_h >> 1;
207
208    if (dst_w < 1) dst_w = 1;
209    if (dst_h < 1) dst_h = 1;
210
211    src_ptr = src;
212    src_ptr2 = src + src_w;
213    dst_ptr = dst;
214    for (y = 0; y < dst_h; y++)
215      {
216         for (x = 0; x < dst_w; x++)
217           {
218              R_VAL(dst_ptr) = (R_VAL(src_ptr) + R_VAL(src_ptr + 1) + R_VAL(src_ptr2) + R_VAL(src_ptr2 + 1)) >> 2;
219              G_VAL(dst_ptr) = (G_VAL(src_ptr) + G_VAL(src_ptr + 1) + G_VAL(src_ptr2) + G_VAL(src_ptr2 + 1)) >> 2;
220              B_VAL(dst_ptr) = (B_VAL(src_ptr) + B_VAL(src_ptr + 1) + B_VAL(src_ptr2) + B_VAL(src_ptr2 + 1)) >> 2;
221              A_VAL(dst_ptr) = 0xff;
222
223              src_ptr+=2;
224              src_ptr2+=2;
225              dst_ptr++;
226           }
227         src_ptr += src_w;
228         src_ptr2 += src_w;
229      }
230 }
231 #endif
232 #endif
233
234 #ifdef BUILD_SCALE_SMOOTH
235 #ifdef BUILD_C
236 EAPI void
237 evas_common_scale_rgb_mipmap_down_2x1_c(DATA32 *src, DATA32 *dst, int src_w, int src_h)
238 {
239    int x, y, dst_w, dst_h;
240    DATA32 *src_ptr, *dst_ptr;
241
242    dst_w = src_w >> 1;
243    dst_h = src_h >> 1;
244
245    if (dst_w < 1) dst_w = 1;
246    if (dst_h < 1) dst_h = 1;
247
248    src_ptr = src;
249    dst_ptr = dst;
250    for (y = 0; y < dst_h; y++)
251      {
252         for (x = 0; x < dst_w; x++)
253           {
254              R_VAL(dst_ptr) = (R_VAL(src_ptr) + R_VAL(src_ptr + 1)) >> 1;
255              G_VAL(dst_ptr) = (G_VAL(src_ptr) + G_VAL(src_ptr + 1)) >> 1;
256              B_VAL(dst_ptr) = (B_VAL(src_ptr) + B_VAL(src_ptr + 1)) >> 1;
257              A_VAL(dst_ptr) = 0xff;
258
259              src_ptr+=2;
260              dst_ptr++;
261           }
262         src_ptr += src_w;
263      }
264 }
265 #endif
266 #endif
267
268 #ifdef BUILD_SCALE_SMOOTH
269 #ifdef BUILD_C
270 EAPI void
271 evas_common_scale_rgb_mipmap_down_1x2_c(DATA32 *src, DATA32 *dst, int src_w, int src_h)
272 {
273    int x, y, dst_w, dst_h;
274    DATA32 *src_ptr, *src_ptr2, *dst_ptr;
275
276    dst_w = src_w >> 1;
277    dst_h = src_h >> 1;
278
279    if (dst_w < 1) dst_w = 1;
280    if (dst_h < 1) dst_h = 1;
281
282    src_ptr = src;
283    src_ptr2 = src + src_w;
284    dst_ptr = dst;
285    for (y = 0; y < dst_h; y++)
286      {
287         for (x = 0; x < dst_w; x++)
288           {
289              R_VAL(dst_ptr) = (R_VAL(src_ptr) + R_VAL(src_ptr2)) >> 1;
290              G_VAL(dst_ptr) = (G_VAL(src_ptr) + G_VAL(src_ptr2)) >> 1;
291              B_VAL(dst_ptr) = (B_VAL(src_ptr) + B_VAL(src_ptr2)) >> 1;
292              A_VAL(dst_ptr) = 0xff;
293
294              src_ptr+=2;
295              src_ptr2+=2;
296              dst_ptr++;
297           }
298         src_ptr += src_w;
299         src_ptr2 += src_w;
300      }
301 }
302 #endif
303 #endif
304
305 #ifdef BUILD_SCALE_SMOOTH
306 #ifdef BUILD_MMX
307 EAPI void
308 evas_common_scale_rgba_mipmap_down_2x2_mmx(DATA32 *src, DATA32 *dst, int src_w, int src_h)
309 {
310    int x, y, dst_w, dst_h;
311    DATA32 *src_ptr, *src_ptr2, *dst_ptr;
312
313    dst_w = src_w >> 1;
314    dst_h = src_h >> 1;
315
316    if (dst_w < 1) dst_w = 1;
317    if (dst_h < 1) dst_h = 1;
318
319    src_ptr = src;
320    src_ptr2 = src + src_w;
321    dst_ptr = dst;
322    for (y = 0; y < dst_h; y++)
323      {
324         src_ptr = src + (y * src_w * 2);
325         src_ptr2 = src_ptr + src_w;
326         for (x = 0; x < dst_w; x++)
327           {
328              punpcklbw_m2r(src_ptr[0], mm0);
329              punpcklbw_m2r(src_ptr[1], mm1);
330              punpcklbw_m2r(src_ptr2[0], mm2);
331              punpcklbw_m2r(src_ptr2[1], mm3);
332              psrlw_i2r(8, mm0);
333              psrlw_i2r(8, mm1);
334              psrlw_i2r(8, mm2);
335              psrlw_i2r(8, mm3);
336              paddw_r2r(mm1, mm0);
337              paddw_r2r(mm2, mm0);
338              paddw_r2r(mm3, mm0);
339              psrlw_i2r(2, mm0);
340              packuswb_r2r(mm0, mm0);
341              movd_r2m(mm0, dst_ptr[0]);
342
343              src_ptr+=2;
344              src_ptr2+=2;
345              dst_ptr++;
346           }
347      }
348 }
349 #endif
350 #endif
351
352 #ifdef BUILD_SCALE_SMOOTH
353 #ifdef BUILD_MMX
354 EAPI void
355 evas_common_scale_rgba_mipmap_down_2x1_mmx(DATA32 *src, DATA32 *dst, int src_w, int src_h)
356 {
357    int x, y, dst_w, dst_h;
358    DATA32 *src_ptr, *dst_ptr;
359
360    dst_w = src_w >> 1;
361    dst_h = src_h >> 1;
362
363    if (dst_w < 1) dst_w = 1;
364    if (dst_h < 1) dst_h = 1;
365
366    src_ptr = src;
367    dst_ptr = dst;
368    for (y = 0; y < dst_h; y++)
369      {
370         src_ptr = src + (y * src_w * 2);
371         for (x = 0; x < dst_w; x++)
372           {
373              punpcklbw_m2r(src_ptr[0], mm0);
374              punpcklbw_m2r(src_ptr[1], mm1);
375              psrlw_i2r(8, mm0);
376              psrlw_i2r(8, mm1);
377              paddw_r2r(mm1, mm0);
378              psrlw_i2r(1, mm0);
379              packuswb_r2r(mm0, mm0);
380              movd_r2m(mm0, dst_ptr[0]);
381
382              src_ptr+=2;
383              dst_ptr++;
384           }
385      }
386 }
387 #endif
388 #endif
389
390 #ifdef BUILD_SCALE_SMOOTH
391 #ifdef BUILD_MMX
392 EAPI void
393 evas_common_scale_rgba_mipmap_down_1x2_mmx(DATA32 *src, DATA32 *dst, int src_w, int src_h)
394 {
395    int x, y, dst_w, dst_h;
396    DATA32 *src_ptr, *src_ptr2, *dst_ptr;
397
398    dst_w = src_w >> 1;
399    dst_h = src_h >> 1;
400
401    if (dst_w < 1) dst_w = 1;
402    if (dst_h < 1) dst_h = 1;
403
404    src_ptr = src;
405    src_ptr2 = src + src_w;
406    dst_ptr = dst;
407    for (y = 0; y < dst_h; y++)
408      {
409         src_ptr = src + (y * src_w * 2);
410         src_ptr2 = src_ptr + src_w;
411         for (x = 0; x < dst_w; x++)
412           {
413              punpcklbw_m2r(src_ptr[0], mm0);
414              punpcklbw_m2r(src_ptr2[0], mm1);
415              psrlw_i2r(8, mm0);
416              psrlw_i2r(8, mm1);
417              paddw_r2r(mm1, mm0);
418              psrlw_i2r(1, mm0);
419              packuswb_r2r(mm0, mm0);
420              movd_r2m(mm0, dst_ptr[0]);
421
422              src_ptr+=2;
423              src_ptr2+=2;
424              dst_ptr++;
425           }
426      }
427 }
428 #endif
429 #endif
430
431 #ifdef BUILD_SCALE_SMOOTH
432 # ifdef BUILD_MMX
433 #  undef SCALE_FUNC
434 #  define SCALE_FUNC evas_common_scale_rgba_in_to_out_clip_smooth_mmx
435 #  undef SCALE_USING_MMX
436 #  define SCALE_USING_MMX
437 #  include "evas_scale_smooth_scaler.c"
438 # endif
439 # ifdef BUILD_C
440 #  undef SCALE_FUNC
441 #  define SCALE_FUNC evas_common_scale_rgba_in_to_out_clip_smooth_c
442 #  undef SCALE_USING_MMX
443 #  include "evas_scale_smooth_scaler.c"
444 # endif
445 EAPI void
446 evas_common_scale_rgba_in_to_out_clip_smooth(RGBA_Image *src, RGBA_Image *dst,
447                                  RGBA_Draw_Context *dc,
448                                  int src_region_x, int src_region_y,
449                                  int src_region_w, int src_region_h,
450                                  int dst_region_x, int dst_region_y,
451                                  int dst_region_w, int dst_region_h)
452 {
453 # ifdef BUILD_MMX
454    int mmx, sse, sse2;
455 # endif
456    Cutout_Rects *rects;
457    Cutout_Rect  *r;
458    int          c, cx, cy, cw, ch;
459    int          i;
460    /* handle cutouts here! */
461
462    if ((dst_region_w <= 0) || (dst_region_h <= 0)) return;
463    if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
464      return;
465 # ifdef BUILD_MMX
466    evas_common_cpu_can_do(&mmx, &sse, &sse2);
467 # endif
468    /* no cutouts - cut right to the chase */
469    if (!dc->cutout.rects)
470      {
471 # ifdef BUILD_MMX
472         if (mmx)
473           evas_common_scale_rgba_in_to_out_clip_smooth_mmx(src, dst, dc,
474                                                src_region_x, src_region_y,
475                                                src_region_w, src_region_h,
476                                                dst_region_x, dst_region_y,
477                                                dst_region_w, dst_region_h);
478         else
479 # endif
480 # ifdef BUILD_C
481           evas_common_scale_rgba_in_to_out_clip_smooth_c(src, dst, dc,
482                                              src_region_x, src_region_y,
483                                              src_region_w, src_region_h,
484                                              dst_region_x, dst_region_y,
485                                              dst_region_w, dst_region_h);
486 # endif
487         return;
488      }
489    /* save out clip info */
490    c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
491    evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w, dst->cache_entry.h);
492    evas_common_draw_context_clip_clip(dc, dst_region_x, dst_region_y, dst_region_w, dst_region_h);
493    /* our clip is 0 size.. abort */
494    if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
495      {
496         dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
497         return;
498      }
499    rects = evas_common_draw_context_apply_cutouts(dc);
500    for (i = 0; i < rects->active; ++i)
501      {
502         r = rects->rects + i;
503         evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
504 # ifdef BUILD_MMX
505         if (mmx)
506           evas_common_scale_rgba_in_to_out_clip_smooth_mmx(src, dst, dc,
507                                                src_region_x, src_region_y,
508                                                src_region_w, src_region_h,
509                                                dst_region_x, dst_region_y,
510                                                dst_region_w, dst_region_h);
511         else
512 # endif
513 # ifdef BUILD_C
514           evas_common_scale_rgba_in_to_out_clip_smooth_c(src, dst, dc,
515                                              src_region_x, src_region_y,
516                                              src_region_w, src_region_h,
517                                              dst_region_x, dst_region_y,
518                                              dst_region_w, dst_region_h);
519 # endif
520      }
521    evas_common_draw_context_apply_clear_cutouts(rects);
522    /* restore clip info */
523    dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
524 }
525 #endif