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