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