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