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 |
| 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 } |
| 88 |
| 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, |
| 146 SkXfermode::Mode mode) { |
| 147 #if !SK_ARM_NEON_IS_NONE |
| 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 } |
OLD | NEW |