merged evas image masking code from brett
[framework/uifw/evas.git] / src / lib / engines / common / evas_blit_main.c
1 #include "evas_common.h"
2
3 #if defined BUILD_MMX || defined BUILD_SSE
4 #include "evas_mmx.h"
5 #endif
6
7 #define ALIGN_FIX
8
9 static void evas_common_copy_pixels_c        (DATA32 *src, DATA32 *dst, int len);
10 #ifdef BUILD_MMX
11 static void evas_common_copy_pixels_mmx      (DATA32 *src, DATA32 *dst, int len);
12 static void evas_common_copy_pixels_mmx2     (DATA32 *src, DATA32 *dst, int len);
13 #endif
14 #ifdef BUILD_SSE
15 static void evas_common_copy_pixels_sse/*NB*/ (DATA32 *src, DATA32 *dst, int len);
16 #endif
17
18 #ifdef BUILD_NEON
19 static void evas_common_copy_pixels_neon     (DATA32 *src, DATA32 *dst, int len);
20 static void evas_common_copy_pixels_rev_neon (DATA32 *src, DATA32 *dst, int len);
21 #endif
22
23 static void evas_common_copy_pixels_rev_c           (DATA32 *src, DATA32 *dst, int len);
24 #ifdef BUILD_MMX
25 static void evas_common_copy_pixels_rev_mmx         (DATA32 *src, DATA32 *dst, int len);
26 #endif
27 #ifdef BUILD_SSE
28 static void evas_common_copy_pixels_rev_sse/*NB*/ (DATA32 *src, DATA32 *dst, int len);
29 #endif
30
31 static void evas_common_copy_rev_pixels_c           (DATA32 *src, DATA32 *dst, int len);
32
33
34 EAPI void
35 evas_common_blit_init(void)
36 {
37 }
38
39 EAPI void
40 evas_common_blit_rectangle(const RGBA_Image *src, RGBA_Image *dst, int src_x, int src_y, int w, int h, int dst_x, int dst_y)
41 {
42    int y;
43    Gfx_Func_Copy func;
44    DATA32 *src_ptr, *dst_ptr;
45
46    /* clip clip clip */
47    if (w <= 0) return;
48    if (src_x + w > (int)src->cache_entry.w) w = src->cache_entry.w - src_x;
49    if (w <= 0) return;
50    if (src_x < 0)
51      {
52         dst_x -= src_x;
53         w += src_x;
54         src_x = 0;
55      }
56    if (w <= 0) return;
57
58    if (h <= 0) return;
59    if (src_y + h > (int)src->cache_entry.h) h = src->cache_entry.h - src_y;
60    if (h <= 0) return;
61    if (src_y < 0)
62      {
63         dst_y -= src_y;
64         h += src_y;
65         src_y = 0;
66      }
67    if (h <= 0) return;
68
69    if (w <= 0) return;
70    if (dst_x + w > (int)dst->cache_entry.w) w = dst->cache_entry.w - dst_x;
71    if (w <= 0) return;
72    if (dst_x < 0)
73      {
74         src_x -= dst_x;
75         w += dst_x;
76         dst_x = 0;
77      }
78    if (w <= 0) return;
79
80    if (h <= 0) return;
81    if (dst_y + h > (int)dst->cache_entry.h) h = dst->cache_entry.h - dst_y;
82    if (h <= 0) return;
83    if (dst_y < 0)
84      {
85         src_y -= dst_y;
86         h += dst_y;
87         dst_y = 0;
88      }
89    if (h <= 0) return;
90
91    if (dst == src)
92      {
93         /* src after dst - go forward */
94         if (((src_y * src->cache_entry.w) + src_x) > ((dst_y * dst->cache_entry.w) + dst_x))
95           {
96              func = evas_common_draw_func_copy_get(w, 0);
97              for (y = 0; y < h; y++)
98                {
99                   src_ptr = src->image.data + ((y + src_y) * src->cache_entry.w) + src_x;
100                   dst_ptr = dst->image.data + ((y + dst_y) * dst->cache_entry.w) + dst_x;
101                   func(src_ptr, dst_ptr, w);
102                }
103           }
104         /* reverse */
105         else
106           {
107              func = evas_common_draw_func_copy_get(w, 1);
108              for (y = h - 1; y >= 0; y--)
109                {
110                   src_ptr = src->image.data + ((y + src_y) * src->cache_entry.w) + src_x;
111                   dst_ptr = dst->image.data + ((y + dst_y) * dst->cache_entry.w) + dst_x;
112                   func(src_ptr, dst_ptr, w);
113                }
114           }
115      }
116    else
117      {
118         func = evas_common_draw_func_copy_get(w, 0);
119         for (y = 0; y < h; y++)
120           {
121              src_ptr = src->image.data + ((y + src_y) * src->cache_entry.w) + src_x;
122              dst_ptr = dst->image.data + ((y + dst_y) * dst->cache_entry.w) + dst_x;
123              func(src_ptr, dst_ptr, w);
124           }
125      }
126 }
127
128 /****************************************************************************/
129
130 static void
131 evas_common_copy_rev_pixels_c(DATA32 *src, DATA32 *dst, int len)
132 {
133    DATA32 *dst_end = dst + len;
134
135    src += len - 1;
136    while (dst < dst_end) *dst++ = *src--;
137 }
138
139
140 #ifdef BUILD_NEON
141 static void
142 evas_common_copy_pixels_rev_neon(DATA32 *src, DATA32 *dst, int len)
143 {
144    uint32_t *tmp = (void *)37;
145 #define AP      "evas_common_copy_rev_pixels_neon_"
146    asm volatile (
147                 // Can we do 32 byte?
148                 "andS           %[tmp], %[d], $0x1f     \n\t"
149                 "beq            "AP"quadstart           \n\t"
150
151                 // Can we do at least 16 byte?
152                 "andS           %[tmp], %[d], $0x4      \n\t"
153                 "beq            "AP"dualstart           \n\t"
154
155         // Only once
156         AP"singleloop:                                  \n\t"
157                 "sub            %[s], #4                \n\t"
158                 "vld1.32        d0[0],  [%[s]]          \n\t"
159                 "vst1.32        d0[0],  [%[d]]!         \n\t"
160
161         // Up to 3 times
162         AP"dualstart:                                   \n\t"
163                 "sub            %[tmp], %[e], %[d]      \n\t"
164                 "cmp            %[tmp], #31             \n\t"
165                 "blt            "AP"loopout             \n\t"
166
167                 "andS           %[tmp], %[d], $0x1f     \n\t"
168                 "beq            "AP"quadstart           \n\t"
169
170         AP"dualloop:                                    \n\t"
171                 "sub            %[s], #8                \n\t"
172                 "vldm           %[s], {d0}              \n\t"
173                 "vrev64.32      d1, d0                  \n\t"
174                 "vstm           %[d]!, {d1}             \n\t"
175
176                 "andS           %[tmp], %[d], $0x1f     \n\t"
177                 "bne            "AP"dualloop            \n\t"
178
179
180         AP"quadstart:                                   \n\t"
181                 "sub            %[tmp], %[e], %[d]      \n\t"
182                 "cmp            %[tmp], #32             \n\t"
183                 "blt            "AP"loopout             \n\t"
184
185                 "sub            %[tmp],%[e],#32         \n\t"
186
187         AP "quadloop:                                   \n\t"
188                 "sub            %[s],   #32             \n\t"
189                 "vldm           %[s],   {d0,d1,d2,d3}   \n\t"
190
191                 "vrev64.32      d7,d0                   \n\t"
192                 "vrev64.32      d6,d1                   \n\t"
193                 "vrev64.32      d5,d2                   \n\t"
194                 "vrev64.32      d4,d3                   \n\t"
195
196                 "vstm           %[d]!,  {d4,d5,d6,d7}   \n\t"
197
198                 "cmp            %[tmp], %[d]            \n\t"
199                 "bhi            "AP"quadloop            \n\t"
200
201
202         AP "loopout:                                    \n\t"
203                 "cmp            %[d], %[e]              \n\t"
204                 "beq            "AP"done                \n\t"
205                 "sub            %[tmp],%[e], %[d]       \n\t"
206                 "cmp            %[tmp],$0x04            \n\t"
207                 "beq            "AP"singleloop2         \n\t"
208
209         AP "dualloop2:                                  \n\t"
210                 "sub            %[tmp],%[e],$0x7        \n\t"
211         AP "dualloop2int:                               \n\t"
212                 "sub            %[s], #8                \n\t"
213                 "vldm           %[s], {d0}              \n\t"
214                 "vrev64.32      d1,d0                   \n\t"
215                 "vstm           %[d]!, {d1}             \n\t"
216
217                 "cmp            %[tmp], %[d]            \n\t"
218                 "bhi            "AP"dualloop2int        \n\t"
219
220                 // Single ??
221                 "cmp            %[e], %[d]              \n\t"
222                 "beq            "AP"done                \n\t"
223
224         AP "singleloop2:                                \n\t"
225                 "sub            %[s], #4                \n\t"
226                 "vld1.32        d0[0], [%[s]]           \n\t"
227                 "vst1.32        d0[0], [%[d]]           \n\t"
228
229         AP "done:\n\t"
230
231                 : // No output regs
232                 // Input
233                 : [s] "r" (src + len), [e] "r" (dst + len), [d] "r" (dst),[tmp] "r" (tmp)
234                 // Clobbered
235                 : "q0","q1","q2","q3","0","1","memory"
236    );
237 #undef AP
238
239 }
240 #endif
241
242
243 #ifdef BUILD_C
244 static void
245 evas_common_copy_pixels_c(DATA32 *src, DATA32 *dst, int len)
246 {
247    DATA32 *dst_end = dst + len;
248    
249    while (dst < dst_end) *dst++ = *src++;
250 }
251 #endif
252
253 #ifdef BUILD_MMX
254 static void
255 evas_common_copy_pixels_mmx(DATA32 *src, DATA32 *dst, int len)
256 { // XXX cppcheck: [./src/lib/engines/common/evas_blit_main.c:248]: (error) Invalid number of character ({). Can't process file.
257   // so... wtf? what's wrong with this { ? or anytrhing surrounding it?
258    DATA32 *dst_end, *dst_end_pre;
259 #ifdef ALIGN_FIX
260    intptr_t src_align;
261    intptr_t dst_align;
262    
263    src_align = (intptr_t)src & 0x3f; /* 64 byte alignment */
264    dst_align = (intptr_t)dst & 0x3f; /* 64 byte alignment */
265    
266    if ((src_align != dst_align) ||
267        ((src_align & 0x3) != 0))
268      {
269 #ifdef BUILD_C
270         evas_common_copy_pixels_c(src, dst, len);
271         return;
272      }
273 #endif
274
275    while ((src_align > 0) && (len > 0))
276      {
277         *dst++ = *src++;
278         len--;
279         src_align -= sizeof(DATA32);
280      }
281 #endif /* ALIGN_FIX */
282
283    dst_end = dst + len;
284    dst_end_pre = dst + ((len / 16) * 16);
285
286    while (dst < dst_end_pre)
287      {
288         MOVE_16DWORDS_MMX(src, dst);
289         src += 16;
290         dst += 16;
291      }
292    while (dst < dst_end) *dst++ = *src++;
293 }
294 #endif
295
296 #ifdef BUILD_MMX
297 static void
298 evas_common_copy_pixels_mmx2(DATA32 *src, DATA32 *dst, int len)
299 {
300    DATA32 *dst_end, *dst_end_pre;
301 #ifdef ALIGN_FIX
302    intptr_t src_align;
303    intptr_t dst_align;
304
305    src_align = (intptr_t)src & 0x3f; /* 64 byte alignment */
306    dst_align = (intptr_t)dst & 0x3f; /* 64 byte alignment */
307
308    if ((src_align != dst_align) ||
309        ((src_align & 0x3) != 0))
310      {
311 #ifdef BUILD_C
312         evas_common_copy_pixels_c(src, dst, len);
313 #endif
314         return;
315      }
316
317    while ((src_align > 0) && (len > 0))
318      {
319         *dst++ = *src++;
320         len--;
321         src_align -= sizeof(DATA32);
322      }
323 #endif
324
325    dst_end = dst + len;
326    dst_end_pre = dst + ((len / 16) * 16);
327
328    while (dst < dst_end_pre)
329      {
330         MOVE_16DWORDS_MMX(src, dst);
331         src += 16;
332         dst += 16;
333      }
334    while (dst < dst_end) *dst++ = *src++;
335 }
336 #endif
337
338 #ifdef BUILD_NEON
339 static void
340 evas_common_copy_pixels_neon(DATA32 *src, DATA32 *dst, int len){
341    uint32_t *e,*tmp = (void *)37;
342    e = dst + len;
343 #define AP      "evas_common_copy_pixels_neon_"
344    asm volatile (
345                 // Can we do 32 byte?
346                 "andS           %[tmp], %[d], $0x1f     \n\t"
347                 "beq            "AP"quadstart           \n\t"
348
349                 // Can we do at least 16 byte?
350                 "andS           %[tmp], %[d], $0x4      \n\t"
351                 "beq            "AP"dualstart           \n\t"
352
353         // Only once
354         AP"singleloop:                                  \n\t"
355                 "vld1.32        d0[0],  [%[s]]!         \n\t"
356                 "vst1.32        d0[0],  [%[d]]!         \n\t"
357
358         // Up to 3 times
359         AP"dualstart:                                   \n\t"
360                 "sub            %[tmp], %[e], %[d]      \n\t"
361                 "cmp            %[tmp], #31             \n\t"
362                 "blt            "AP"loopout             \n\t"
363
364                 "andS           %[tmp], %[d], $0x1f     \n\t"
365                 "beq            "AP"quadstart           \n\t"
366
367         AP"dualloop:                                    \n\t"
368                 "vldm           %[s]!, {d0}             \n\t"
369                 "vstm           %[d]!, {d0}             \n\t"
370
371                 "andS           %[tmp], %[d], $0x1f     \n\t"
372                 "bne            "AP"dualloop            \n\t"
373
374
375         AP"quadstart:                                   \n\t"
376                 "sub            %[tmp], %[e], %[d]      \n\t"
377                 "cmp            %[tmp], #64             \n\t"
378                 "blt            "AP"loopout             \n\t"
379
380                 "sub            %[tmp],%[e],#63         \n\t"
381
382         AP "quadloop:                                   \n\t"
383                 "vldm           %[s]!,  {d0,d1,d2,d3}   \n\t"
384                 "vldm           %[s]!,  {d4,d5,d6,d7}   \n\t"
385                 "vstm           %[d]!,  {d0,d1,d2,d3}   \n\t"
386                 "vstm           %[d]!,  {d4,d5,d6,d7}   \n\t"
387
388                 "cmp            %[tmp], %[d]            \n\t"
389                 "bhi            "AP"quadloop            \n\t"
390
391
392         AP "loopout:                                    \n\t"
393                 "cmp            %[d], %[e]              \n\t"
394                 "beq            "AP"done                \n\t"
395                 "sub            %[tmp],%[e], %[d]       \n\t"
396                 "cmp            %[tmp],$0x04            \n\t"
397                 "beq            "AP"singleloop2         \n\t"
398
399         AP "dualloop2:                                  \n\t"
400                 "sub            %[tmp],%[e],$0x7        \n\t"
401         AP "dualloop2int:                               \n\t"
402                 "vldm           %[s]!, {d0}             \n\t"
403                 "vstm           %[d]!, {d0}             \n\t"
404
405                 "cmp            %[tmp], %[d]            \n\t"
406                 "bhi            "AP"dualloop2int        \n\t"
407
408                 // Single ??
409                 "cmp            %[e], %[d]              \n\t"
410                 "beq            "AP"done                \n\t"
411
412         AP "singleloop2:                                \n\t"
413                 "vld1.32        d0[0], [%[s]]           \n\t"
414                 "vst1.32        d0[0], [%[d]]           \n\t"
415
416         AP "done:\n\t"
417
418                 : // No output regs
419                 // Input
420                 : [s] "r" (src), [e] "r" (e), [d] "r" (dst),[tmp] "r" (tmp)
421                 // Clobbered
422                 : "q0","q1","q2","q3","memory"
423    );
424 #undef AP
425
426 }
427 #endif /* BUILD_NEON */
428
429 #ifdef BUILD_SSE
430 static void
431 evas_common_copy_pixels_sse(DATA32 *src, DATA32 *dst, int len)
432 {
433    DATA32 *src_ptr, *dst_ptr, *dst_end_ptr;
434
435    dst_end_ptr = dst + len;
436    dst_end_ptr -= 15;
437    src_ptr = src;
438    dst_ptr = dst;
439    while (dst_ptr < dst_end_ptr)
440      {
441         MOVE_16DWORDS_MMX2(src_ptr, dst_ptr);
442         src_ptr+=16;
443         dst_ptr+=16;
444      }
445    dst_end_ptr = dst + len;
446    while (dst_ptr < dst_end_ptr)
447      {
448         *dst_ptr = *src_ptr;
449         src_ptr++;
450         dst_ptr++;
451      }
452 #if 0
453 #ifdef ALIGN_FIX
454    int src_align;
455    int dst_align;
456
457    src_align = (int)src & 0x3f; /* 64 byte alignment */
458    dst_align = (int)dst & 0x3f; /* 64 byte alignment */
459
460    if ((src_align != dst_align) ||
461        ((src_align & 0x3) != 0))
462      {
463 #ifdef BUILD_C
464         evas_common_copy_pixels_c(src, dst, len);
465 #endif
466         return;
467      }
468
469    while ((src_align > 0) && (len > 0))
470      {
471         *dst = *src;
472         dst++;
473         src++;
474         len--;
475         src_align -= sizeof(DATA32);
476      }
477 #endif /* ALIGN_FIX */
478
479    src_ptr = src;
480    dst_ptr = dst;
481    dst_end_ptr = dst + len;
482    dst_end_ptr_pre = dst + ((len / 16) * 16);
483
484    while (dst_ptr < dst_end_ptr_pre)
485      {
486         prefetch(&src_ptr[16]);
487         MOVE_16DWORDS_MMX(src_ptr, dst_ptr);
488         src_ptr+=16;
489         dst_ptr+=16;
490      }
491    while (dst_ptr < dst_end_ptr)
492      {
493         *dst_ptr = *src_ptr;
494         src_ptr++;
495         dst_ptr++;
496      }
497 #endif
498 }
499 #endif
500
501 /****************************************************************************/
502
503 #ifdef BUILD_C
504 static void
505 evas_common_copy_pixels_rev_c(DATA32 *src, DATA32 *dst, int len)
506 {
507    DATA32 *dst_end;
508
509    src = src + len - 1;
510    dst_end = dst - 1;
511    dst = dst + len - 1;
512
513    while (dst > dst_end) *dst-- = *src--;
514 }
515 #endif
516
517 #ifdef BUILD_MMX
518 static void
519 evas_common_copy_pixels_rev_mmx(DATA32 *src, DATA32 *dst, int len)
520 {
521    DATA32 *dst_end, *dst_end_pre;
522
523    if (len >= 16)
524      {
525         src = src + len - 16;
526         dst_end = dst;
527         dst_end_pre = dst + len - ((len / 16) * 16);
528         dst = dst + len - 16;
529
530         while (dst >= dst_end_pre)
531           {
532              MOVE_16DWORDS_MMX(src, dst);
533              src -= 16;
534              dst -= 16;
535           }
536         src += 15;
537         dst += 15;
538         while (dst >= dst_end)
539              *dst-- = *src--;
540      }
541    else
542      {
543         src = src + len - 1;
544         dst_end = dst - 1;
545         dst = dst + len - 1;
546         while (dst > dst_end)
547              *dst-- = *src--;
548      }
549 }
550 #endif
551
552 #ifdef BUILD_SSE
553 static void
554 evas_common_copy_pixels_rev_sse(DATA32 *src, DATA32 *dst, int len)
555 {
556    DATA32 *src_ptr, *dst_ptr, *dst_end_ptr, *dst_end_ptr_pre;
557
558    src_ptr = src + len - 16;
559    dst_ptr = dst + len - 16;
560    dst_end_ptr = dst;
561    dst_end_ptr_pre = dst + len - ((len / 16) * 16);
562
563    if (len >= 16)
564      {
565         while (dst_ptr >= dst_end_ptr_pre)
566           {
567              prefetch(&src_ptr[-16]);
568              MOVE_10DWORDS_MMX(src_ptr, dst_ptr);
569              src_ptr -= 16;
570              dst_ptr -= 16;
571           }
572         src_ptr += 15;
573         dst_ptr += 15;
574         while (dst_ptr >= dst_end_ptr)
575           {
576              *dst_ptr = *src_ptr;
577              src_ptr--;
578              dst_ptr--;
579           }
580      }
581    else
582      {
583         src_ptr = src + len - 1;
584         dst_ptr = dst + len - 1;
585         while (dst_ptr >= dst_end_ptr)
586           {
587              *dst_ptr = *src_ptr;
588              src_ptr--;
589              dst_ptr--;
590           }
591      }
592 }
593 #endif
594
595
596 Gfx_Func_Copy
597 evas_common_draw_func_copy_get(int pixels, int reverse)
598 {
599    if (reverse == -1)
600         return evas_common_copy_rev_pixels_c;
601    if (reverse)
602      {
603 #ifdef  BUILD_SSE
604         if (evas_common_cpu_has_feature(CPU_FEATURE_SSE) && (pixels > 256 * 256))
605           return evas_common_copy_pixels_rev_sse;
606 #endif
607 #ifdef BUILD_MMX
608 # ifdef BUILD_SSE
609         else
610 # endif
611           if (evas_common_cpu_has_feature(CPU_FEATURE_MMX))
612             return evas_common_copy_pixels_rev_mmx;
613 #endif
614 #ifdef BUILD_NEON
615 # if defined(BUILD_SSE) || defined(BUILD_MMX)
616         else
617 # endif
618           if (evas_common_cpu_has_feature(CPU_FEATURE_NEON))
619             return evas_common_copy_pixels_rev_neon;
620 #endif
621
622 #ifdef BUILD_C
623 # if defined(BUILD_MMX) || defined(BUILD_NEON)
624         else
625 # endif
626           return evas_common_copy_pixels_rev_c;
627 #endif
628      }
629    else
630      {
631 #if 1
632
633 # ifdef BUILD_MMX
634 # ifdef BUILD_C
635              if (evas_common_cpu_has_feature(CPU_FEATURE_MMX2))
636 # endif
637                return evas_common_copy_pixels_mmx2;
638 # ifdef BUILD_SSE
639              else
640 # endif
641 #endif
642 #ifdef BUILD_SSE
643 # ifdef BUILD_C
644                if (evas_common_cpu_has_feature(CPU_FEATURE_SSE) && (pixels > 64 * 64))
645 # endif
646                  return evas_common_copy_pixels_sse;
647 # ifdef BUILD_MMX
648              else
649 # endif
650 #endif
651 # ifdef BUILD_NEON
652 # ifdef BUILD_C
653              if (evas_common_cpu_has_feature(CPU_FEATURE_NEON))
654 # endif
655                return evas_common_copy_pixels_neon;
656 # ifdef BUILD_SSE
657              else
658 # endif
659 #endif
660 #ifdef BUILD_MMX
661 # ifdef BUILD_C
662                if (evas_common_cpu_has_feature(CPU_FEATURE_MMX))
663 # endif
664                  return evas_common_copy_pixels_mmx;
665 # ifdef BUILD_C
666              else
667 # endif
668 #endif
669 #ifdef BUILD_C
670                return evas_common_copy_pixels_c;
671 #endif
672
673 #else
674
675 # ifdef BUILD_SSE
676              if (evas_common_cpu_has_feature(CPU_FEATURE_SSE) && (pixels > 256 * 256))
677                return evas_common_copy_pixels_sse;
678 # ifdef BUILD_MMX
679              else
680 # endif
681 #endif
682 #ifdef BUILD_MMX
683 # ifdef BUILD_C
684                if (evas_common_cpu_has_feature(CPU_FEATURE_MMX2))
685 # endif
686                  return evas_common_copy_pixels_mmx2;
687 # ifdef BUILD_C
688                else if (evas_common_cpu_has_feature(CPU_FEATURE_MMX))
689 # endif
690                  return evas_common_copy_pixels_mmx;
691 # ifdef BUILD_C
692              else
693 # endif
694 #endif
695 #ifdef BUILD_C
696                return evas_common_copy_pixels_c;
697 #endif
698
699 #endif
700      }
701 #ifdef BUILD_C
702    return evas_common_copy_pixels_c;
703 #else
704    return NULL;
705 #endif
706 }