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