|  | #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"); | 
|  | } | 
|  |  | 
|  | bool isSuitableFor(Backend backend) SK_OVERRIDE { | 
|  | return backend == kNonRendering_Backend; | 
|  | } | 
|  |  | 
|  | const char* onGetName() SK_OVERRIDE { return fName.c_str(); } | 
|  |  | 
|  | 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]. | 
|  | } | 
|  |  | 
|  | 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 |