1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef Benchmark_DEFINED
9#define Benchmark_DEFINED
10
11#include "SkPoint.h"
12#include "SkRefCnt.h"
13#include "SkString.h"
14#include "SkTRegistry.h"
15
16#define DEF_BENCH3(code, N) \
17    static BenchRegistry gBench##N([](void*) -> Benchmark* { code; });
18#define DEF_BENCH2(code, N) DEF_BENCH3(code, N)
19#define DEF_BENCH(code) DEF_BENCH2(code, __COUNTER__)
20
21/*
22 *  With the above macros, you can register benches as follows (at the bottom
23 *  of your .cpp)
24 *
25 *  DEF_BENCH(return new MyBenchmark(...))
26 *  DEF_BENCH(return new MyBenchmark(...))
27 *  DEF_BENCH(return new MyBenchmark(...))
28 */
29
30
31class SkCanvas;
32class SkPaint;
33
34class SkTriState {
35public:
36    enum State {
37        kDefault,
38        kTrue,
39        kFalse
40    };
41    static const char* Name[];
42};
43
44class Benchmark : public SkRefCnt {
45public:
46    SK_DECLARE_INST_COUNT(Benchmark)
47
48    Benchmark();
49
50    const char* getName();
51    const char* getUniqueName();
52    SkIPoint getSize();
53
54    enum Backend {
55        kNonRendering_Backend,
56        kRaster_Backend,
57        kGPU_Backend,
58        kPDF_Backend,
59        kHWUI_Backend,
60    };
61
62    // Call to determine whether the benchmark is intended for
63    // the rendering mode.
64    virtual bool isSuitableFor(Backend backend) {
65        return backend != kNonRendering_Backend;
66    }
67
68    // Call before draw, allows the benchmark to do setup work outside of the
69    // timer. When a benchmark is repeatedly drawn, this should be called once
70    // before the initial draw.
71    void preDraw();
72
73    // Called once before and after a series of draw calls to a single canvas.
74    // The setup/break down in these calls is not timed.
75    void perCanvasPreDraw(SkCanvas*);
76    void perCanvasPostDraw(SkCanvas*);
77
78    // Bench framework can tune loops to be large enough for stable timing.
79    void draw(const int loops, SkCanvas*);
80
81    void setForceAlpha(int alpha) {
82        fForceAlpha = alpha;
83    }
84
85    void setDither(SkTriState::State state) {
86        fDither = state;
87    }
88
89    /** Assign masks for paint-flags. These will be applied when setupPaint()
90     *  is called.
91     *
92     *  Performs the following on the paint:
93     *      uint32_t flags = paint.getFlags();
94     *      flags &= ~clearMask;
95     *      flags |= orMask;
96     *      paint.setFlags(flags);
97     */
98    void setPaintMasks(uint32_t orMask, uint32_t clearMask) {
99        fOrMask = orMask;
100        fClearMask = clearMask;
101    }
102
103protected:
104    virtual void setupPaint(SkPaint* paint);
105
106    virtual const char* onGetName() = 0;
107    virtual const char* onGetUniqueName() { return this->onGetName(); }
108    virtual void onPreDraw() {}
109    virtual void onPerCanvasPreDraw(SkCanvas*) {}
110    virtual void onPerCanvasPostDraw(SkCanvas*) {}
111    // Each bench should do its main work in a loop like this:
112    //   for (int i = 0; i < loops; i++) { <work here> }
113    virtual void onDraw(const int loops, SkCanvas*) = 0;
114
115    virtual SkIPoint onGetSize();
116
117private:
118    int     fForceAlpha;
119    SkTriState::State  fDither;
120    uint32_t    fOrMask, fClearMask;
121
122    typedef SkRefCnt INHERITED;
123};
124
125typedef SkTRegistry<Benchmark*(*)(void*)> BenchRegistry;
126
127#endif
128