Home | History | Annotate | Download | only in bench
      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 "../tools/Registry.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 struct GrContextOptions;
     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     Benchmark();
     47 
     48     const char* getName();
     49     const char* getUniqueName();
     50     SkIPoint getSize();
     51 
     52     enum Backend {
     53         kNonRendering_Backend,
     54         kRaster_Backend,
     55         kGPU_Backend,
     56         kPDF_Backend,
     57         kHWUI_Backend,
     58     };
     59 
     60     // Call to determine whether the benchmark is intended for
     61     // the rendering mode.
     62     virtual bool isSuitableFor(Backend backend) {
     63         return backend != kNonRendering_Backend;
     64     }
     65 
     66     // Allows a benchmark to override options used to construct the GrContext.
     67     virtual void modifyGrContextOptions(GrContextOptions*) {}
     68 
     69     virtual int calculateLoops(int defaultLoops) const {
     70         return defaultLoops;
     71     }
     72 
     73     // Call before draw, allows the benchmark to do setup work outside of the
     74     // timer. When a benchmark is repeatedly drawn, this should be called once
     75     // before the initial draw.
     76     void delayedSetup();
     77 
     78     // Called once before and after a series of draw calls to a single canvas.
     79     // The setup/break down in these calls is not timed.
     80     void perCanvasPreDraw(SkCanvas*);
     81     void perCanvasPostDraw(SkCanvas*);
     82 
     83     // Called just before and after each call to draw().  Not timed.
     84     void preDraw(SkCanvas*);
     85     void postDraw(SkCanvas*);
     86 
     87     // Bench framework can tune loops to be large enough for stable timing.
     88     void draw(int loops, SkCanvas*);
     89 
     90     void setForceAlpha(int alpha) {
     91         fForceAlpha = alpha;
     92     }
     93 
     94     void setDither(SkTriState::State state) {
     95         fDither = state;
     96     }
     97 
     98     /** Assign masks for paint-flags. These will be applied when setupPaint()
     99      *  is called.
    100      *
    101      *  Performs the following on the paint:
    102      *      uint32_t flags = paint.getFlags();
    103      *      flags &= ~clearMask;
    104      *      flags |= orMask;
    105      *      paint.setFlags(flags);
    106      */
    107     void setPaintMasks(uint32_t orMask, uint32_t clearMask) {
    108         fOrMask = orMask;
    109         fClearMask = clearMask;
    110     }
    111 
    112     /*
    113      * Benches which support running in a visual mode can advertise this functionality
    114      */
    115     virtual bool isVisual() { return false; }
    116 
    117     /*
    118      * VisualBench frequently resets the canvas.  As a result we need to bulk call all of the hooks
    119      */
    120     void preTimingHooks(SkCanvas* canvas) {
    121         this->perCanvasPreDraw(canvas);
    122         this->preDraw(canvas);
    123     }
    124 
    125     void postTimingHooks(SkCanvas* canvas)  {
    126         this->postDraw(canvas);
    127         this->perCanvasPostDraw(canvas);
    128     }
    129 
    130     virtual void getGpuStats(SkCanvas*, SkTArray<SkString>* keys, SkTArray<double>* values) {}
    131 
    132 protected:
    133     virtual void setupPaint(SkPaint* paint);
    134 
    135     virtual const char* onGetName() = 0;
    136     virtual const char* onGetUniqueName() { return this->onGetName(); }
    137     virtual void onDelayedSetup() {}
    138     virtual void onPerCanvasPreDraw(SkCanvas*) {}
    139     virtual void onPerCanvasPostDraw(SkCanvas*) {}
    140     virtual void onPreDraw(SkCanvas*) {}
    141     virtual void onPostDraw(SkCanvas*) {}
    142     // Each bench should do its main work in a loop like this:
    143     //   for (int i = 0; i < loops; i++) { <work here> }
    144     virtual void onDraw(int loops, SkCanvas*) = 0;
    145 
    146     virtual SkIPoint onGetSize();
    147 
    148 private:
    149     int     fForceAlpha;
    150     SkTriState::State  fDither;
    151     uint32_t    fOrMask, fClearMask;
    152 
    153     typedef SkRefCnt INHERITED;
    154 };
    155 
    156 typedef sk_tools::Registry<Benchmark*(*)(void*)> BenchRegistry;
    157 
    158 #endif
    159