OLD | NEW |
| (Empty) |
1 #include "SkXfermode.h" | |
2 #include "SkXfermode_proccoeff.h" | |
3 #include "SkColorPriv.h" | |
4 #include "SkUtilsArm.h" | |
5 | |
6 #if !SK_ARM_NEON_IS_NONE | |
7 | |
8 #include <arm_neon.h> | |
9 | |
10 //////////////////////////////////////////////////////////////////////////////// | |
11 | |
12 typedef uint8x8x4_t (*SkXfermodeProcSIMD)(uint8x8x4_t src, uint8x8x4_t dst); | |
13 | |
14 class SkNEONProcCoeffXfermode : public SkProcCoeffXfermode { | |
15 public: | |
16 SkNEONProcCoeffXfermode(const ProcCoeff& rec, SkXfermode::Mode mode, | |
17 SkXfermodeProcSIMD procSIMD) | |
18 : INHERITED(rec, mode), fProcSIMD(procSIMD) {} | |
19 | |
20 virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, | |
21 const SkAlpha aa[]) const SK_OVERRIDE; | |
22 private: | |
23 SkXfermodeProcSIMD fProcSIMD; | |
24 typedef SkProcCoeffXfermode INHERITED; | |
25 }; | |
26 | |
27 | |
28 void SkNEONProcCoeffXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], | |
29 int count, const SkAlpha aa[]) const { | |
30 SkASSERT(dst && src && count >= 0); | |
31 | |
32 SkXfermodeProc proc = this->getProc(); | |
33 SkXfermodeProcSIMD procSIMD = fProcSIMD; | |
34 | |
35 if (NULL == aa) { | |
36 // Unrolled NEON code | |
37 while (count >= 8) { | |
38 uint8x8x4_t vsrc, vdst, vres; | |
39 | |
40 asm volatile ( | |
41 "vld4.u8 %h[vsrc], [%[src]]! \t\n" | |
42 "vld4.u8 %h[vdst], [%[dst]] \t\n" | |
43 : [vsrc] "=w" (vsrc), [vdst] "=w" (vdst) | |
44 : [src] "r" (src), [dst] "r" (dst) | |
45 : | |
46 ); | |
47 | |
48 vres = procSIMD(vsrc, vdst); | |
49 | |
50 vst4_u8((uint8_t*)dst, vres); | |
51 | |
52 count -= 8; | |
53 dst += 8; | |
54 } | |
55 // Leftovers | |
56 for (int i = 0; i < count; i++) { | |
57 dst[i] = proc(src[i], dst[i]); | |
58 } | |
59 } else { | |
60 for (int i = count - 1; i >= 0; --i) { | |
61 unsigned a = aa[i]; | |
62 if (0 != a) { | |
63 SkPMColor dstC = dst[i]; | |
64 SkPMColor C = proc(src[i], dstC); | |
65 if (a != 0xFF) { | |
66 C = SkFourByteInterp(C, dstC, a); | |
67 } | |
68 dst[i] = C; | |
69 } | |
70 } | |
71 } | |
72 } | |
73 | |
74 #ifdef SK_DEVELOPER | |
75 void SkNEONProcCoeffXfermode::toString(SkString* str) const { | |
76 this->INHERITED::toString(str); | |
77 } | |
78 #endif | |
79 | |
80 //////////////////////////////////////////////////////////////////////////////// | |
81 | |
82 SkXfermodeProcSIMD gNEONXfermodeProcs[] = { | |
83 [SkXfermode::kClear_Mode] = NULL, | |
84 [SkXfermode::kSrc_Mode] = NULL, | |
85 [SkXfermode::kDst_Mode] = NULL, | |
86 [SkXfermode::kSrcOver_Mode] = NULL, | |
87 [SkXfermode::kDstOver_Mode] = NULL, | |
88 [SkXfermode::kSrcIn_Mode] = NULL, | |
89 [SkXfermode::kDstIn_Mode] = NULL, | |
90 [SkXfermode::kSrcOut_Mode] = NULL, | |
91 [SkXfermode::kDstOut_Mode] = NULL, | |
92 [SkXfermode::kSrcATop_Mode] = NULL, | |
93 [SkXfermode::kDstATop_Mode] = NULL, | |
94 [SkXfermode::kXor_Mode] = NULL, | |
95 [SkXfermode::kPlus_Mode] = NULL, | |
96 [SkXfermode::kModulate_Mode]= NULL, | |
97 [SkXfermode::kScreen_Mode] = NULL, | |
98 | |
99 [SkXfermode::kOverlay_Mode] = NULL, | |
100 [SkXfermode::kDarken_Mode] = NULL, | |
101 [SkXfermode::kLighten_Mode] = NULL, | |
102 [SkXfermode::kColorDodge_Mode] = NULL, | |
103 [SkXfermode::kColorBurn_Mode] = NULL, | |
104 [SkXfermode::kHardLight_Mode] = NULL, | |
105 [SkXfermode::kSoftLight_Mode] = NULL, | |
106 [SkXfermode::kDifference_Mode] = NULL, | |
107 [SkXfermode::kExclusion_Mode] = NULL, | |
108 [SkXfermode::kMultiply_Mode] = NULL, | |
109 | |
110 [SkXfermode::kHue_Mode] = NULL, | |
111 [SkXfermode::kSaturation_Mode] = NULL, | |
112 [SkXfermode::kColor_Mode] = NULL, | |
113 [SkXfermode::kLuminosity_Mode] = NULL, | |
114 }; | |
115 | |
116 SK_COMPILE_ASSERT( | |
117 SK_ARRAY_COUNT(gNEONXfermodeProcs) == SkXfermode::kLastMode + 1, | |
118 mode_count_arm | |
119 ); | |
120 | |
121 #endif | |
122 | |
123 SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, | |
124 SkXfermode::Mode mode) { | |
125 #if !SK_ARM_NEON_IS_NONE | |
126 #if SK_ARM_NEON_IS_DYNAMIC | |
127 if ((sk_cpu_arm_has_neon()) && (gNEONXfermodeProcs[mode] != NULL)) { | |
128 #elif SK_ARM_NEON_IS_ALWAYS | |
129 if (gNEONXfermodeProcs[mode] != NULL) { | |
130 #endif | |
131 return SkNEW_ARGS(SkNEONProcCoeffXfermode, | |
132 (rec, mode, gNEONXfermodeProcs[mode])); | |
133 } | |
134 #endif | |
135 return NULL; | |
136 } | |
OLD | NEW |