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 { |