1 #include "SkBenchmark.h" 2 #include "SkColorPriv.h" 3 #include "SkRandom.h" 4 #include "SkString.h" 5 6 template <bool kFast, bool kScale> 7 class FourByteInterpBench : public SkBenchmark { 8 public: FourByteInterpBench()9 FourByteInterpBench() { 10 fName.set("four_byte_interp"); 11 fName.append(kFast ? "_fast" : "_slow"); 12 fName.append(kScale ? "_255" : "_256"); 13 } 14 isSuitableFor(Backend backend)15 virtual bool isSuitableFor(Backend backend) SK_OVERRIDE { 16 return backend == kNonRendering_Backend; 17 } 18 onGetName()19 virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); } 20 onPreDraw()21 virtual void onPreDraw() SK_OVERRIDE { 22 // A handful of random srcs and dsts. 23 SkRandom rand; 24 for (int i = 0; i < kInputs; i++) { 25 fSrcs[i] = SkPreMultiplyColor(rand.nextU()); 26 fDsts[i] = SkPreMultiplyColor(rand.nextU()); 27 } 28 29 // We'll exhaustively test all scales instead of using random numbers. 30 for (int i = 0; i <= 256; i++) { 31 fScales[i] = i; 32 } 33 if (kScale) fScales[256] = 255; // We'll just do 255 twice if we're limited to [0,255]. 34 } 35 onDraw(const int loops,SkCanvas *)36 virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE { 37 // We xor results of FourByteInterp into junk to make sure the function runs. 38 volatile SkPMColor junk = 0; 39 40 for (int loop = 0; loop < loops; loop++) { 41 for (int i = 0; i < kInputs; i++) { 42 for (size_t j = 0; j <= 256; j++) { 43 // Note: we really want to load src and dst here and not outside in the i-loop. 44 // If we put the loads there, a clever compiler will do the not-insignificant 45 // work in the FourByteInterps that depends only on src and dst outside this 46 // loop, so we'd only be benchmarking the back half of those functions that also 47 // depends on scale. Even here, these must be volatile arrays to prevent that 48 // clever compiler from hoisting the loads out of the loop on its own. 49 const SkPMColor src = fSrcs[i]; 50 const SkPMColor dst = fDsts[i]; 51 52 const unsigned scale = fScales[j]; 53 54 if (kFast && kScale) { 55 junk ^= SkFastFourByteInterp(src, dst, scale); 56 } else if (kFast) { 57 junk ^= SkFastFourByteInterp256(src, dst, scale); 58 } else if (kScale) { 59 junk ^= SkFourByteInterp(src, dst, scale); 60 } else { 61 junk ^= SkFourByteInterp256(src, dst, scale); 62 } 63 } 64 } 65 } 66 } 67 68 private: 69 SkString fName; 70 static const int kInputs = 10; // Arbitrary. 71 volatile unsigned fSrcs[kInputs]; 72 volatile unsigned fDsts[kInputs]; 73 unsigned fScales[257]; // We need space for [0, 256]. 74 }; 75 76 #define COMMA , 77 DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA true>); ) 78 DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA false>); ) 79 DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA true>); ) 80 DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA false>); ) 81 #undef COMMA 82