1 /* 2 * Copyright 2014 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/SkRRect.h" 10 #include "include/core/SkRect.h" 11 #include "src/base/SkRandom.h" 12 #include "src/core/SkGeometry.h" 13 #include "src/core/SkPathPriv.h" 14 15 class GeometryBench : public Benchmark { 16 public: GeometryBench(const char suffix[])17 GeometryBench(const char suffix[]) : fVolatileInt(0) { 18 fName.printf("geo_%s", suffix); 19 } 20 onGetName()21 const char* onGetName() override { 22 return fName.c_str(); 23 } 24 isSuitableFor(Backend backend)25 bool isSuitableFor(Backend backend) override { 26 return kNonRendering_Backend == backend; 27 } 28 29 protected: 30 volatile int fVolatileInt; 31 32 /** 33 * Subclasses can call this to try to defeat the optimizer (with some result of their 34 * inner loop), since it will fool the compiler into assuming that "n" is actually 35 * needed somewhere, and since this method is not const, the member fields cannot 36 * be assumed to be const before and after the call. 37 */ virtualCallToFoilOptimizers(int n)38 virtual void virtualCallToFoilOptimizers(int n) { fVolatileInt += n; } 39 40 private: 41 SkString fName; 42 }; 43 44 class GeoRectBench : public GeometryBench { 45 public: GeoRectBench(const char suffix[])46 GeoRectBench(const char suffix[]) : GeometryBench(suffix) {} 47 48 protected: 49 SkRect fRects[2048]; 50 onDelayedSetup()51 void onDelayedSetup() override { 52 const SkScalar min = -100; 53 const SkScalar max = 100; 54 SkRandom rand; 55 for (size_t i = 0; i < std::size(fRects); ++i) { 56 SkScalar x = rand.nextRangeScalar(min, max); 57 SkScalar y = rand.nextRangeScalar(min, max); 58 SkScalar w = rand.nextRangeScalar(min, max); 59 SkScalar h = rand.nextRangeScalar(min, max); 60 fRects[i].setXYWH(x, y, w, h); 61 } 62 } 63 }; 64 65 class GeoRectBench_intersect : public GeoRectBench { 66 public: GeoRectBench_intersect()67 GeoRectBench_intersect() : GeoRectBench("rect_intersect") {} 68 69 protected: onDraw(int loops,SkCanvas * canvas)70 void onDraw(int loops, SkCanvas* canvas) override { 71 for (int outer = 0; outer < loops; ++outer) { 72 int count = 0; 73 for (size_t i = 0; i < std::size(fRects); ++i) { 74 SkRect r = fRects[0]; 75 count += r.intersect(fRects[i]); 76 } 77 this->virtualCallToFoilOptimizers(count); 78 } 79 } 80 }; 81 82 class GeoRectBench_intersect_rect : public GeoRectBench { 83 public: GeoRectBench_intersect_rect()84 GeoRectBench_intersect_rect() : GeoRectBench("rect_intersect_rect") {} 85 86 protected: onDraw(int loops,SkCanvas * canvas)87 void onDraw(int loops, SkCanvas* canvas) override { 88 for (int outer = 0; outer < loops; ++outer) { 89 int count = 0; 90 SkRect r; 91 for (size_t i = 0; i < std::size(fRects); ++i) { 92 count += r.intersect(fRects[0], fRects[i]); 93 } 94 this->virtualCallToFoilOptimizers(count); 95 } 96 } 97 }; 98 99 class GeoRectBench_Intersects : public GeoRectBench { 100 public: GeoRectBench_Intersects()101 GeoRectBench_Intersects() : GeoRectBench("rect_Intersects") {} 102 103 protected: onDraw(int loops,SkCanvas * canvas)104 void onDraw(int loops, SkCanvas* canvas) override { 105 for (int outer = 0; outer < loops; ++outer) { 106 int count = 0; 107 for (size_t i = 0; i < std::size(fRects); ++i) { 108 count += SkRect::Intersects(fRects[0], fRects[i]); 109 } 110 this->virtualCallToFoilOptimizers(count); 111 } 112 } 113 }; 114 115 class GeoRectBench_sort : public GeoRectBench { 116 public: GeoRectBench_sort()117 GeoRectBench_sort() : GeoRectBench("rect_sort") {} 118 119 protected: onDraw(int loops,SkCanvas * canvas)120 void onDraw(int loops, SkCanvas* canvas) override { 121 for (int outer = 0; outer < loops; ++outer) { 122 for (size_t i = 0; i < std::size(fRects); ++i) { 123 fRects[i].sort(); 124 } 125 } 126 } 127 }; 128 129 DEF_BENCH( return new GeoRectBench_intersect; ) 130 DEF_BENCH( return new GeoRectBench_intersect_rect; ) 131 DEF_BENCH( return new GeoRectBench_Intersects; ) 132 133 DEF_BENCH( return new GeoRectBench_sort; ) 134 135 /////////////////////////////////////////////////////////////////////////////////////////////////// 136 137 class QuadBenchBase : public GeometryBench { 138 protected: 139 SkPoint fPts[4]; 140 public: QuadBenchBase(const char name[])141 QuadBenchBase(const char name[]) : GeometryBench(name) { 142 SkRandom rand; 143 for (int i = 0; i < 4; ++i) { 144 fPts[i].set(rand.nextUScalar1(), rand.nextUScalar1()); 145 } 146 } 147 }; 148 149 class EvalQuadAt0 : public QuadBenchBase { 150 public: EvalQuadAt0()151 EvalQuadAt0() : QuadBenchBase("evalquadat0") {} 152 protected: onDraw(int loops,SkCanvas * canvas)153 void onDraw(int loops, SkCanvas* canvas) override { 154 SkPoint result; 155 for (int outer = 0; outer < loops; ++outer) { 156 SkEvalQuadAt(fPts, 0.5f, &result); 157 SkEvalQuadAt(fPts, 0.5f, &result); 158 SkEvalQuadAt(fPts, 0.5f, &result); 159 SkEvalQuadAt(fPts, 0.5f, &result); 160 } 161 } 162 }; 163 DEF_BENCH( return new EvalQuadAt0; ) 164 165 class EvalQuadAt1 : public QuadBenchBase { 166 public: EvalQuadAt1()167 EvalQuadAt1() : QuadBenchBase("evalquadat1") {} 168 protected: onDraw(int loops,SkCanvas * canvas)169 void onDraw(int loops, SkCanvas* canvas) override { 170 SkPoint result; 171 for (int outer = 0; outer < loops; ++outer) { 172 result = SkEvalQuadAt(fPts, 0.5f); 173 result = SkEvalQuadAt(fPts, 0.5f); 174 result = SkEvalQuadAt(fPts, 0.5f); 175 result = SkEvalQuadAt(fPts, 0.5f); 176 } 177 } 178 }; 179 DEF_BENCH( return new EvalQuadAt1; ) 180 181 //////// 182 183 class EvalQuadTangentAt0 : public QuadBenchBase { 184 public: EvalQuadTangentAt0()185 EvalQuadTangentAt0() : QuadBenchBase("evalquadtangentat0") {} 186 protected: onDraw(int loops,SkCanvas * canvas)187 void onDraw(int loops, SkCanvas* canvas) override { 188 SkPoint result; 189 for (int outer = 0; outer < loops; ++outer) { 190 SkEvalQuadAt(fPts, 0.5f, nullptr, &result); 191 SkEvalQuadAt(fPts, 0.5f, nullptr, &result); 192 SkEvalQuadAt(fPts, 0.5f, nullptr, &result); 193 SkEvalQuadAt(fPts, 0.5f, nullptr, &result); 194 } 195 } 196 }; 197 DEF_BENCH( return new EvalQuadTangentAt0; ) 198 199 class EvalQuadTangentAt1 : public QuadBenchBase { 200 public: EvalQuadTangentAt1()201 EvalQuadTangentAt1() : QuadBenchBase("evalquadtangentat1") {} 202 protected: onDraw(int loops,SkCanvas * canvas)203 void onDraw(int loops, SkCanvas* canvas) override { 204 SkPoint result; 205 for (int outer = 0; outer < loops; ++outer) { 206 result = SkEvalQuadTangentAt(fPts, 0.5f); 207 result = SkEvalQuadTangentAt(fPts, 0.5f); 208 result = SkEvalQuadTangentAt(fPts, 0.5f); 209 result = SkEvalQuadTangentAt(fPts, 0.5f); 210 } 211 } 212 }; 213 DEF_BENCH( return new EvalQuadTangentAt1; ) 214 215 //////// 216 217 class ChopQuadAt : public QuadBenchBase { 218 public: ChopQuadAt()219 ChopQuadAt() : QuadBenchBase("chopquadat") {} 220 protected: onDraw(int loops,SkCanvas * canvas)221 void onDraw(int loops, SkCanvas* canvas) override { 222 SkPoint dst[5]; 223 for (int outer = 0; outer < loops; ++outer) { 224 SkChopQuadAt(fPts, dst, 0.5f); 225 SkChopQuadAt(fPts, dst, 0.5f); 226 SkChopQuadAt(fPts, dst, 0.5f); 227 SkChopQuadAt(fPts, dst, 0.5f); 228 } 229 } 230 }; 231 DEF_BENCH( return new ChopQuadAt; ) 232 233 class ChopCubicAt : public QuadBenchBase { 234 public: ChopCubicAt()235 ChopCubicAt() : QuadBenchBase("chopcubicat0") {} 236 protected: onDraw(int loops,SkCanvas * canvas)237 void onDraw(int loops, SkCanvas* canvas) override { 238 SkPoint dst[7]; 239 for (int outer = 0; outer < loops; ++outer) { 240 SkChopCubicAt(fPts, dst, 0.5f); 241 SkChopCubicAt(fPts, dst, 0.5f); 242 SkChopCubicAt(fPts, dst, 0.5f); 243 SkChopCubicAt(fPts, dst, 0.5f); 244 } 245 } 246 }; 247 DEF_BENCH( return new ChopCubicAt; ) 248 249 #include "include/core/SkPath.h" 250 251 class ConvexityBench : public Benchmark { 252 SkPath fPath; 253 254 public: ConvexityBench(const char suffix[])255 ConvexityBench(const char suffix[]) { 256 fName.printf("convexity_%s", suffix); 257 } 258 onGetName()259 const char* onGetName() override { 260 return fName.c_str(); 261 } 262 isSuitableFor(Backend backend)263 bool isSuitableFor(Backend backend) override { 264 return kNonRendering_Backend == backend; 265 } 266 267 virtual void preparePath(SkPath*) = 0; 268 269 protected: onPreDraw(SkCanvas *)270 void onPreDraw(SkCanvas*) override { 271 this->preparePath(&fPath); 272 } 273 onDraw(int loops,SkCanvas * canvas)274 void onDraw(int loops, SkCanvas* canvas) override { 275 for (int i = 0; i < loops; ++i) { 276 SkPathPriv::ForceComputeConvexity(fPath); 277 } 278 } 279 280 private: 281 SkString fName; 282 }; 283 284 class RRectConvexityBench : public ConvexityBench { 285 public: RRectConvexityBench()286 RRectConvexityBench() : ConvexityBench("rrect") {} 287 preparePath(SkPath * path)288 void preparePath(SkPath* path) override { 289 SkRRect rr; 290 rr.setRectXY({0, 0, 100, 100}, 20, 30); 291 path->addRRect(rr); 292 } 293 }; 294 DEF_BENCH( return new RRectConvexityBench; ) 295 296