Chromium Code Reviews| Index: src/core/SkXfermode.cpp |
| diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp |
| index 1efd9efc4b2eae7a7ba7020e99a88d28e9e963f2..d24e24c8c8e764eb91575aabe175408325e4112b 100644 |
| --- a/src/core/SkXfermode.cpp |
| +++ b/src/core/SkXfermode.cpp |
| @@ -12,6 +12,8 @@ |
| #include "SkFlattenableBuffers.h" |
| #include "SkMathPriv.h" |
| #include "SkString.h" |
| +#include "SkXfermode_opts.h" |
| +#include "SkUtilsArm.h" |
| SK_DEFINE_INST_COUNT(SkXfermode) |
| @@ -634,6 +636,7 @@ static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { |
| struct ProcCoeff { |
| SkXfermodeProc fProc; |
| + SkXfermodeProcSIMD fProcSIMD; |
|
djsollen
2013/10/03 16:38:29
instead of defining this at compile time why not h
|
| SkXfermode::Coeff fSC; |
| SkXfermode::Coeff fDC; |
| }; |
| @@ -641,36 +644,36 @@ struct ProcCoeff { |
| #define CANNOT_USE_COEFF SkXfermode::Coeff(-1) |
| static const ProcCoeff gProcCoeffs[] = { |
| - { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, |
| - { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, |
| - { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, |
| - { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, |
| - { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, |
| - { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, |
| - { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, |
| - { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, |
| - { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, |
| - { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, |
| - { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, |
| - { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, |
| - |
| - { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, |
| - { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, |
| - { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, |
| - { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| - { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { clear_modeproc, SK_XMPSIMD_CLEAR, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, |
| + { src_modeproc, SK_XMPSIMD_SRC, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, |
| + { dst_modeproc, SK_XMPSIMD_DST, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, |
| + { srcover_modeproc, SK_XMPSIMD_SRCOVER, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, |
| + { dstover_modeproc, SK_XMPSIMD_DSTOVER, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, |
| + { srcin_modeproc, SK_XMPSIMD_SRCIN, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, |
| + { dstin_modeproc, SK_XMPSIMD_DSTIN, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, |
| + { srcout_modeproc, SK_XMPSIMD_SRCOUT, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, |
| + { dstout_modeproc, SK_XMPSIMD_DSTOUT, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, |
| + { srcatop_modeproc, SK_XMPSIMD_SRCATOP, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, |
| + { dstatop_modeproc, SK_XMPSIMD_DSTATOP, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, |
| + { xor_modeproc, SK_XMPSIMD_XOR, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, |
| + |
| + { plus_modeproc, SK_XMPSIMD_PLUS, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, |
| + { modulate_modeproc, SK_XMPSIMD_MODULATE, SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, |
| + { screen_modeproc, SK_XMPSIMD_SCREEN, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, |
| + { overlay_modeproc, SK_XMPSIMD_OVERLAY, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { darken_modeproc, SK_XMPSIMD_DARKEN, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { lighten_modeproc, SK_XMPSIMD_LIGHTEN, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { colordodge_modeproc,SK_XMPSIMD_COLORDODGE,CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { colorburn_modeproc, SK_XMPSIMD_COLORBURN, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { hardlight_modeproc, SK_XMPSIMD_HARDLIGHT, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { softlight_modeproc, SK_XMPSIMD_SOFTLIGHT, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { difference_modeproc,SK_XMPSIMD_DIFFERENCE,CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { exclusion_modeproc, SK_XMPSIMD_EXCLUSION, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { multiply_modeproc, SK_XMPSIMD_MULTIPLY, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { hue_modeproc, NULL, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { saturation_modeproc,NULL, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { color_modeproc, NULL, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| + { luminosity_modeproc,NULL, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| }; |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -791,8 +794,38 @@ void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, |
| if (NULL != proc) { |
| if (NULL == aa) { |
| - for (int i = count - 1; i >= 0; --i) { |
| - dst[i] = proc(src[i], dst[i]); |
| +#if SK_ARM_NEON_IS_ALWAYS |
|
djsollen
2013/10/03 16:38:29
if you do the above approach this code could be pu
reed1
2013/10/04 13:39:19
Looks like we could also return a different subcla
|
| + SkXfermodeProcSIMD procSIMD = fProcSIMD; |
| + if (procSIMD != NULL) { |
| + // 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 |
| +#endif |
| + { |
| + for (int i = count - 1; i >= 0; --i) { |
| + dst[i] = proc(src[i], dst[i]); |
| + } |
| } |
| } else { |
| for (int i = count - 1; i >= 0; --i) { |
| @@ -872,8 +905,10 @@ void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, |
| SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer) |
| : SkXfermode(buffer) { |
| fProc = NULL; |
| + fProcSIMD = NULL; |
| if (!buffer.isCrossProcess()) { |
| fProc = (SkXfermodeProc)buffer.readFunctionPtr(); |
| + fProcSIMD = (SkXfermodeProcSIMD)buffer.readFunctionPtr(); |
| } |
| } |
| @@ -881,12 +916,13 @@ void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { |
| this->INHERITED::flatten(buffer); |
| if (!buffer.isCrossProcess()) { |
| buffer.writeFunctionPtr((void*)fProc); |
| + buffer.writeFunctionPtr((void*)fProcSIMD); |
| } |
| } |
| #ifdef SK_DEVELOPER |
| void SkProcXfermode::toString(SkString* str) const { |
| - str->appendf("SkProcXfermode: %p", fProc); |
| + str->appendf("SkProcXfermode: fProc = %p, fProcSIMD = %p", fProc, fProcSIMD); |
| } |
| #endif |
| @@ -1377,7 +1413,7 @@ GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand, |
| class SkProcCoeffXfermode : public SkProcXfermode { |
| public: |
| SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) |
| - : INHERITED(rec.fProc) { |
| + : INHERITED(rec.fProc, rec.fProcSIMD) { |
| fMode = mode; |
| // these may be valid, or may be CANNOT_USE_COEFF |
| fSrcCoeff = rec.fSC; |
| @@ -1437,7 +1473,7 @@ protected: |
| fSrcCoeff = rec.fSC; |
| fDstCoeff = rec.fDC; |
| // now update our function-ptr in the super class |
| - this->INHERITED::setProc(rec.fProc); |
| + this->INHERITED::setProcs(rec.fProc, rec.fProcSIMD); |
| } |
| virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { |