blob: 757ffcc198cc9cee98f32cacee6ad1c81947d57f [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
bungemand3ebb482015-08-05 13:57:49 -07007
tfarinaf168b862014-06-19 12:32:29 -07008#include "Benchmark.h"
reed@google.comd34658a2011-04-11 13:12:51 +00009#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkColorPriv.h"
12#include "SkPaint.h"
bungemand3ebb482015-08-05 13:57:49 -070013#include "SkPath.h"
tomhudson@google.com6e8d3352011-06-22 17:16:35 +000014#include "SkRandom.h"
reed@google.comd34658a2011-04-11 13:12:51 +000015#include "SkShader.h"
16#include "SkString.h"
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +000017#include "SkTArray.h"
18
reed@google.comd34658a2011-04-11 13:12:51 +000019enum Flags {
20 kStroke_Flag = 1 << 0,
21 kBig_Flag = 1 << 1
22};
23
24#define FLAGS00 Flags(0)
25#define FLAGS01 Flags(kStroke_Flag)
26#define FLAGS10 Flags(kBig_Flag)
27#define FLAGS11 Flags(kStroke_Flag | kBig_Flag)
28
tfarinaf168b862014-06-19 12:32:29 -070029class PathBench : public Benchmark {
reed@google.comd34658a2011-04-11 13:12:51 +000030 SkPaint fPaint;
31 SkString fName;
32 Flags fFlags;
reed@google.comd34658a2011-04-11 13:12:51 +000033public:
mtklein@google.com410e6e82013-09-13 19:52:27 +000034 PathBench(Flags flags) : fFlags(flags) {
reed@google.comd34658a2011-04-11 13:12:51 +000035 fPaint.setStyle(flags & kStroke_Flag ? SkPaint::kStroke_Style :
36 SkPaint::kFill_Style);
37 fPaint.setStrokeWidth(SkIntToScalar(5));
38 fPaint.setStrokeJoin(SkPaint::kBevel_Join);
39 }
40
41 virtual void appendName(SkString*) = 0;
42 virtual void makePath(SkPath*) = 0;
tomhudson@google.com6e8d3352011-06-22 17:16:35 +000043 virtual int complexity() { return 0; }
reed@google.comd34658a2011-04-11 13:12:51 +000044
45protected:
mtklein36352bf2015-03-25 18:17:31 -070046 const char* onGetName() override {
reed@google.comd34658a2011-04-11 13:12:51 +000047 fName.printf("path_%s_%s_",
48 fFlags & kStroke_Flag ? "stroke" : "fill",
49 fFlags & kBig_Flag ? "big" : "small");
50 this->appendName(&fName);
51 return fName.c_str();
52 }
53
mtkleina1ebeb22015-10-01 09:43:39 -070054 void onDraw(int loops, SkCanvas* canvas) override {
reed@google.comd34658a2011-04-11 13:12:51 +000055 SkPaint paint(fPaint);
56 this->setupPaint(&paint);
57
58 SkPath path;
59 this->makePath(&path);
60 if (fFlags & kBig_Flag) {
robertphillips1d24b8d2015-03-26 19:57:08 -070061 const SkMatrix m = SkMatrix::MakeScale(SkIntToScalar(10), SkIntToScalar(10));
reed@google.comd34658a2011-04-11 13:12:51 +000062 path.transform(m);
63 }
64
commit-bot@chromium.org33614712013-12-03 18:17:16 +000065 int count = loops;
reed@google.comd34658a2011-04-11 13:12:51 +000066 if (fFlags & kBig_Flag) {
67 count >>= 2;
68 }
tomhudson@google.com6e8d3352011-06-22 17:16:35 +000069 count >>= (3 * complexity());
reed@google.comd34658a2011-04-11 13:12:51 +000070
Yuqian Li9d5dcda2017-06-23 16:44:34 -040071 for (int i = 0; i < SkTMax(1, count); i++) {
reed@google.comd34658a2011-04-11 13:12:51 +000072 canvas->drawPath(path, paint);
73 }
74 }
75
76private:
tfarinaf168b862014-06-19 12:32:29 -070077 typedef Benchmark INHERITED;
reed@google.comd34658a2011-04-11 13:12:51 +000078};
79
80class TrianglePathBench : public PathBench {
81public:
mtklein@google.com410e6e82013-09-13 19:52:27 +000082 TrianglePathBench(Flags flags) : INHERITED(flags) {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +000083
mtklein36352bf2015-03-25 18:17:31 -070084 void appendName(SkString* name) override {
reed@google.comd34658a2011-04-11 13:12:51 +000085 name->append("triangle");
86 }
mtklein36352bf2015-03-25 18:17:31 -070087 void makePath(SkPath* path) override {
reed@google.comd34658a2011-04-11 13:12:51 +000088 static const int gCoord[] = {
89 10, 10, 15, 5, 20, 20
90 };
91 path->moveTo(SkIntToScalar(gCoord[0]), SkIntToScalar(gCoord[1]));
92 path->lineTo(SkIntToScalar(gCoord[2]), SkIntToScalar(gCoord[3]));
93 path->lineTo(SkIntToScalar(gCoord[4]), SkIntToScalar(gCoord[5]));
94 path->close();
95 }
96private:
97 typedef PathBench INHERITED;
98};
99
100class RectPathBench : public PathBench {
101public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000102 RectPathBench(Flags flags) : INHERITED(flags) {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000103
mtklein36352bf2015-03-25 18:17:31 -0700104 void appendName(SkString* name) override {
reed@google.comd34658a2011-04-11 13:12:51 +0000105 name->append("rect");
106 }
mtklein36352bf2015-03-25 18:17:31 -0700107 void makePath(SkPath* path) override {
reed@google.comd34658a2011-04-11 13:12:51 +0000108 SkRect r = { 10, 10, 20, 20 };
109 path->addRect(r);
110 }
111private:
112 typedef PathBench INHERITED;
113};
114
liyuqiana27f6692016-06-20 14:05:27 -0700115class RotatedRectBench : public PathBench {
116public:
117 RotatedRectBench(Flags flags, bool aa, int degrees) : INHERITED(flags) {
118 fAA = aa;
119 fDegrees = degrees;
120 }
121
122 void appendName(SkString* name) override {
123 SkString suffix;
124 suffix.printf("rotated_rect_%s_%d", fAA ? "aa" : "noaa", fDegrees);
125 name->append(suffix);
126 }
127
128 void makePath(SkPath* path) override {
129 SkRect r = { 10, 10, 20, 20 };
130 path->addRect(r);
131 SkMatrix rotateMatrix;
132 rotateMatrix.setRotate((SkScalar)fDegrees);
133 path->transform(rotateMatrix);
134 }
135
136 virtual void setupPaint(SkPaint* paint) override {
137 PathBench::setupPaint(paint);
138 paint->setAntiAlias(fAA);
139 }
140private:
141 typedef PathBench INHERITED;
142 int fDegrees;
143 bool fAA;
144};
145
reed@google.comd34658a2011-04-11 13:12:51 +0000146class OvalPathBench : public PathBench {
147public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000148 OvalPathBench(Flags flags) : INHERITED(flags) {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000149
mtklein36352bf2015-03-25 18:17:31 -0700150 void appendName(SkString* name) override {
reed@google.comd34658a2011-04-11 13:12:51 +0000151 name->append("oval");
152 }
mtklein36352bf2015-03-25 18:17:31 -0700153 void makePath(SkPath* path) override {
jvanverth@google.come2bfd8b2013-01-24 15:45:35 +0000154 SkRect r = { 10, 10, 23, 20 };
reed@google.comd34658a2011-04-11 13:12:51 +0000155 path->addOval(r);
156 }
157private:
158 typedef PathBench INHERITED;
159};
160
bsalomon@google.com1647a192012-04-11 15:34:46 +0000161class CirclePathBench: public PathBench {
162public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000163 CirclePathBench(Flags flags) : INHERITED(flags) {}
bsalomon@google.com1647a192012-04-11 15:34:46 +0000164
mtklein36352bf2015-03-25 18:17:31 -0700165 void appendName(SkString* name) override {
bsalomon@google.com1647a192012-04-11 15:34:46 +0000166 name->append("circle");
167 }
mtklein36352bf2015-03-25 18:17:31 -0700168 void makePath(SkPath* path) override {
bsalomon@google.com1647a192012-04-11 15:34:46 +0000169 path->addCircle(SkIntToScalar(20), SkIntToScalar(20),
170 SkIntToScalar(10));
171 }
172private:
173 typedef PathBench INHERITED;
174};
175
Yuqian Li8eedbfc2017-01-11 13:55:49 +0000176class NonAACirclePathBench: public CirclePathBench {
177public:
178 NonAACirclePathBench(Flags flags) : INHERITED(flags) {}
179
180 void appendName(SkString* name) override {
181 name->append("nonaacircle");
182 }
183
184 void setupPaint(SkPaint* paint) override {
185 CirclePathBench::setupPaint(paint);
186 paint->setAntiAlias(false);
187 }
188
189private:
190 typedef CirclePathBench INHERITED;
191};
192
Yuqian Li131c1fb2016-12-12 16:24:47 -0500193// Test max speedup of Analytic AA for concave paths
194class AAAConcavePathBench : public PathBench {
195public:
196 AAAConcavePathBench(Flags flags) : INHERITED(flags) {}
197
198 void appendName(SkString* name) override {
199 name->append("concave_aaa");
200 }
201
202 void makePath(SkPath* path) override {
203 path->moveTo(10, 10);
204 path->lineTo(15, 10);
205 path->lineTo(15, 5);
206 path->lineTo(40, 40);
207 path->close();
208 }
209
210private:
211 typedef PathBench INHERITED;
212};
213
214// Test max speedup of Analytic AA for convex paths
215class AAAConvexPathBench : public PathBench {
216public:
217 AAAConvexPathBench(Flags flags) : INHERITED(flags) {}
218
219 void appendName(SkString* name) override {
220 name->append("convex_aaa");
221 }
222
223 void makePath(SkPath* path) override {
224 path->moveTo(10, 10);
225 path->lineTo(15, 10);
226 path->lineTo(40, 50);
227 path->close();
228 }
229
230private:
231 typedef PathBench INHERITED;
232};
233
reed@google.comd34658a2011-04-11 13:12:51 +0000234class SawToothPathBench : public PathBench {
235public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000236 SawToothPathBench(Flags flags) : INHERITED(flags) {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000237
mtklein36352bf2015-03-25 18:17:31 -0700238 void appendName(SkString* name) override {
reed@google.comd34658a2011-04-11 13:12:51 +0000239 name->append("sawtooth");
240 }
mtkleinf0599002015-07-13 06:18:39 -0700241 void makePath(SkPath* path) override {
reed@google.comd34658a2011-04-11 13:12:51 +0000242 SkScalar x = SkIntToScalar(20);
243 SkScalar y = SkIntToScalar(20);
244 const SkScalar x0 = x;
245 const SkScalar dx = SK_Scalar1 * 5;
246 const SkScalar dy = SK_Scalar1 * 10;
247
248 path->moveTo(x, y);
249 for (int i = 0; i < 32; i++) {
250 x += dx;
251 path->lineTo(x, y - dy);
252 x += dx;
253 path->lineTo(x, y + dy);
254 }
255 path->lineTo(x, y + 2 * dy);
256 path->lineTo(x0, y + 2 * dy);
257 path->close();
258 }
mtklein36352bf2015-03-25 18:17:31 -0700259 int complexity() override { return 1; }
reed@google.comd34658a2011-04-11 13:12:51 +0000260private:
261 typedef PathBench INHERITED;
262};
263
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000264class LongCurvedPathBench : public PathBench {
265public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000266 LongCurvedPathBench(Flags flags) : INHERITED(flags) {}
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000267
mtklein36352bf2015-03-25 18:17:31 -0700268 void appendName(SkString* name) override {
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000269 name->append("long_curved");
270 }
mtklein36352bf2015-03-25 18:17:31 -0700271 void makePath(SkPath* path) override {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000272 SkRandom rand (12);
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000273 int i;
274 for (i = 0; i < 100; i++) {
Mike Reeddf85c382017-02-14 10:59:19 -0500275 path->quadTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480,
276 rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000277 }
278 path->close();
279 }
mtklein36352bf2015-03-25 18:17:31 -0700280 int complexity() override { return 2; }
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000281private:
282 typedef PathBench INHERITED;
283};
284
senorblanco@chromium.orge50f7362012-01-12 19:10:35 +0000285class LongLinePathBench : public PathBench {
286public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000287 LongLinePathBench(Flags flags) : INHERITED(flags) {}
senorblanco@chromium.orge50f7362012-01-12 19:10:35 +0000288
mtklein36352bf2015-03-25 18:17:31 -0700289 void appendName(SkString* name) override {
senorblanco@chromium.orge50f7362012-01-12 19:10:35 +0000290 name->append("long_line");
291 }
mtklein36352bf2015-03-25 18:17:31 -0700292 void makePath(SkPath* path) override {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000293 SkRandom rand;
senorblanco@chromium.orge50f7362012-01-12 19:10:35 +0000294 path->moveTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
295 for (size_t i = 1; i < 100; i++) {
296 path->lineTo(rand.nextUScalar1() * 640, rand.nextUScalar1() * 480);
297 }
298 }
mtklein36352bf2015-03-25 18:17:31 -0700299 int complexity() override { return 2; }
senorblanco@chromium.orge50f7362012-01-12 19:10:35 +0000300private:
301 typedef PathBench INHERITED;
302};
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000303
tfarinaf168b862014-06-19 12:32:29 -0700304class RandomPathBench : public Benchmark {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000305public:
mtklein36352bf2015-03-25 18:17:31 -0700306 bool isSuitableFor(Backend backend) override {
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000307 return backend == kNonRendering_Backend;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000308 }
309
310protected:
311 void createData(int minVerbs,
312 int maxVerbs,
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000313 bool allowMoves = true,
halcanary96fcdcc2015-08-27 07:41:13 -0700314 SkRect* bounds = nullptr) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000315 SkRect tempBounds;
halcanary96fcdcc2015-08-27 07:41:13 -0700316 if (nullptr == bounds) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000317 tempBounds.setXYWH(0, 0, SK_Scalar1, SK_Scalar1);
318 bounds = &tempBounds;
319 }
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000320 fVerbCnts.reset(kNumVerbCnts);
321 for (int i = 0; i < kNumVerbCnts; ++i) {
322 fVerbCnts[i] = fRandom.nextRangeU(minVerbs, maxVerbs + 1);
323 }
324 fVerbs.reset(kNumVerbs);
325 for (int i = 0; i < kNumVerbs; ++i) {
326 do {
327 fVerbs[i] = static_cast<SkPath::Verb>(fRandom.nextULessThan(SkPath::kDone_Verb));
328 } while (!allowMoves && SkPath::kMove_Verb == fVerbs[i]);
329 }
330 fPoints.reset(kNumPoints);
331 for (int i = 0; i < kNumPoints; ++i) {
332 fPoints[i].set(fRandom.nextRangeScalar(bounds->fLeft, bounds->fRight),
333 fRandom.nextRangeScalar(bounds->fTop, bounds->fBottom));
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000334 }
335 this->restartMakingPaths();
336 }
337
338 void restartMakingPaths() {
339 fCurrPath = 0;
340 fCurrVerb = 0;
341 fCurrPoint = 0;
342 }
343
344 void makePath(SkPath* path) {
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000345 int vCount = fVerbCnts[(fCurrPath++) & (kNumVerbCnts - 1)];
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000346 for (int v = 0; v < vCount; ++v) {
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000347 int verb = fVerbs[(fCurrVerb++) & (kNumVerbs - 1)];
348 switch (verb) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000349 case SkPath::kMove_Verb:
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000350 path->moveTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000351 break;
352 case SkPath::kLine_Verb:
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000353 path->lineTo(fPoints[(fCurrPoint++) & (kNumPoints - 1)]);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000354 break;
355 case SkPath::kQuad_Verb:
bsalomon@google.com373ebc62012-09-26 13:08:56 +0000356 path->quadTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
357 fPoints[(fCurrPoint + 1) & (kNumPoints - 1)]);
358 fCurrPoint += 2;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000359 break;
reed@google.com277c3f82013-05-31 15:17:50 +0000360 case SkPath::kConic_Verb:
361 path->conicTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
362 fPoints[(fCurrPoint + 1) & (kNumPoints - 1)],
363 SK_ScalarHalf);
364 fCurrPoint += 2;
365 break;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000366 case SkPath::kCubic_Verb:
bsalomon@google.com373ebc62012-09-26 13:08:56 +0000367 path->cubicTo(fPoints[(fCurrPoint + 0) & (kNumPoints - 1)],
368 fPoints[(fCurrPoint + 1) & (kNumPoints - 1)],
369 fPoints[(fCurrPoint + 2) & (kNumPoints - 1)]);
370 fCurrPoint += 3;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000371 break;
372 case SkPath::kClose_Verb:
373 path->close();
374 break;
375 default:
376 SkDEBUGFAIL("Unexpected path verb");
377 break;
378 }
379 }
380 }
381
382 void finishedMakingPaths() {
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000383 fVerbCnts.reset(0);
384 fVerbs.reset(0);
385 fPoints.reset(0);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000386 }
387
388private:
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000389 enum {
390 // these should all be pow 2
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000391 kNumVerbCnts = 1 << 5,
392 kNumVerbs = 1 << 5,
393 kNumPoints = 1 << 5,
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000394 };
395 SkAutoTArray<int> fVerbCnts;
396 SkAutoTArray<SkPath::Verb> fVerbs;
397 SkAutoTArray<SkPoint> fPoints;
398 int fCurrPath;
399 int fCurrVerb;
400 int fCurrPoint;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000401 SkRandom fRandom;
tfarinaf168b862014-06-19 12:32:29 -0700402 typedef Benchmark INHERITED;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000403};
404
405class PathCreateBench : public RandomPathBench {
406public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000407 PathCreateBench() {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000408 }
409
410protected:
mtklein36352bf2015-03-25 18:17:31 -0700411 const char* onGetName() override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000412 return "path_create";
413 }
414
joshualitt8a6697a2015-09-30 12:11:07 -0700415 void onDelayedSetup() override {
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000416 this->createData(10, 100);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000417 }
418
mtkleina1ebeb22015-10-01 09:43:39 -0700419 void onDraw(int loops, SkCanvas*) override {
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000420 for (int i = 0; i < loops; ++i) {
commit-bot@chromium.org8f881172014-01-06 20:19:14 +0000421 if (i % 1000 == 0) {
422 fPath.reset(); // PathRef memory can grow without bound otherwise.
423 }
424 this->makePath(&fPath);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000425 }
426 this->restartMakingPaths();
427 }
428
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000429private:
commit-bot@chromium.org8f881172014-01-06 20:19:14 +0000430 SkPath fPath;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000431
432 typedef RandomPathBench INHERITED;
433};
434
435class PathCopyBench : public RandomPathBench {
436public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000437 PathCopyBench() {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000438 }
439
440protected:
mtklein36352bf2015-03-25 18:17:31 -0700441 const char* onGetName() override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000442 return "path_copy";
443 }
joshualitt8a6697a2015-09-30 12:11:07 -0700444 void onDelayedSetup() override {
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000445 this->createData(10, 100);
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000446 fPaths.reset(kPathCnt);
447 fCopies.reset(kPathCnt);
448 for (int i = 0; i < kPathCnt; ++i) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000449 this->makePath(&fPaths[i]);
450 }
451 this->finishedMakingPaths();
452 }
mtkleina1ebeb22015-10-01 09:43:39 -0700453 void onDraw(int loops, SkCanvas*) override {
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000454 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000455 int idx = i & (kPathCnt - 1);
456 fCopies[idx] = fPaths[idx];
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000457 }
458 }
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000459
460private:
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000461 enum {
462 // must be a pow 2
463 kPathCnt = 1 << 5,
464 };
465 SkAutoTArray<SkPath> fPaths;
466 SkAutoTArray<SkPath> fCopies;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000467
468 typedef RandomPathBench INHERITED;
469};
470
471class PathTransformBench : public RandomPathBench {
472public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000473 PathTransformBench(bool inPlace) : fInPlace(inPlace) {}
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000474
475protected:
mtklein36352bf2015-03-25 18:17:31 -0700476 const char* onGetName() override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000477 return fInPlace ? "path_transform_in_place" : "path_transform_copy";
478 }
479
joshualitt8a6697a2015-09-30 12:11:07 -0700480 void onDelayedSetup() override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000481 fMatrix.setScale(5 * SK_Scalar1, 6 * SK_Scalar1);
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000482 this->createData(10, 100);
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000483 fPaths.reset(kPathCnt);
484 for (int i = 0; i < kPathCnt; ++i) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000485 this->makePath(&fPaths[i]);
486 }
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000487 this->finishedMakingPaths();
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000488 if (!fInPlace) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000489 fTransformed.reset(kPathCnt);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000490 }
491 }
492
mtkleina1ebeb22015-10-01 09:43:39 -0700493 void onDraw(int loops, SkCanvas*) override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000494 if (fInPlace) {
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000495 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000496 fPaths[i & (kPathCnt - 1)].transform(fMatrix);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000497 }
498 } else {
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000499 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000500 int idx = i & (kPathCnt - 1);
501 fPaths[idx].transform(fMatrix, &fTransformed[idx]);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000502 }
503 }
504 }
505
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000506private:
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000507 enum {
508 // must be a pow 2
509 kPathCnt = 1 << 5,
510 };
511 SkAutoTArray<SkPath> fPaths;
512 SkAutoTArray<SkPath> fTransformed;
513
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000514 SkMatrix fMatrix;
515 bool fInPlace;
516 typedef RandomPathBench INHERITED;
517};
518
519class PathEqualityBench : public RandomPathBench {
520public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000521 PathEqualityBench() { }
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000522
523protected:
mtklein36352bf2015-03-25 18:17:31 -0700524 const char* onGetName() override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000525 return "path_equality_50%";
526 }
527
joshualitt8a6697a2015-09-30 12:11:07 -0700528 void onDelayedSetup() override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000529 fParity = 0;
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000530 this->createData(10, 100);
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000531 fPaths.reset(kPathCnt);
532 fCopies.reset(kPathCnt);
533 for (int i = 0; i < kPathCnt; ++i) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000534 this->makePath(&fPaths[i]);
535 fCopies[i] = fPaths[i];
536 }
537 this->finishedMakingPaths();
538 }
539
mtkleina1ebeb22015-10-01 09:43:39 -0700540 void onDraw(int loops, SkCanvas*) override {
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000541 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000542 int idx = i & (kPathCnt - 1);
543 fParity ^= (fPaths[idx] == fCopies[idx & ~0x1]);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000544 }
545 }
546
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000547private:
548 bool fParity; // attempt to keep compiler from optimizing out the ==
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000549 enum {
550 // must be a pow 2
551 kPathCnt = 1 << 5,
552 };
553 SkAutoTArray<SkPath> fPaths;
554 SkAutoTArray<SkPath> fCopies;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000555 typedef RandomPathBench INHERITED;
556};
557
558class SkBench_AddPathTest : public RandomPathBench {
559public:
560 enum AddType {
561 kAdd_AddType,
562 kAddTrans_AddType,
563 kAddMatrix_AddType,
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000564 kReverseAdd_AddType,
565 kReversePathTo_AddType,
566 };
567
mtklein@google.com410e6e82013-09-13 19:52:27 +0000568 SkBench_AddPathTest(AddType type) : fType(type) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000569 fMatrix.setRotate(60 * SK_Scalar1);
570 }
571
572protected:
mtklein36352bf2015-03-25 18:17:31 -0700573 const char* onGetName() override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000574 switch (fType) {
575 case kAdd_AddType:
576 return "path_add_path";
577 case kAddTrans_AddType:
578 return "path_add_path_trans";
579 case kAddMatrix_AddType:
580 return "path_add_path_matrix";
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000581 case kReverseAdd_AddType:
582 return "path_reverse_add_path";
583 case kReversePathTo_AddType:
584 return "path_reverse_path_to";
585 default:
586 SkDEBUGFAIL("Bad add type");
587 return "";
588 }
589 }
590
joshualitt8a6697a2015-09-30 12:11:07 -0700591 void onDelayedSetup() override {
commit-bot@chromium.orga1a097e2013-11-14 16:53:22 +0000592 // reversePathTo assumes a single contour path.
593 bool allowMoves = kReversePathTo_AddType != fType;
bsalomon@google.com6d552ee2012-08-14 15:10:09 +0000594 this->createData(10, 100, allowMoves);
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000595 fPaths0.reset(kPathCnt);
596 fPaths1.reset(kPathCnt);
597 for (int i = 0; i < kPathCnt; ++i) {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000598 this->makePath(&fPaths0[i]);
599 this->makePath(&fPaths1[i]);
600 }
601 this->finishedMakingPaths();
602 }
603
mtkleina1ebeb22015-10-01 09:43:39 -0700604 void onDraw(int loops, SkCanvas*) override {
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000605 switch (fType) {
606 case kAdd_AddType:
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000607 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000608 int idx = i & (kPathCnt - 1);
609 SkPath result = fPaths0[idx];
610 result.addPath(fPaths1[idx]);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000611 }
612 break;
613 case kAddTrans_AddType:
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000614 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000615 int idx = i & (kPathCnt - 1);
616 SkPath result = fPaths0[idx];
617 result.addPath(fPaths1[idx], 2 * SK_Scalar1, 5 * SK_Scalar1);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000618 }
619 break;
620 case kAddMatrix_AddType:
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000621 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000622 int idx = i & (kPathCnt - 1);
623 SkPath result = fPaths0[idx];
624 result.addPath(fPaths1[idx], fMatrix);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000625 }
626 break;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000627 case kReverseAdd_AddType:
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000628 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000629 int idx = i & (kPathCnt - 1);
630 SkPath result = fPaths0[idx];
631 result.reverseAddPath(fPaths1[idx]);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000632 }
633 break;
634 case kReversePathTo_AddType:
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000635 for (int i = 0; i < loops; ++i) {
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000636 int idx = i & (kPathCnt - 1);
637 SkPath result = fPaths0[idx];
638 result.reversePathTo(fPaths1[idx]);
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000639 }
640 break;
641 }
642 }
643
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000644private:
645 AddType fType; // or reverseAddPath
bsalomon@google.comb5e47032012-08-14 17:49:46 +0000646 enum {
647 // must be a pow 2
648 kPathCnt = 1 << 5,
649 };
650 SkAutoTArray<SkPath> fPaths0;
651 SkAutoTArray<SkPath> fPaths1;
bsalomon@google.com30e6d2c2012-08-13 14:03:31 +0000652 SkMatrix fMatrix;
653 typedef RandomPathBench INHERITED;
654};
tomhudson@google.com6e8d3352011-06-22 17:16:35 +0000655
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000656
tfarinaf168b862014-06-19 12:32:29 -0700657class CirclesBench : public Benchmark {
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000658protected:
659 SkString fName;
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000660 Flags fFlags;
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000661
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000662public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000663 CirclesBench(Flags flags) : fFlags(flags) {
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000664 fName.printf("circles_%s", fFlags & kStroke_Flag ? "stroke" : "fill");
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000665 }
666
667protected:
mtklein36352bf2015-03-25 18:17:31 -0700668 const char* onGetName() override {
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000669 return fName.c_str();
670 }
671
mtkleina1ebeb22015-10-01 09:43:39 -0700672 void onDraw(int loops, SkCanvas* canvas) override {
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000673 SkPaint paint;
674
675 paint.setColor(SK_ColorBLACK);
676 paint.setAntiAlias(true);
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000677 if (fFlags & kStroke_Flag) {
678 paint.setStyle(SkPaint::kStroke_Style);
679 }
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000680
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000681 SkRandom rand;
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000682
683 SkRect r;
684
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000685 for (int i = 0; i < loops; ++i) {
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000686 SkScalar radius = rand.nextUScalar1() * 3;
687 r.fLeft = rand.nextUScalar1() * 300;
688 r.fTop = rand.nextUScalar1() * 300;
689 r.fRight = r.fLeft + 2 * radius;
690 r.fBottom = r.fTop + 2 * radius;
691
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000692 if (fFlags & kStroke_Flag) {
693 paint.setStrokeWidth(rand.nextUScalar1() * 5.0f);
694 }
695
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000696 SkPath temp;
697
698 // mimic how Chrome does circles
699 temp.arcTo(r, 0, 0, false);
700 temp.addOval(r, SkPath::kCCW_Direction);
701 temp.arcTo(r, 360, 0, true);
702 temp.close();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000703
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000704 canvas->drawPath(temp, paint);
705 }
706 }
707
708private:
tfarinaf168b862014-06-19 12:32:29 -0700709 typedef Benchmark INHERITED;
robertphillips@google.com17bb4582012-08-20 17:24:16 +0000710};
711
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000712
robertphillips@google.com158618e2012-10-23 16:56:56 +0000713// Chrome creates its own round rects with each corner possibly being different.
714// In its "zero radius" incarnation it creates degenerate round rects.
skia.committer@gmail.com1e34ff72012-10-24 02:01:24 +0000715// Note: PathTest::test_arb_round_rect_is_convex and
robertphillips@google.com158618e2012-10-23 16:56:56 +0000716// test_arb_zero_rad_round_rect_is_rect perform almost exactly
robertphillips@google.comb95eaa82012-10-18 15:26:12 +0000717// the same test (but with no drawing)
tfarinaf168b862014-06-19 12:32:29 -0700718class ArbRoundRectBench : public Benchmark {
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000719protected:
720 SkString fName;
721
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000722public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000723 ArbRoundRectBench(bool zeroRad) : fZeroRad(zeroRad) {
robertphillips@google.com158618e2012-10-23 16:56:56 +0000724 if (zeroRad) {
725 fName.printf("zeroradroundrect");
726 } else {
727 fName.printf("arbroundrect");
728 }
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000729 }
730
731protected:
mtklein36352bf2015-03-25 18:17:31 -0700732 const char* onGetName() override {
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000733 return fName.c_str();
734 }
735
skia.committer@gmail.com989a95e2012-10-18 02:01:23 +0000736 static void add_corner_arc(SkPath* path, const SkRect& rect,
737 SkScalar xIn, SkScalar yIn,
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000738 int startAngle)
739 {
740
741 SkScalar rx = SkMinScalar(rect.width(), xIn);
742 SkScalar ry = SkMinScalar(rect.height(), yIn);
743
744 SkRect arcRect;
745 arcRect.set(-rx, -ry, rx, ry);
746 switch (startAngle) {
747 case 0:
748 arcRect.offset(rect.fRight - arcRect.fRight, rect.fBottom - arcRect.fBottom);
749 break;
750 case 90:
751 arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fBottom - arcRect.fBottom);
752 break;
753 case 180:
754 arcRect.offset(rect.fLeft - arcRect.fLeft, rect.fTop - arcRect.fTop);
755 break;
756 case 270:
757 arcRect.offset(rect.fRight - arcRect.fRight, rect.fTop - arcRect.fTop);
758 break;
759 default:
760 break;
761 }
762
763 path->arcTo(arcRect, SkIntToScalar(startAngle), SkIntToScalar(90), false);
764 }
765
skia.committer@gmail.com989a95e2012-10-18 02:01:23 +0000766 static void make_arb_round_rect(SkPath* path, const SkRect& r,
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000767 SkScalar xCorner, SkScalar yCorner) {
768 // we are lazy here and use the same x & y for each corner
769 add_corner_arc(path, r, xCorner, yCorner, 270);
770 add_corner_arc(path, r, xCorner, yCorner, 0);
771 add_corner_arc(path, r, xCorner, yCorner, 90);
772 add_corner_arc(path, r, xCorner, yCorner, 180);
robertphillips@google.com158618e2012-10-23 16:56:56 +0000773 path->close();
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000774
robertphillips@google.comb95eaa82012-10-18 15:26:12 +0000775 SkASSERT(path->isConvex());
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000776 }
777
mtkleina1ebeb22015-10-01 09:43:39 -0700778 void onDraw(int loops, SkCanvas* canvas) override {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000779 SkRandom rand;
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000780 SkRect r;
781
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000782 for (int i = 0; i < loops; ++i) {
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000783 SkPaint paint;
784 paint.setColor(0xff000000 | rand.nextU());
785 paint.setAntiAlias(true);
786
robertphillips@google.com158618e2012-10-23 16:56:56 +0000787 SkScalar size = rand.nextUScalar1() * 30;
788 if (size < SK_Scalar1) {
robertphillips@google.comb95eaa82012-10-18 15:26:12 +0000789 continue;
790 }
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000791 r.fLeft = rand.nextUScalar1() * 300;
792 r.fTop = rand.nextUScalar1() * 300;
robertphillips@google.com158618e2012-10-23 16:56:56 +0000793 r.fRight = r.fLeft + 2 * size;
794 r.fBottom = r.fTop + 2 * size;
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000795
796 SkPath temp;
797
robertphillips@google.com158618e2012-10-23 16:56:56 +0000798 if (fZeroRad) {
799 make_arb_round_rect(&temp, r, 0, 0);
800
halcanary96fcdcc2015-08-27 07:41:13 -0700801 SkASSERT(temp.isRect(nullptr));
robertphillips@google.com158618e2012-10-23 16:56:56 +0000802 } else {
803 make_arb_round_rect(&temp, r, r.width() / 10, r.height() / 15);
804 }
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000805
806 canvas->drawPath(temp, paint);
807 }
808 }
809
810private:
robertphillips@google.com158618e2012-10-23 16:56:56 +0000811 bool fZeroRad; // should 0 radius rounds rects be tested?
812
tfarinaf168b862014-06-19 12:32:29 -0700813 typedef Benchmark INHERITED;
robertphillips@google.comf6fc3fc2012-10-17 15:23:21 +0000814};
815
tfarinaf168b862014-06-19 12:32:29 -0700816class ConservativelyContainsBench : public Benchmark {
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000817public:
818 enum Type {
819 kRect_Type,
820 kRoundRect_Type,
821 kOval_Type,
822 };
823
mtklein@google.com410e6e82013-09-13 19:52:27 +0000824 ConservativelyContainsBench(Type type) {
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000825 fParity = false;
826 fName = "conservatively_contains_";
827 switch (type) {
828 case kRect_Type:
829 fName.append("rect");
830 fPath.addRect(kBaseRect);
831 break;
832 case kRoundRect_Type:
833 fName.append("round_rect");
834 fPath.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1]);
835 break;
836 case kOval_Type:
837 fName.append("oval");
838 fPath.addOval(kBaseRect);
839 break;
840 }
841 }
842
mtklein36352bf2015-03-25 18:17:31 -0700843 bool isSuitableFor(Backend backend) override {
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000844 return backend == kNonRendering_Backend;
845 }
846
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000847private:
mtklein36352bf2015-03-25 18:17:31 -0700848 const char* onGetName() override {
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000849 return fName.c_str();
850 }
851
mtkleina1ebeb22015-10-01 09:43:39 -0700852 void onDraw(int loops, SkCanvas*) override {
commit-bot@chromium.org33614712013-12-03 18:17:16 +0000853 for (int i = 0; i < loops; ++i) {
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000854 const SkRect& rect = fQueryRects[i % kQueryRectCnt];
855 fParity = fParity != fPath.conservativelyContainsRect(rect);
856 }
857 }
858
joshualitt8a6697a2015-09-30 12:11:07 -0700859 void onDelayedSetup() override {
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000860 fQueryRects.setCount(kQueryRectCnt);
861
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000862 SkRandom rand;
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000863 for (int i = 0; i < kQueryRectCnt; ++i) {
864 SkSize size;
865 SkPoint xy;
866 size.fWidth = rand.nextRangeScalar(kQueryMin.fWidth, kQueryMax.fWidth);
867 size.fHeight = rand.nextRangeScalar(kQueryMin.fHeight, kQueryMax.fHeight);
868 xy.fX = rand.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth);
869 xy.fY = rand.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight);
870
871 fQueryRects[i] = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
872 }
873 }
874
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000875 enum {
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000876 kQueryRectCnt = 400,
877 };
878 static const SkRect kBounds; // bounds for all random query rects
879 static const SkSize kQueryMin; // minimum query rect size, should be <= kQueryMax
880 static const SkSize kQueryMax; // max query rect size, should < kBounds
881 static const SkRect kBaseRect; // rect that is used to construct the path
882 static const SkScalar kRRRadii[2]; // x and y radii for round rect
883
884 SkString fName;
885 SkPath fPath;
886 bool fParity;
887 SkTDArray<SkRect> fQueryRects;
888
tfarinaf168b862014-06-19 12:32:29 -0700889 typedef Benchmark INHERITED;
bsalomon@google.com9bee33a2012-11-13 21:51:38 +0000890};
891
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000892///////////////////////////////////////////////////////////////////////////////
893
894#include "SkGeometry.h"
895
reed55011032015-03-26 09:10:22 -0700896class ConicBench_Chop : public Benchmark {
reedb6402032015-03-20 13:23:43 -0700897protected:
898 SkConic fRQ, fDst[2];
899 SkString fName;
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000900public:
reed55011032015-03-26 09:10:22 -0700901 ConicBench_Chop() : fName("conic-chop") {
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000902 fRQ.fPts[0].set(0, 0);
903 fRQ.fPts[1].set(100, 0);
904 fRQ.fPts[2].set(100, 100);
905 fRQ.fW = SkScalarCos(SK_ScalarPI/4);
reedb6402032015-03-20 13:23:43 -0700906 }
907
mtklein36352bf2015-03-25 18:17:31 -0700908 bool isSuitableFor(Backend backend) override {
reedb6402032015-03-20 13:23:43 -0700909 return backend == kNonRendering_Backend;
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000910 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +0000911
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000912private:
mtklein36352bf2015-03-25 18:17:31 -0700913 const char* onGetName() override { return fName.c_str(); }
skia.committer@gmail.com81521132013-04-30 07:01:03 +0000914
mtkleina1ebeb22015-10-01 09:43:39 -0700915 void onDraw(int loops, SkCanvas*) override {
reed55011032015-03-26 09:10:22 -0700916 for (int i = 0; i < loops; ++i) {
917 fRQ.chop(fDst);
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000918 }
919 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +0000920
tfarinaf168b862014-06-19 12:32:29 -0700921 typedef Benchmark INHERITED;
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000922};
reed55011032015-03-26 09:10:22 -0700923DEF_BENCH( return new ConicBench_Chop; )
reedb6402032015-03-20 13:23:43 -0700924
reed55011032015-03-26 09:10:22 -0700925class ConicBench_EvalPos : public ConicBench_Chop {
926 const bool fUseV2;
reedb6402032015-03-20 13:23:43 -0700927public:
reed55011032015-03-26 09:10:22 -0700928 ConicBench_EvalPos(bool useV2) : fUseV2(useV2) {
reedb6402032015-03-20 13:23:43 -0700929 fName.printf("conic-eval-pos%d", useV2);
930 }
mtkleina1ebeb22015-10-01 09:43:39 -0700931 void onDraw(int loops, SkCanvas*) override {
reedb6402032015-03-20 13:23:43 -0700932 if (fUseV2) {
933 for (int i = 0; i < loops; ++i) {
934 for (int j = 0; j < 1000; ++j) {
935 fDst[0].fPts[0] = fRQ.evalAt(0.4f);
936 }
937 }
938 } else {
939 for (int i = 0; i < loops; ++i) {
940 for (int j = 0; j < 1000; ++j) {
halcanary96fcdcc2015-08-27 07:41:13 -0700941 fRQ.evalAt(0.4f, &fDst[0].fPts[0], nullptr);
reedb6402032015-03-20 13:23:43 -0700942 }
943 }
944 }
945 }
946};
947DEF_BENCH( return new ConicBench_EvalPos(false); )
948DEF_BENCH( return new ConicBench_EvalPos(true); )
949
reed55011032015-03-26 09:10:22 -0700950class ConicBench_EvalTan : public ConicBench_Chop {
951 const bool fUseV2;
reedb6402032015-03-20 13:23:43 -0700952public:
reed55011032015-03-26 09:10:22 -0700953 ConicBench_EvalTan(bool useV2) : fUseV2(useV2) {
reedb6402032015-03-20 13:23:43 -0700954 fName.printf("conic-eval-tan%d", useV2);
955 }
mtkleina1ebeb22015-10-01 09:43:39 -0700956 void onDraw(int loops, SkCanvas*) override {
reedb6402032015-03-20 13:23:43 -0700957 if (fUseV2) {
958 for (int i = 0; i < loops; ++i) {
959 for (int j = 0; j < 1000; ++j) {
960 fDst[0].fPts[0] = fRQ.evalTangentAt(0.4f);
961 }
962 }
963 } else {
964 for (int i = 0; i < loops; ++i) {
965 for (int j = 0; j < 1000; ++j) {
halcanary96fcdcc2015-08-27 07:41:13 -0700966 fRQ.evalAt(0.4f, nullptr, &fDst[0].fPts[0]);
reedb6402032015-03-20 13:23:43 -0700967 }
968 }
969 }
970 }
971};
972DEF_BENCH( return new ConicBench_EvalTan(false); )
973DEF_BENCH( return new ConicBench_EvalTan(true); )
mike@reedtribe.org8d551012013-04-14 02:40:50 +0000974
975///////////////////////////////////////////////////////////////////////////////
976
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000977static void rand_conic(SkConic* conic, SkRandom& rand) {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +0000978 for (int i = 0; i < 3; ++i) {
979 conic->fPts[i].set(rand.nextUScalar1() * 100, rand.nextUScalar1() * 100);
980 }
981 if (rand.nextUScalar1() > 0.5f) {
982 conic->fW = rand.nextUScalar1();
983 } else {
984 conic->fW = 1 + rand.nextUScalar1() * 4;
985 }
986}
987
tfarinaf168b862014-06-19 12:32:29 -0700988class ConicBench : public Benchmark {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +0000989public:
mtklein@google.com410e6e82013-09-13 19:52:27 +0000990 ConicBench() {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000991 SkRandom rand;
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +0000992 for (int i = 0; i < CONICS; ++i) {
993 rand_conic(&fConics[i], rand);
994 }
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000995 }
996
mtklein36352bf2015-03-25 18:17:31 -0700997 bool isSuitableFor(Backend backend) override {
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000998 return backend == kNonRendering_Backend;
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +0000999 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001000
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001001protected:
1002 enum {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001003 CONICS = 100
1004 };
1005 SkConic fConics[CONICS];
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001006
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001007private:
tfarinaf168b862014-06-19 12:32:29 -07001008 typedef Benchmark INHERITED;
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001009};
1010
1011class ConicBench_ComputeError : public ConicBench {
1012public:
mtklein@google.com410e6e82013-09-13 19:52:27 +00001013 ConicBench_ComputeError() {}
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001014
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001015protected:
mtklein36352bf2015-03-25 18:17:31 -07001016 const char* onGetName() override {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001017 return "conic-compute-error";
1018 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001019
mtkleina1ebeb22015-10-01 09:43:39 -07001020 void onDraw(int loops, SkCanvas*) override {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001021 SkVector err;
commit-bot@chromium.org33614712013-12-03 18:17:16 +00001022 for (int i = 0; i < loops; ++i) {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001023 for (int j = 0; j < CONICS; ++j) {
1024 fConics[j].computeAsQuadError(&err);
1025 }
1026 }
1027 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001028
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001029private:
1030 typedef ConicBench INHERITED;
1031};
1032
1033class ConicBench_asQuadTol : public ConicBench {
1034public:
mtklein@google.com410e6e82013-09-13 19:52:27 +00001035 ConicBench_asQuadTol() {}
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001036
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001037protected:
mtklein36352bf2015-03-25 18:17:31 -07001038 const char* onGetName() override {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001039 return "conic-asQuadTol";
1040 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001041
mtkleina1ebeb22015-10-01 09:43:39 -07001042 void onDraw(int loops, SkCanvas*) override {
commit-bot@chromium.org33614712013-12-03 18:17:16 +00001043 for (int i = 0; i < loops; ++i) {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001044 for (int j = 0; j < CONICS; ++j) {
1045 fConics[j].asQuadTol(SK_ScalarHalf);
1046 }
1047 }
1048 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001049
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001050private:
1051 typedef ConicBench INHERITED;
1052};
1053
1054class ConicBench_quadPow2 : public ConicBench {
1055public:
mtklein@google.com410e6e82013-09-13 19:52:27 +00001056 ConicBench_quadPow2() {}
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001057
1058protected:
mtklein36352bf2015-03-25 18:17:31 -07001059 const char* onGetName() override {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001060 return "conic-quadPow2";
1061 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001062
mtkleina1ebeb22015-10-01 09:43:39 -07001063 void onDraw(int loops, SkCanvas*) override {
commit-bot@chromium.org33614712013-12-03 18:17:16 +00001064 for (int i = 0; i < loops; ++i) {
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001065 for (int j = 0; j < CONICS; ++j) {
1066 fConics[j].computeQuadPOW2(SK_ScalarHalf);
1067 }
1068 }
1069 }
skia.committer@gmail.com81521132013-04-30 07:01:03 +00001070
mike@reedtribe.orgaf5c5062013-04-30 02:14:58 +00001071private:
1072 typedef ConicBench INHERITED;
1073};
1074
1075///////////////////////////////////////////////////////////////////////////////
1076
Mike Reed0d7dac82017-02-02 17:45:56 -08001077class TightBoundsBench : public Benchmark {
1078 SkPath fPath;
1079 SkString fName;
Mike Reed8d3196b2017-02-03 11:34:13 -05001080 SkRect (*fProc)(const SkPath&);
Mike Reed0d7dac82017-02-02 17:45:56 -08001081
1082public:
Mike Reed8d3196b2017-02-03 11:34:13 -05001083 TightBoundsBench(SkRect (*proc)(const SkPath&), const char suffix[]) : fProc(proc) {
Mike Reed0d7dac82017-02-02 17:45:56 -08001084 fName.printf("tight_bounds_%s", suffix);
Yuqian Li9d5dcda2017-06-23 16:44:34 -04001085
Mike Reed0d7dac82017-02-02 17:45:56 -08001086 const int N = 100;
1087 SkRandom rand;
1088 for (int i = 0; i < N; ++i) {
1089 fPath.moveTo(rand.nextF()*100, rand.nextF()*100);
1090 fPath.lineTo(rand.nextF()*100, rand.nextF()*100);
1091 fPath.quadTo(rand.nextF()*100, rand.nextF()*100, rand.nextF()*100, rand.nextF()*100);
1092 fPath.conicTo(rand.nextF()*100, rand.nextF()*100, rand.nextF()*100, rand.nextF()*100,
1093 rand.nextF()*10);
1094 fPath.cubicTo(rand.nextF()*100, rand.nextF()*100, rand.nextF()*100, rand.nextF()*100,
1095 rand.nextF()*100, rand.nextF()*100);
1096 }
1097 }
1098
1099protected:
1100 bool isSuitableFor(Backend backend) override {
1101 return backend == kNonRendering_Backend;
1102 }
1103
1104 const char* onGetName() override { return fName.c_str(); }
Yuqian Li9d5dcda2017-06-23 16:44:34 -04001105
Mike Reed0d7dac82017-02-02 17:45:56 -08001106 void onDraw(int loops, SkCanvas* canvas) override {
Mike Reed0d7dac82017-02-02 17:45:56 -08001107 for (int i = 0; i < loops*100; ++i) {
Mike Reed8d3196b2017-02-03 11:34:13 -05001108 fProc(fPath);
Mike Reed0d7dac82017-02-02 17:45:56 -08001109 }
1110 }
Yuqian Li9d5dcda2017-06-23 16:44:34 -04001111
Mike Reed0d7dac82017-02-02 17:45:56 -08001112private:
1113 typedef Benchmark INHERITED;
1114};
1115
1116
bsalomon@google.com9bee33a2012-11-13 21:51:38 +00001117const SkRect ConservativelyContainsBench::kBounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
Hal Canaryfafe1352017-04-11 12:12:02 -04001118const SkSize ConservativelyContainsBench::kQueryMin = {SkIntToScalar(1), SkIntToScalar(1)};
1119const SkSize ConservativelyContainsBench::kQueryMax = {SkIntToScalar(40), SkIntToScalar(40)};
bsalomon@google.com9bee33a2012-11-13 21:51:38 +00001120const SkRect ConservativelyContainsBench::kBaseRect = SkRect::MakeXYWH(SkIntToScalar(25), SkIntToScalar(25), SkIntToScalar(50), SkIntToScalar(50));
1121const SkScalar ConservativelyContainsBench::kRRRadii[2] = {SkIntToScalar(5), SkIntToScalar(10)};
1122
mtklein@google.com410e6e82013-09-13 19:52:27 +00001123DEF_BENCH( return new TrianglePathBench(FLAGS00); )
1124DEF_BENCH( return new TrianglePathBench(FLAGS01); )
1125DEF_BENCH( return new TrianglePathBench(FLAGS10); )
1126DEF_BENCH( return new TrianglePathBench(FLAGS11); )
reed@google.comd34658a2011-04-11 13:12:51 +00001127
mtklein@google.com410e6e82013-09-13 19:52:27 +00001128DEF_BENCH( return new RectPathBench(FLAGS00); )
1129DEF_BENCH( return new RectPathBench(FLAGS01); )
1130DEF_BENCH( return new RectPathBench(FLAGS10); )
1131DEF_BENCH( return new RectPathBench(FLAGS11); )
reed@google.comd34658a2011-04-11 13:12:51 +00001132
liyuqiana27f6692016-06-20 14:05:27 -07001133DEF_BENCH( return new RotatedRectBench(FLAGS00, false, 45));
1134DEF_BENCH( return new RotatedRectBench(FLAGS10, false, 45));
1135DEF_BENCH( return new RotatedRectBench(FLAGS00, true, 45));
1136DEF_BENCH( return new RotatedRectBench(FLAGS10, true, 45));
1137
mtklein@google.com410e6e82013-09-13 19:52:27 +00001138DEF_BENCH( return new OvalPathBench(FLAGS00); )
1139DEF_BENCH( return new OvalPathBench(FLAGS01); )
1140DEF_BENCH( return new OvalPathBench(FLAGS10); )
1141DEF_BENCH( return new OvalPathBench(FLAGS11); )
reed@google.comd34658a2011-04-11 13:12:51 +00001142
mtklein@google.com410e6e82013-09-13 19:52:27 +00001143DEF_BENCH( return new CirclePathBench(FLAGS00); )
1144DEF_BENCH( return new CirclePathBench(FLAGS01); )
1145DEF_BENCH( return new CirclePathBench(FLAGS10); )
1146DEF_BENCH( return new CirclePathBench(FLAGS11); )
bsalomon@google.com1647a192012-04-11 15:34:46 +00001147
Yuqian Li8eedbfc2017-01-11 13:55:49 +00001148DEF_BENCH( return new NonAACirclePathBench(FLAGS00); )
1149DEF_BENCH( return new NonAACirclePathBench(FLAGS10); )
1150
Yuqian Li131c1fb2016-12-12 16:24:47 -05001151DEF_BENCH( return new AAAConcavePathBench(FLAGS00); )
1152DEF_BENCH( return new AAAConcavePathBench(FLAGS10); )
1153DEF_BENCH( return new AAAConvexPathBench(FLAGS00); )
1154DEF_BENCH( return new AAAConvexPathBench(FLAGS10); )
1155
mtklein@google.com410e6e82013-09-13 19:52:27 +00001156DEF_BENCH( return new SawToothPathBench(FLAGS00); )
1157DEF_BENCH( return new SawToothPathBench(FLAGS01); )
reed@google.comd34658a2011-04-11 13:12:51 +00001158
mtklein@google.com410e6e82013-09-13 19:52:27 +00001159DEF_BENCH( return new LongCurvedPathBench(FLAGS00); )
1160DEF_BENCH( return new LongCurvedPathBench(FLAGS01); )
1161DEF_BENCH( return new LongLinePathBench(FLAGS00); )
1162DEF_BENCH( return new LongLinePathBench(FLAGS01); )
tomhudson@google.com6e8d3352011-06-22 17:16:35 +00001163
mtklein@google.com410e6e82013-09-13 19:52:27 +00001164DEF_BENCH( return new PathCreateBench(); )
1165DEF_BENCH( return new PathCopyBench(); )
1166DEF_BENCH( return new PathTransformBench(true); )
1167DEF_BENCH( return new PathTransformBench(false); )
1168DEF_BENCH( return new PathEqualityBench(); )
senorblanco@chromium.orge50f7362012-01-12 19:10:35 +00001169
mtklein@google.com410e6e82013-09-13 19:52:27 +00001170DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kAdd_AddType); )
1171DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kAddTrans_AddType); )
1172DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kAddMatrix_AddType); )
mtklein@google.com410e6e82013-09-13 19:52:27 +00001173DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kReverseAdd_AddType); )
1174DEF_BENCH( return new SkBench_AddPathTest(SkBench_AddPathTest::kReversePathTo_AddType); )
senorblanco@chromium.orge50f7362012-01-12 19:10:35 +00001175
mtklein@google.com410e6e82013-09-13 19:52:27 +00001176DEF_BENCH( return new CirclesBench(FLAGS00); )
1177DEF_BENCH( return new CirclesBench(FLAGS01); )
1178DEF_BENCH( return new ArbRoundRectBench(false); )
1179DEF_BENCH( return new ArbRoundRectBench(true); )
1180DEF_BENCH( return new ConservativelyContainsBench(ConservativelyContainsBench::kRect_Type); )
1181DEF_BENCH( return new ConservativelyContainsBench(ConservativelyContainsBench::kRoundRect_Type); )
1182DEF_BENCH( return new ConservativelyContainsBench(ConservativelyContainsBench::kOval_Type); )
mike@reedtribe.org8d551012013-04-14 02:40:50 +00001183
Mike Reed0d7dac82017-02-02 17:45:56 -08001184#include "SkPathOps.h"
1185#include "SkPathPriv.h"
Mike Reed8d3196b2017-02-03 11:34:13 -05001186DEF_BENCH( return new TightBoundsBench([](const SkPath& path){ return path.computeTightBounds();},
1187 "priv"); )
1188DEF_BENCH( return new TightBoundsBench([](const SkPath& path) {
1189 SkRect bounds; TightBounds(path, &bounds); return bounds;
1190 }, "pathops"); )
reedb6402032015-03-20 13:23:43 -07001191
Mike Klein3f376a52014-07-16 20:23:43 -04001192// These seem to be optimized away, which is troublesome for timing.
1193/*
mtklein@google.com410e6e82013-09-13 19:52:27 +00001194DEF_BENCH( return new ConicBench_Chop5() )
mtklein@google.com410e6e82013-09-13 19:52:27 +00001195DEF_BENCH( return new ConicBench_ComputeError() )
1196DEF_BENCH( return new ConicBench_asQuadTol() )
1197DEF_BENCH( return new ConicBench_quadPow2() )
Mike Klein3f376a52014-07-16 20:23:43 -04001198*/