1 /*
2  * Copyright 2017 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 #include "Benchmark.h"
8 #include "SkCanvas.h"
9 #include "SkDrawShadowInfo.h"
10 #include "SkPaint.h"
11 #include "SkPath.h"
12 #include "SkShadowUtils.h"
13 
14 class ShadowBench : public Benchmark {
15 // Draws a set of shadowed rrects filling the canvas, in various modes:
16 // * opaque or transparent
17 // * use analytic fast path or geometric tessellation
18 public:
19     ShadowBench(bool transparent, bool forceGeometric)
20         : fTransparent(transparent)
21         , fForceGeometric(forceGeometric) {
22         computeName("shadows");
23     }
24 
25     bool isVisual() override { return true; }
26 
27 protected:
28     enum {
29         kWidth = 640,
30         kHeight = 480,
31         kRRSize = 50,
32         kRRRadius = 6,
33         kRRSpace = 8,
34         kRRStep = kRRSize + kRRSpace,
35         kElevation = 16,
36         kNumRRects = ((kWidth - kRRSpace) / kRRStep)*((kHeight - kRRSpace) / kRRStep)
37     };
38 
39     void computeName(const char root[]) {
40         static const char kTransChars[2] = {
41             'o', 't'
42         };
43         static const char kGeomChars[2] = {
44             'a', 'g'
45         };
46 
47         fBaseName.printf("%s_%c_%c", root, kTransChars[fTransparent], kGeomChars[fForceGeometric]);
48     }
49 
50     void genRRects() {
51         int i = 0;
52         for (int x = kRRSpace; x < kWidth - kRRStep; x += kRRStep) {
53             for (int y = kRRSpace; y < kHeight - kRRStep; y += kRRStep) {
54                 SkRect rect = SkRect::MakeXYWH(x, y, kRRSize, kRRSize);
55                 fRRects[i].addRRect(SkRRect::MakeRectXY(rect, kRRRadius, kRRRadius));
56                 ++i;
57             }
58         }
59         SkASSERT(i == kNumRRects);
60     }
61 
62     const char* onGetName() override { return fBaseName.c_str(); }
63 
64     void onDelayedSetup() override {
65         fRec.fZPlaneParams = SkPoint3::Make(0, 0, kElevation);
66         fRec.fLightPos = SkPoint3::Make(270, 0, 600);
67         fRec.fLightRadius = 800;
68         fRec.fAmbientColor = 0x19000000;
69         fRec.fSpotColor = 0x40000000;
70         fRec.fFlags = 0;
71         if (fTransparent) {
72             fRec.fFlags |= SkShadowFlags::kTransparentOccluder_ShadowFlag;
73         }
74         if (fForceGeometric) {
75             fRec.fFlags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
76         }
77 
78         this->genRRects();
79     }
80 
81     void onDraw(int loops, SkCanvas* canvas) override {
82         SkPaint paint;
83         paint.setColor(SK_ColorWHITE);
84         this->setupPaint(&paint);
85 
86         for (int i = 0; i < loops; ++i) {
87             // use the private canvas call so we don't include the time to stuff data in the Rec
88             canvas->private_draw_shadow_rec(fRRects[i % kNumRRects], fRec);
89         }
90     }
91 
92 private:
93     SkString fBaseName;
94 
95     SkPath  fRRects[kNumRRects];
96     SkDrawShadowRec fRec;
97     int    fTransparent;
98     int    fForceGeometric;
99 
100     typedef Benchmark INHERITED;
101 };
102 
103 DEF_BENCH(return new ShadowBench(false, false);)
104 DEF_BENCH(return new ShadowBench(false, true);)
105 DEF_BENCH(return new ShadowBench(true, false);)
106 DEF_BENCH(return new ShadowBench(true, true);)
107 
108