| /* | |
| * Copyright 2013 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "bench/Benchmark.h" | |
| #include "include/core/SkCanvas.h" | |
| #include "include/core/SkPaint.h" | |
| #include "include/core/SkPath.h" | |
| #include "include/core/SkPathBuilder.h" | |
| #include "include/core/SkShader.h" | |
| #include "include/core/SkString.h" | |
| #include "src/core/SkRandom.h" | |
| #include <array> | |
| enum Flags { | |
| kBig_Flag = 1 << 0, | |
| kAA_Flag = 1 << 1 | |
| }; | |
| #define FLAGS00 Flags(0) | |
| #define FLAGS01 Flags(kBig_Flag) | |
| #define FLAGS10 Flags(kAA_Flag) | |
| #define FLAGS11 Flags(kBig_Flag | kAA_Flag) | |
| static constexpr auto points = std::to_array<int>({ | |
| 10, 10, 15, 5, 20, 20, | |
| 30, 5, 25, 20, 15, 12, | |
| 21, 21, 30, 30, 12, 4, | |
| 32, 28, 20, 18, 12, 10 | |
| }); | |
| static const int kMaxPathSize = 10; | |
| class HairlinePathBench : public Benchmark { | |
| public: | |
| HairlinePathBench(Flags flags) : fFlags(flags) { | |
| fPaint.setStyle(SkPaint::kStroke_Style); | |
| fPaint.setStrokeWidth(SkIntToScalar(0)); | |
| } | |
| virtual void appendName(SkString*) = 0; | |
| virtual SkPath makePath() = 0; | |
| protected: | |
| const char* onGetName() override { | |
| fName.printf("path_hairline_%s_%s_", | |
| fFlags & kBig_Flag ? "big" : "small", | |
| fFlags & kAA_Flag ? "AA" : "noAA"); | |
| this->appendName(&fName); | |
| return fName.c_str(); | |
| } | |
| void onDraw(int loops, SkCanvas* canvas) override { | |
| SkPaint paint(fPaint); | |
| this->setupPaint(&paint); | |
| paint.setAntiAlias(fFlags & kAA_Flag ? true : false); | |
| SkPath path = this->makePath(); | |
| if (fFlags & kBig_Flag) { | |
| path = path.makeTransform(SkMatrix::Scale(3, 3)); | |
| } | |
| for (int i = 0; i < loops; i++) { | |
| for (int j = 0; j < 100; ++j) { | |
| canvas->drawPath(path, paint); | |
| } | |
| } | |
| } | |
| private: | |
| SkPaint fPaint; | |
| SkString fName; | |
| Flags fFlags; | |
| using INHERITED = Benchmark; | |
| }; | |
| class LinePathBench : public HairlinePathBench { | |
| public: | |
| LinePathBench(Flags flags) : INHERITED(flags) {} | |
| void appendName(SkString* name) override { | |
| name->append("line"); | |
| } | |
| SkPath makePath() override { | |
| SkRandom rand; | |
| SkPathBuilder builder; | |
| int size = std::size(points); | |
| int hSize = size / 2; | |
| for (int i = 0; i < kMaxPathSize; ++i) { | |
| int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); | |
| int yTrans = 0; | |
| if (i > kMaxPathSize/2 - 1) { | |
| yTrans = 40; | |
| } | |
| int base1 = 2 * rand.nextULessThan(hSize); | |
| int base2 = 2 * rand.nextULessThan(hSize); | |
| int base3 = 2 * rand.nextULessThan(hSize); | |
| builder.moveTo(SkIntToScalar(points[base1] + xTrans), | |
| SkIntToScalar(points[base1+1] + yTrans)); | |
| builder.lineTo(SkIntToScalar(points[base2] + xTrans), | |
| SkIntToScalar(points[base2+1] + yTrans)); | |
| builder.lineTo(SkIntToScalar(points[base3] + xTrans), | |
| SkIntToScalar(points[base3+1] + yTrans)); | |
| } | |
| return builder.detach(); | |
| } | |
| private: | |
| using INHERITED = HairlinePathBench; | |
| }; | |
| class QuadPathBench : public HairlinePathBench { | |
| public: | |
| QuadPathBench(Flags flags) : INHERITED(flags) {} | |
| void appendName(SkString* name) override { | |
| name->append("quad"); | |
| } | |
| SkPath makePath() override { | |
| SkRandom rand; | |
| SkPathBuilder builder; | |
| int size = std::size(points); | |
| int hSize = size / 2; | |
| for (int i = 0; i < kMaxPathSize; ++i) { | |
| int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); | |
| int yTrans = 0; | |
| if (i > kMaxPathSize/2 - 1) { | |
| yTrans = 40; | |
| } | |
| int base1 = 2 * rand.nextULessThan(hSize); | |
| int base2 = 2 * rand.nextULessThan(hSize); | |
| int base3 = 2 * rand.nextULessThan(hSize); | |
| builder.moveTo(SkIntToScalar(points[base1] + xTrans), | |
| SkIntToScalar(points[base1+1] + yTrans)); | |
| builder.quadTo(SkIntToScalar(points[base2] + xTrans), | |
| SkIntToScalar(points[base2+1] + yTrans), | |
| SkIntToScalar(points[base3] + xTrans), | |
| SkIntToScalar(points[base3+1] + yTrans)); | |
| } | |
| return builder.detach(); | |
| } | |
| private: | |
| using INHERITED = HairlinePathBench; | |
| }; | |
| class ConicPathBench : public HairlinePathBench { | |
| public: | |
| ConicPathBench(Flags flags) : INHERITED(flags) {} | |
| void appendName(SkString* name) override { | |
| name->append("conic"); | |
| } | |
| SkPath makePath() override { | |
| SkRandom rand; | |
| SkRandom randWeight; | |
| SkPathBuilder builder; | |
| int size = std::size(points); | |
| int hSize = size / 2; | |
| for (int i = 0; i < kMaxPathSize; ++i) { | |
| int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); | |
| int yTrans = 0; | |
| if (i > kMaxPathSize/2 - 1) { | |
| yTrans = 40; | |
| } | |
| int base1 = 2 * rand.nextULessThan(hSize); | |
| int base2 = 2 * rand.nextULessThan(hSize); | |
| int base3 = 2 * rand.nextULessThan(hSize); | |
| float weight = randWeight.nextRangeF(0.0f, 2.0f); | |
| builder.moveTo(SkIntToScalar(points[base1] + xTrans), | |
| SkIntToScalar(points[base1+1] + yTrans)); | |
| builder.conicTo(SkIntToScalar(points[base2] + xTrans), | |
| SkIntToScalar(points[base2+1] + yTrans), | |
| SkIntToScalar(points[base3] + xTrans), | |
| SkIntToScalar(points[base3+1] + yTrans), | |
| weight); | |
| } | |
| return builder.detach(); | |
| } | |
| private: | |
| using INHERITED = HairlinePathBench; | |
| }; | |
| class CubicPathBench : public HairlinePathBench { | |
| public: | |
| CubicPathBench(Flags flags) : INHERITED(flags) {} | |
| void appendName(SkString* name) override { | |
| name->append("cubic"); | |
| } | |
| SkPath makePath() override { | |
| SkRandom rand; | |
| SkPathBuilder builder; | |
| int size = std::size(points); | |
| int hSize = size / 2; | |
| for (int i = 0; i < kMaxPathSize; ++i) { | |
| int xTrans = 10 + 40 * (i%(kMaxPathSize/2)); | |
| int yTrans = 0; | |
| if (i > kMaxPathSize/2 - 1) { | |
| yTrans = 40; | |
| } | |
| int base1 = 2 * rand.nextULessThan(hSize); | |
| int base2 = 2 * rand.nextULessThan(hSize); | |
| int base3 = 2 * rand.nextULessThan(hSize); | |
| int base4 = 2 * rand.nextULessThan(hSize); | |
| builder.moveTo(SkIntToScalar(points[base1] + xTrans), | |
| SkIntToScalar(points[base1+1] + yTrans)); | |
| builder.cubicTo(SkIntToScalar(points[base2] + xTrans), | |
| SkIntToScalar(points[base2+1] + yTrans), | |
| SkIntToScalar(points[base3] + xTrans), | |
| SkIntToScalar(points[base3+1] + yTrans), | |
| SkIntToScalar(points[base4] + xTrans), | |
| SkIntToScalar(points[base4+1] + yTrans)); | |
| } | |
| return builder.detach(); | |
| } | |
| private: | |
| using INHERITED = HairlinePathBench; | |
| }; | |
| // FLAG00 - no AA, small | |
| // FLAG01 - no AA, small | |
| // FLAG10 - AA, big | |
| // FLAG11 - AA, big | |
| DEF_BENCH( return new LinePathBench(FLAGS00); ) | |
| DEF_BENCH( return new LinePathBench(FLAGS01); ) | |
| DEF_BENCH( return new LinePathBench(FLAGS10); ) | |
| DEF_BENCH( return new LinePathBench(FLAGS11); ) | |
| DEF_BENCH( return new QuadPathBench(FLAGS00); ) | |
| DEF_BENCH( return new QuadPathBench(FLAGS01); ) | |
| DEF_BENCH( return new QuadPathBench(FLAGS10); ) | |
| DEF_BENCH( return new QuadPathBench(FLAGS11); ) | |
| // Don't have default path renderer for conics yet on GPU, so must use AA | |
| // DEF_BENCH( return new ConicPathBench(FLAGS00); ) | |
| // DEF_BENCH( return new ConicPathBench(FLAGS01); ) | |
| DEF_BENCH( return new ConicPathBench(FLAGS10); ) | |
| DEF_BENCH( return new ConicPathBench(FLAGS11); ) | |
| DEF_BENCH( return new CubicPathBench(FLAGS00); ) | |
| DEF_BENCH( return new CubicPathBench(FLAGS01); ) | |
| DEF_BENCH( return new CubicPathBench(FLAGS10); ) | |
| DEF_BENCH( return new CubicPathBench(FLAGS11); ) |