1 /*
2  * Copyright 2013 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 #include "bench/Benchmark.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkPaint.h"
11 #include "include/core/SkPath.h"
12 #include "include/core/SkShader.h"
13 #include "include/core/SkString.h"
14 #include "include/utils/SkRandom.h"
15 
16 enum Flags {
17     kBig_Flag = 1 << 0,
18     kAA_Flag = 1 << 1
19 };
20 
21 #define FLAGS00 Flags(0)
22 #define FLAGS01 Flags(kBig_Flag)
23 #define FLAGS10 Flags(kAA_Flag)
24 #define FLAGS11 Flags(kBig_Flag | kAA_Flag)
25 
26 static const int points[] = {
27     10, 10, 15, 5, 20, 20,
28     30, 5, 25, 20, 15, 12,
29     21, 21, 30, 30, 12, 4,
30     32, 28, 20, 18, 12, 10
31 };
32 
33 static const int kMaxPathSize = 10;
34 
35 class HairlinePathBench : public Benchmark {
36 public:
HairlinePathBench(Flags flags)37     HairlinePathBench(Flags flags) : fFlags(flags) {
38         fPaint.setStyle(SkPaint::kStroke_Style);
39         fPaint.setStrokeWidth(SkIntToScalar(0));
40     }
41 
42     virtual void appendName(SkString*) = 0;
43     virtual void makePath(SkPath*) = 0;
44 
45 protected:
onGetName()46     const char* onGetName() override {
47         fName.printf("path_hairline_%s_%s_",
48                      fFlags & kBig_Flag ? "big" : "small",
49                      fFlags & kAA_Flag ? "AA" : "noAA");
50         this->appendName(&fName);
51         return fName.c_str();
52     }
53 
onDraw(int loops,SkCanvas * canvas)54     void onDraw(int loops, SkCanvas* canvas) override {
55         SkPaint paint(fPaint);
56         this->setupPaint(&paint);
57 
58         paint.setAntiAlias(fFlags & kAA_Flag ? true : false);
59 
60         SkPath path;
61         this->makePath(&path);
62         if (fFlags & kBig_Flag) {
63             const SkMatrix m = SkMatrix::MakeScale(SkIntToScalar(3), SkIntToScalar(3));
64             path.transform(m);
65         }
66 
67         for (int i = 0; i < loops; i++) {
68             for (int j = 0; j < 100; ++j) {
69                 canvas->drawPath(path, paint);
70             }
71         }
72     }
73 
74 private:
75     SkPaint     fPaint;
76     SkString    fName;
77     Flags       fFlags;
78     typedef Benchmark INHERITED;
79 };
80 
81 class LinePathBench : public HairlinePathBench {
82 public:
LinePathBench(Flags flags)83     LinePathBench(Flags flags) : INHERITED(flags) {}
84 
appendName(SkString * name)85     void appendName(SkString* name) override {
86         name->append("line");
87     }
makePath(SkPath * path)88     void makePath(SkPath* path) override {
89         SkRandom rand;
90         int size = SK_ARRAY_COUNT(points);
91         int hSize = size / 2;
92         for (int i = 0; i < kMaxPathSize; ++i) {
93             int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
94             int yTrans = 0;
95             if (i > kMaxPathSize/2 - 1) {
96                 yTrans = 40;
97             }
98             int base1 = 2 * rand.nextULessThan(hSize);
99             int base2 = 2 * rand.nextULessThan(hSize);
100             int base3 = 2 * rand.nextULessThan(hSize);
101             path->moveTo(SkIntToScalar(points[base1] + xTrans),
102                          SkIntToScalar(points[base1+1] + yTrans));
103             path->lineTo(SkIntToScalar(points[base2] + xTrans),
104                          SkIntToScalar(points[base2+1] + yTrans));
105             path->lineTo(SkIntToScalar(points[base3] + xTrans),
106                          SkIntToScalar(points[base3+1] + yTrans));
107         }
108     }
109 private:
110     typedef HairlinePathBench INHERITED;
111 };
112 
113 class QuadPathBench : public HairlinePathBench {
114 public:
QuadPathBench(Flags flags)115     QuadPathBench(Flags flags) : INHERITED(flags) {}
116 
appendName(SkString * name)117     void appendName(SkString* name) override {
118         name->append("quad");
119     }
makePath(SkPath * path)120     void makePath(SkPath* path) override {
121         SkRandom rand;
122         int size = SK_ARRAY_COUNT(points);
123         int hSize = size / 2;
124         for (int i = 0; i < kMaxPathSize; ++i) {
125             int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
126             int yTrans = 0;
127             if (i > kMaxPathSize/2 - 1) {
128                 yTrans = 40;
129             }
130             int base1 = 2 * rand.nextULessThan(hSize);
131             int base2 = 2 * rand.nextULessThan(hSize);
132             int base3 = 2 * rand.nextULessThan(hSize);
133             path->moveTo(SkIntToScalar(points[base1] + xTrans),
134                          SkIntToScalar(points[base1+1] + yTrans));
135             path->quadTo(SkIntToScalar(points[base2] + xTrans),
136                          SkIntToScalar(points[base2+1] + yTrans),
137                          SkIntToScalar(points[base3] + xTrans),
138                          SkIntToScalar(points[base3+1] + yTrans));
139         }
140     }
141 private:
142     typedef HairlinePathBench INHERITED;
143 };
144 
145 class ConicPathBench : public HairlinePathBench {
146 public:
ConicPathBench(Flags flags)147     ConicPathBench(Flags flags) : INHERITED(flags) {}
148 
appendName(SkString * name)149     void appendName(SkString* name) override {
150         name->append("conic");
151     }
makePath(SkPath * path)152     void makePath(SkPath* path) override {
153         SkRandom rand;
154         SkRandom randWeight;
155         int size = SK_ARRAY_COUNT(points);
156         int hSize = size / 2;
157         for (int i = 0; i < kMaxPathSize; ++i) {
158             int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
159             int yTrans = 0;
160             if (i > kMaxPathSize/2 - 1) {
161                 yTrans = 40;
162             }
163             int base1 = 2 * rand.nextULessThan(hSize);
164             int base2 = 2 * rand.nextULessThan(hSize);
165             int base3 = 2 * rand.nextULessThan(hSize);
166             float weight = randWeight.nextRangeF(0.0f, 2.0f);
167             path->moveTo(SkIntToScalar(points[base1] + xTrans),
168                          SkIntToScalar(points[base1+1] + yTrans));
169             path->conicTo(SkIntToScalar(points[base2] + xTrans),
170                           SkIntToScalar(points[base2+1] + yTrans),
171                          SkIntToScalar(points[base3] + xTrans),
172                          SkIntToScalar(points[base3+1] + yTrans),
173                          weight);
174         }
175     }
176 
177 private:
178     typedef HairlinePathBench INHERITED;
179 };
180 
181 class CubicPathBench : public HairlinePathBench {
182 public:
CubicPathBench(Flags flags)183     CubicPathBench(Flags flags) : INHERITED(flags) {}
184 
appendName(SkString * name)185     void appendName(SkString* name) override {
186         name->append("cubic");
187     }
makePath(SkPath * path)188     void makePath(SkPath* path) override {
189         SkRandom rand;
190         int size = SK_ARRAY_COUNT(points);
191         int hSize = size / 2;
192         for (int i = 0; i < kMaxPathSize; ++i) {
193             int xTrans = 10 + 40 * (i%(kMaxPathSize/2));
194             int yTrans = 0;
195             if (i > kMaxPathSize/2 - 1) {
196                 yTrans = 40;
197             }
198             int base1 = 2 * rand.nextULessThan(hSize);
199             int base2 = 2 * rand.nextULessThan(hSize);
200             int base3 = 2 * rand.nextULessThan(hSize);
201             int base4 = 2 * rand.nextULessThan(hSize);
202             path->moveTo(SkIntToScalar(points[base1] + xTrans),
203                          SkIntToScalar(points[base1+1] + yTrans));
204             path->cubicTo(SkIntToScalar(points[base2] + xTrans),
205                          SkIntToScalar(points[base2+1] + yTrans),
206                          SkIntToScalar(points[base3] + xTrans),
207                          SkIntToScalar(points[base3+1] + yTrans),
208                          SkIntToScalar(points[base4] + xTrans),
209                          SkIntToScalar(points[base4+1] + yTrans));
210         }
211     }
212 private:
213     typedef HairlinePathBench INHERITED;
214 };
215 
216 // FLAG00 - no AA, small
217 // FLAG01 - no AA, small
218 // FLAG10 - AA, big
219 // FLAG11 - AA, big
220 
221 DEF_BENCH( return new LinePathBench(FLAGS00); )
222 DEF_BENCH( return new LinePathBench(FLAGS01); )
223 DEF_BENCH( return new LinePathBench(FLAGS10); )
224 DEF_BENCH( return new LinePathBench(FLAGS11); )
225 
226 DEF_BENCH( return new QuadPathBench(FLAGS00); )
227 DEF_BENCH( return new QuadPathBench(FLAGS01); )
228 DEF_BENCH( return new QuadPathBench(FLAGS10); )
229 DEF_BENCH( return new QuadPathBench(FLAGS11); )
230 
231 // Don't have default path renderer for conics yet on GPU, so must use AA
232 // DEF_BENCH( return new ConicPathBench(FLAGS00); )
233 // DEF_BENCH( return new ConicPathBench(FLAGS01); )
234 DEF_BENCH( return new ConicPathBench(FLAGS10); )
235 DEF_BENCH( return new ConicPathBench(FLAGS11); )
236 
237 DEF_BENCH( return new CubicPathBench(FLAGS00); )
238 DEF_BENCH( return new CubicPathBench(FLAGS01); )
239 DEF_BENCH( return new CubicPathBench(FLAGS10); )
240 DEF_BENCH( return new CubicPathBench(FLAGS11); )
241