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