1#include "Benchmark.h"
2#include "SkColorPriv.h"
3#include "SkRandom.h"
4#include "SkString.h"
5
6template <bool kFast, bool kScale>
7class FourByteInterpBench : public Benchmark {
8public:
9    FourByteInterpBench() {
10        fName.set("four_byte_interp");
11        fName.append(kFast ? "_fast" : "_slow");
12        fName.append(kScale ? "_255" : "_256");
13    }
14
15    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
16        return backend == kNonRendering_Backend;
17    }
18
19    virtual const char* onGetName() SK_OVERRIDE { return fName.c_str(); }
20
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
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
68private:
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 ,
77DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA true>); )
78DEF_BENCH( return SkNEW(FourByteInterpBench<true COMMA false>); )
79DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA true>); )
80DEF_BENCH( return SkNEW(FourByteInterpBench<false COMMA false>); )
81#undef COMMA
82