#include "Benchmark.h" #include "SkColorPriv.h" #include "SkRandom.h" #include "SkString.h" template <bool kFast, bool kScale> class FourByteInterpBench : public Benchmark { public: FourByteInterpBench() { fName.set("four_byte_interp"); fName.append(kFast ? "_fast" : "_slow"); fName.append(kScale ? "_255" : "_256"); } virtual bool isSuitableFor(Backend backend) SK_OVERRIDE { return backend == kNonRendering_Backend; } virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); } virtual void onPreDraw() SK_OVERRIDE { // A handful of random srcs and dsts. SkRandom rand; for (int i = 0; i < kInputs; i++) { fSrcs[i] = SkPreMultiplyColor(rand.nextU()); fDsts[i] = SkPreMultiplyColor(rand.nextU()); } // We'll exhaustively test all scales instead of using random numbers. for (int i = 0; i <= 256; i++) { fScales[i] = i; } if (kScale) fScales[256] = 255; // We'll just do 255 twice if we're limited to [0,255]. } virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE { // We xor results of FourByteInterp into junk to make sure the function runs. volatile SkPMColor junk = 0; for (int loop = 0; loop < loops; loop++) { for (int i = 0; i < kInputs; i++) { for (size_t j = 0; j <= 256; j++) { // Note: we really want to load src and dst here and not outside in the i-loop. // If we put the loads there, a clever compiler will do the not-insignificant // work in the FourByteInterps that depends only on src and dst outside this // loop, so we'd only be benchmarking the back half of those functions that also // depends on scale. Even here, these must be volatile arrays to prevent that // clever compiler from hoisting the loads out of the loop on its own. const SkPMColor src = fSrcs[i]; const SkPMColor dst = fDsts[i]; const unsigned scale = fScales[j]; if (kFast && kScale) { junk ^= SkFastFourByteInterp(src, dst, scale); } else if (kFast) { junk ^= SkFastFourByteInterp256(src, dst, scale); } else if (kScale) { junk ^= SkFourByteInterp(src, dst, scale); } else { junk ^= SkFourByteInterp256(src, dst, scale); } } } } } private: SkString fName; static const int kInputs = 10; // Arbitrary. volatile unsigned fSrcs[kInputs]; volatile unsigned fDsts[kInputs]; unsigned fScales[257]; // We need space for [0, 256]. }; #define COMMA , DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA true>); ) DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA false>); ) DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA true>); ) DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA false>); ) #undef COMMA