| Index: src/opts/SkXfermode_opts_arm.cpp
|
| diff --git a/src/opts/SkXfermode_opts_arm.cpp b/src/opts/SkXfermode_opts_arm.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..db5d5317e3d6f5bbb2b8da170b6d96cdbe2fa3e6
|
| --- /dev/null
|
| +++ b/src/opts/SkXfermode_opts_arm.cpp
|
| @@ -0,0 +1,158 @@
|
| +#include "SkXfermode.h"
|
| +#include "SkXfermode_proccoeff.h"
|
| +#include "SkColorPriv.h"
|
| +#include "SkUtilsArm.h"
|
| +
|
| +#if !SK_ARM_NEON_IS_NONE
|
| +
|
| +#include <arm_neon.h>
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +typedef uint8x8x4_t (*SkXfermodeProcSIMD)(uint8x8x4_t src, uint8x8x4_t dst);
|
| +
|
| +class SkNEONProcCoeffXfermode : public SkProcCoeffXfermode {
|
| +public:
|
| + SkNEONProcCoeffXfermode(const ProcCoeff& rec, SkXfermode::Mode mode,
|
| + SkXfermodeProcSIMD procSIMD)
|
| + : INHERITED(rec, mode), fProcSIMD(procSIMD) {}
|
| +
|
| + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
|
| + const SkAlpha aa[]) const SK_OVERRIDE;
|
| +
|
| + SK_DEVELOPER_TO_STRING()
|
| + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkNEONProcCoeffXfermode)
|
| +
|
| +private:
|
| + SkNEONProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
|
| + : INHERITED(buffer) {
|
| +
|
| + fProcSIMD = NULL;
|
| + if (!buffer.isCrossProcess()) {
|
| + fProcSIMD = (SkXfermodeProcSIMD)buffer.readFunctionPtr();
|
| + }
|
| + }
|
| +
|
| + virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
|
| +
|
| + SkXfermodeProcSIMD fProcSIMD;
|
| + typedef SkProcCoeffXfermode INHERITED;
|
| +};
|
| +
|
| +
|
| +void SkNEONProcCoeffXfermode::xfer32(SkPMColor dst[], const SkPMColor src[],
|
| + int count, const SkAlpha aa[]) const {
|
| + SkASSERT(dst && src && count >= 0);
|
| +
|
| + SkXfermodeProc proc = this->getProc();
|
| + SkXfermodeProcSIMD procSIMD = fProcSIMD;
|
| +
|
| + if (NULL == aa) {
|
| + // Unrolled NEON code
|
| + while (count >= 8) {
|
| + uint8x8x4_t vsrc, vdst, vres;
|
| +
|
| + asm volatile (
|
| + "vld4.u8 %h[vsrc], [%[src]]! \t\n"
|
| + "vld4.u8 %h[vdst], [%[dst]] \t\n"
|
| + : [vsrc] "=w" (vsrc), [vdst] "=w" (vdst)
|
| + : [src] "r" (src), [dst] "r" (dst)
|
| + :
|
| + );
|
| +
|
| + vres = procSIMD(vsrc, vdst);
|
| +
|
| + vst4_u8((uint8_t*)dst, vres);
|
| +
|
| + count -= 8;
|
| + dst += 8;
|
| + }
|
| + // Leftovers
|
| + for (int i = 0; i < count; i++) {
|
| + dst[i] = proc(src[i], dst[i]);
|
| + }
|
| + } else {
|
| + for (int i = count - 1; i >= 0; --i) {
|
| + unsigned a = aa[i];
|
| + if (0 != a) {
|
| + SkPMColor dstC = dst[i];
|
| + SkPMColor C = proc(src[i], dstC);
|
| + if (a != 0xFF) {
|
| + C = SkFourByteInterp(C, dstC, a);
|
| + }
|
| + dst[i] = C;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +#ifdef SK_DEVELOPER
|
| +void SkNEONProcCoeffXfermode::toString(SkString* str) const {
|
| + this->INHERITED::toString(str);
|
| +}
|
| +#endif
|
| +
|
| +void SkNEONProcCoeffXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
|
| + this->INHERITED::flatten(buffer);
|
| + if (!buffer.isCrossProcess()) {
|
| + buffer.writeFunctionPtr((void*)fProcSIMD);
|
| + }
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +SkXfermodeProcSIMD gNEONXfermodeProcs[] = {
|
| + [SkXfermode::kClear_Mode] = NULL,
|
| + [SkXfermode::kSrc_Mode] = NULL,
|
| + [SkXfermode::kDst_Mode] = NULL,
|
| + [SkXfermode::kSrcOver_Mode] = NULL,
|
| + [SkXfermode::kDstOver_Mode] = NULL,
|
| + [SkXfermode::kSrcIn_Mode] = NULL,
|
| + [SkXfermode::kDstIn_Mode] = NULL,
|
| + [SkXfermode::kSrcOut_Mode] = NULL,
|
| + [SkXfermode::kDstOut_Mode] = NULL,
|
| + [SkXfermode::kSrcATop_Mode] = NULL,
|
| + [SkXfermode::kDstATop_Mode] = NULL,
|
| + [SkXfermode::kXor_Mode] = NULL,
|
| + [SkXfermode::kPlus_Mode] = NULL,
|
| + [SkXfermode::kModulate_Mode]= NULL,
|
| + [SkXfermode::kScreen_Mode] = NULL,
|
| +
|
| + [SkXfermode::kOverlay_Mode] = NULL,
|
| + [SkXfermode::kDarken_Mode] = NULL,
|
| + [SkXfermode::kLighten_Mode] = NULL,
|
| + [SkXfermode::kColorDodge_Mode] = NULL,
|
| + [SkXfermode::kColorBurn_Mode] = NULL,
|
| + [SkXfermode::kHardLight_Mode] = NULL,
|
| + [SkXfermode::kSoftLight_Mode] = NULL,
|
| + [SkXfermode::kDifference_Mode] = NULL,
|
| + [SkXfermode::kExclusion_Mode] = NULL,
|
| + [SkXfermode::kMultiply_Mode] = NULL,
|
| +
|
| + [SkXfermode::kHue_Mode] = NULL,
|
| + [SkXfermode::kSaturation_Mode] = NULL,
|
| + [SkXfermode::kColor_Mode] = NULL,
|
| + [SkXfermode::kLuminosity_Mode] = NULL,
|
| +};
|
| +
|
| +SK_COMPILE_ASSERT(
|
| + SK_ARRAY_COUNT(gNEONXfermodeProcs) == SkXfermode::kLastMode + 1,
|
| + mode_count_arm
|
| +);
|
| +
|
| +#endif
|
| +
|
| +SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec,
|
| + SkXfermode::Mode mode) {
|
| +#if !SK_ARM_NEON_IS_NONE
|
| + #if SK_ARM_NEON_IS_DYNAMIC
|
| + if ((sk_cpu_arm_has_neon()) && (gNEONXfermodeProcs[mode] != NULL)) {
|
| + #elif SK_ARM_NEON_IS_ALWAYS
|
| + if (gNEONXfermodeProcs[mode] != NULL) {
|
| + #endif
|
| + return SkNEW_ARGS(SkNEONProcCoeffXfermode,
|
| + (rec, mode, gNEONXfermodeProcs[mode]));
|
| + }
|
| +#endif
|
| + return NULL;
|
| +}
|
|
|