1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "bench/Benchmark.h" 9cb93a386Sopenharmony_ci#include "include/core/SkPath.h" 10cb93a386Sopenharmony_ci#include "include/core/SkShader.h" 11cb93a386Sopenharmony_ci#include "include/core/SkString.h" 12cb93a386Sopenharmony_ci#include "include/pathops/SkPathOps.h" 13cb93a386Sopenharmony_ci#include "include/private/SkTArray.h" 14cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ciclass PathOpsBench : public Benchmark { 17cb93a386Sopenharmony_ci SkString fName; 18cb93a386Sopenharmony_ci SkPath fPath1, fPath2; 19cb93a386Sopenharmony_ci SkPathOp fOp; 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cipublic: 22cb93a386Sopenharmony_ci PathOpsBench(const char suffix[], SkPathOp op) : fOp(op) { 23cb93a386Sopenharmony_ci fName.printf("pathops_%s", suffix); 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci fPath1.addOval({-10, -20, 10, 20}); 26cb93a386Sopenharmony_ci fPath2.addOval({-20, -10, 20, 10}); 27cb93a386Sopenharmony_ci } 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 30cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 31cb93a386Sopenharmony_ci } 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ciprotected: 34cb93a386Sopenharmony_ci const char* onGetName() override { 35cb93a386Sopenharmony_ci return fName.c_str(); 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas* canvas) override { 39cb93a386Sopenharmony_ci for (int i = 0; i < loops; i++) { 40cb93a386Sopenharmony_ci for (int j = 0; j < 1000; ++j) { 41cb93a386Sopenharmony_ci SkPath result; 42cb93a386Sopenharmony_ci Op(fPath1, fPath2, fOp, &result); 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ciprivate: 48cb93a386Sopenharmony_ci using INHERITED = Benchmark; 49cb93a386Sopenharmony_ci}; 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ciclass PathOpsSimplifyBench : public Benchmark { 52cb93a386Sopenharmony_ci SkString fName; 53cb93a386Sopenharmony_ci SkPath fPath; 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_cipublic: 56cb93a386Sopenharmony_ci PathOpsSimplifyBench(const char suffix[], const SkPath& path) : fPath(path) { 57cb93a386Sopenharmony_ci fName.printf("pathops_simplify_%s", suffix); 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 61cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 62cb93a386Sopenharmony_ci } 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ciprotected: 65cb93a386Sopenharmony_ci const char* onGetName() override { 66cb93a386Sopenharmony_ci return fName.c_str(); 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas* canvas) override { 70cb93a386Sopenharmony_ci for (int i = 0; i < loops; i++) { 71cb93a386Sopenharmony_ci for (int j = 0; j < 100; ++j) { 72cb93a386Sopenharmony_ci SkPath result; 73cb93a386Sopenharmony_ci Simplify(fPath, &result); 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ciprivate: 79cb93a386Sopenharmony_ci using INHERITED = Benchmark; 80cb93a386Sopenharmony_ci}; 81cb93a386Sopenharmony_ciDEF_BENCH( return new PathOpsBench("sect", kIntersect_SkPathOp); ) 82cb93a386Sopenharmony_ciDEF_BENCH( return new PathOpsBench("join", kUnion_SkPathOp); ) 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_cistatic SkPath makerects() { 85cb93a386Sopenharmony_ci SkRandom rand; 86cb93a386Sopenharmony_ci SkPath path; 87cb93a386Sopenharmony_ci SkScalar scale = 100; 88cb93a386Sopenharmony_ci for (int i = 0; i < 20; ++i) { 89cb93a386Sopenharmony_ci SkScalar x = rand.nextUScalar1() * scale; 90cb93a386Sopenharmony_ci SkScalar y = rand.nextUScalar1() * scale; 91cb93a386Sopenharmony_ci path.addRect({x, y, x + scale, y + scale}); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci return path; 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ciDEF_BENCH( return new PathOpsSimplifyBench("rects", makerects()); ) 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci#include "include/core/SkPathBuilder.h" 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_citemplate <size_t N> struct ArrayPath { 100cb93a386Sopenharmony_ci SkPoint fPts[N]; 101cb93a386Sopenharmony_ci uint8_t fVbs[N]; 102cb93a386Sopenharmony_ci int fPIndex = 0, fVIndex = 0; 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci void moveTo(float x, float y) { 105cb93a386Sopenharmony_ci fVbs[fVIndex++] = (uint8_t)SkPathVerb::kMove; 106cb93a386Sopenharmony_ci fPts[fPIndex++] = {x, y}; 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci void lineTo(float x, float y) { 109cb93a386Sopenharmony_ci fVbs[fVIndex++] = (uint8_t)SkPathVerb::kLine; 110cb93a386Sopenharmony_ci fPts[fPIndex++] = {x, y}; 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci void quadTo(float x, float y, float x1, float y1) { 113cb93a386Sopenharmony_ci fVbs[fVIndex++] = (uint8_t)SkPathVerb::kQuad; 114cb93a386Sopenharmony_ci fPts[fPIndex++] = {x, y}; 115cb93a386Sopenharmony_ci fPts[fPIndex++] = {x1, y1}; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci void cubicTo(float x, float y, float x1, float y1, float x2, float y2) { 118cb93a386Sopenharmony_ci fVbs[fVIndex++] = (uint8_t)SkPathVerb::kCubic; 119cb93a386Sopenharmony_ci fPts[fPIndex++] = {x, y}; 120cb93a386Sopenharmony_ci fPts[fPIndex++] = {x1, y1}; 121cb93a386Sopenharmony_ci fPts[fPIndex++] = {x2, y2}; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci void incReserve(int) {} 124cb93a386Sopenharmony_ci}; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_citemplate <typename T> void run_builder(T& b, bool useReserve, int N) { 127cb93a386Sopenharmony_ci if (useReserve) { 128cb93a386Sopenharmony_ci b.incReserve(N * 12); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci float x = 0, y = 0; 132cb93a386Sopenharmony_ci b.moveTo(x, y); 133cb93a386Sopenharmony_ci for (int i = 1; i < N; ++i) { 134cb93a386Sopenharmony_ci b.lineTo(x, y); 135cb93a386Sopenharmony_ci b.quadTo(x, y, x, y); 136cb93a386Sopenharmony_ci b.cubicTo(x, y, x, y, x, y); 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci} 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_cienum class MakeType { 141cb93a386Sopenharmony_ci kPath, 142cb93a386Sopenharmony_ci kSnapshot, 143cb93a386Sopenharmony_ci kDetach, 144cb93a386Sopenharmony_ci kArray, 145cb93a386Sopenharmony_ci}; 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ciclass PathBuilderBench : public Benchmark { 148cb93a386Sopenharmony_ci SkString fName; 149cb93a386Sopenharmony_ci MakeType fMakeType; 150cb93a386Sopenharmony_ci bool fUseReserve; 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci enum { N = 100 }; 153cb93a386Sopenharmony_ci ArrayPath<N*12> fArrays; 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_cipublic: 156cb93a386Sopenharmony_ci PathBuilderBench(MakeType mt, bool reserve) : fMakeType(mt), fUseReserve(reserve) { 157cb93a386Sopenharmony_ci const char* typenames[] = { "path", "snapshot", "detach", "arrays" }; 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci fName.printf("makepath_%s_%s", typenames[(int)mt], reserve ? "reserve" : "noreserve"); 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci bool isSuitableFor(Backend backend) override { 163cb93a386Sopenharmony_ci return backend == kNonRendering_Backend; 164cb93a386Sopenharmony_ci } 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ciprotected: 167cb93a386Sopenharmony_ci const char* onGetName() override { 168cb93a386Sopenharmony_ci return fName.c_str(); 169cb93a386Sopenharmony_ci } 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci void onDelayedSetup() override { 172cb93a386Sopenharmony_ci run_builder(fArrays, false, N); 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci SkPath build() { 176cb93a386Sopenharmony_ci switch (fMakeType) { 177cb93a386Sopenharmony_ci case MakeType::kSnapshot: 178cb93a386Sopenharmony_ci case MakeType::kDetach: { 179cb93a386Sopenharmony_ci SkPathBuilder b; 180cb93a386Sopenharmony_ci run_builder(b, fUseReserve, N); 181cb93a386Sopenharmony_ci return MakeType::kSnapshot == fMakeType ? b.snapshot() : b.detach(); 182cb93a386Sopenharmony_ci } 183cb93a386Sopenharmony_ci case MakeType::kPath: { 184cb93a386Sopenharmony_ci SkPath p; 185cb93a386Sopenharmony_ci run_builder(p, fUseReserve, N); 186cb93a386Sopenharmony_ci return p; 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci case MakeType::kArray: { 189cb93a386Sopenharmony_ci // ArrayPath<N*12> arrays; 190cb93a386Sopenharmony_ci // run_builder(arrays, false, N); 191cb93a386Sopenharmony_ci return SkPath::Make(fArrays.fPts, fArrays.fPIndex, 192cb93a386Sopenharmony_ci fArrays.fVbs, fArrays.fVIndex, 193cb93a386Sopenharmony_ci nullptr, 0, SkPathFillType::kWinding); 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci return SkPath(); 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci void onDraw(int loops, SkCanvas* canvas) override { 200cb93a386Sopenharmony_ci for (int i = 0; i < loops; i++) { 201cb93a386Sopenharmony_ci for (int j = 0; j < 100; ++j) { 202cb93a386Sopenharmony_ci SkPath result = this->build(); 203cb93a386Sopenharmony_ci // force bounds calc as part of the test 204cb93a386Sopenharmony_ci if (!result.getBounds().isFinite()) { 205cb93a386Sopenharmony_ci SkDebugf("should never get here!\n"); 206cb93a386Sopenharmony_ci return; 207cb93a386Sopenharmony_ci } 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ciprivate: 213cb93a386Sopenharmony_ci using INHERITED = Benchmark; 214cb93a386Sopenharmony_ci}; 215cb93a386Sopenharmony_ciDEF_BENCH( return new PathBuilderBench(MakeType::kPath, false); ) 216cb93a386Sopenharmony_ciDEF_BENCH( return new PathBuilderBench(MakeType::kSnapshot, false); ) 217cb93a386Sopenharmony_ciDEF_BENCH( return new PathBuilderBench(MakeType::kDetach, false); ) 218cb93a386Sopenharmony_ciDEF_BENCH( return new PathBuilderBench(MakeType::kPath, true); ) 219cb93a386Sopenharmony_ciDEF_BENCH( return new PathBuilderBench(MakeType::kSnapshot, true); ) 220cb93a386Sopenharmony_ciDEF_BENCH( return new PathBuilderBench(MakeType::kDetach, true); ) 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_ciDEF_BENCH( return new PathBuilderBench(MakeType::kArray, true); ) 223