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 
31 class SkCanvas;
32 class SkPaint;
33 
34 class SkTriState {
35 public:
36     enum State {
37         kDefault,
38         kTrue,
39         kFalse
40     };
41     static const char* Name[];
42 };
43 
44 class Benchmark : public SkRefCnt {
45 public:
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.
isSuitableFor(Backend backend)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 
setForceAlpha(int alpha)81     void setForceAlpha(int alpha) {
82         fForceAlpha = alpha;
83     }
84 
setDither(SkTriState::State state)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      */
setPaintMasks(uint32_t orMask,uint32_t clearMask)98     void setPaintMasks(uint32_t orMask, uint32_t clearMask) {
99         fOrMask = orMask;
100         fClearMask = clearMask;
101     }
102 
103 protected:
104     virtual void setupPaint(SkPaint* paint);
105 
106     virtual const char* onGetName() = 0;
onGetUniqueName()107     virtual const char* onGetUniqueName() { return this->onGetName(); }
onPreDraw()108     virtual void onPreDraw() {}
onPerCanvasPreDraw(SkCanvas *)109     virtual void onPerCanvasPreDraw(SkCanvas*) {}
onPerCanvasPostDraw(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 
117 private:
118     int     fForceAlpha;
119     SkTriState::State  fDither;
120     uint32_t    fOrMask, fClearMask;
121 
122     typedef SkRefCnt INHERITED;
123 };
124 
125 typedef SkTRegistry<Benchmark*(*)(void*)> BenchRegistry;
126 
127 #endif
128