1 /* 2 * Copyright 2011 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 "SkBenchmark.h" 9 #include "SkAAClip.h" 10 #include "SkPath.h" 11 #include "SkRegion.h" 12 #include "SkString.h" 13 #include "SkCanvas.h" 14 #include "SkRandom.h" 15 16 //////////////////////////////////////////////////////////////////////////////// 17 // This bench tests out AA/BW clipping via canvas' clipPath and clipRect calls 18 class AAClipBench : public SkBenchmark { 19 SkString fName; 20 SkPath fClipPath; 21 SkRect fClipRect; 22 SkRect fDrawRect; 23 bool fDoPath; 24 bool fDoAA; 25 26 enum { 27 N = SkBENCHLOOP(200), 28 }; 29 30 public: 31 AAClipBench(void* param, bool doPath, bool doAA) 32 : INHERITED(param) 33 , fDoPath(doPath) 34 , fDoAA(doAA) { 35 36 fName.printf("aaclip_%s_%s", 37 doPath ? "path" : "rect", 38 doAA ? "AA" : "BW"); 39 40 fClipRect.set(SkFloatToScalar(10.5f), SkFloatToScalar(10.5f), 41 SkFloatToScalar(50.5f), SkFloatToScalar(50.5f)); 42 fClipPath.addRoundRect(fClipRect, SkIntToScalar(10), SkIntToScalar(10)); 43 fDrawRect.set(SkIntToScalar(0), SkIntToScalar(0), 44 SkIntToScalar(100), SkIntToScalar(100)); 45 46 SkASSERT(fClipPath.isConvex()); 47 } 48 49 protected: 50 virtual const char* onGetName() { return fName.c_str(); } 51 virtual void onDraw(SkCanvas* canvas) { 52 53 SkPaint paint; 54 this->setupPaint(&paint); 55 56 for (int i = 0; i < N; ++i) { 57 // jostle the clip regions each time to prevent caching 58 fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0); 59 fClipPath.reset(); 60 fClipPath.addRoundRect(fClipRect, 61 SkIntToScalar(5), SkIntToScalar(5)); 62 SkASSERT(fClipPath.isConvex()); 63 64 canvas->save(); 65 #if 1 66 if (fDoPath) { 67 canvas->clipPath(fClipPath, SkRegion::kReplace_Op, fDoAA); 68 } else { 69 canvas->clipRect(fClipRect, SkRegion::kReplace_Op, fDoAA); 70 } 71 72 canvas->drawRect(fDrawRect, paint); 73 #else 74 // this path tests out directly draw the clip primitive 75 // use it to comparing just drawing the clip vs. drawing using 76 // the clip 77 if (fDoPath) { 78 canvas->drawPath(fClipPath, paint); 79 } else { 80 canvas->drawRect(fClipRect, paint); 81 } 82 #endif 83 canvas->restore(); 84 } 85 } 86 private: 87 typedef SkBenchmark INHERITED; 88 }; 89 90 //////////////////////////////////////////////////////////////////////////////// 91 // This bench tests out nested clip stacks. It is intended to simulate 92 // how WebKit nests clips. 93 class NestedAAClipBench : public SkBenchmark { 94 SkString fName; 95 bool fDoAA; 96 SkRect fDrawRect; 97 SkRandom fRandom; 98 99 static const int kNumDraws = SkBENCHLOOP(2); 100 static const int kNestingDepth = 3; 101 static const int kImageSize = 400; 102 103 SkPoint fSizes[kNestingDepth+1]; 104 105 public: 106 NestedAAClipBench(void* param, bool doAA) 107 : INHERITED(param) 108 , fDoAA(doAA) { 109 110 fName.printf("nested_aaclip_%s", doAA ? "AA" : "BW"); 111 112 fDrawRect = SkRect::MakeLTRB(0, 0, 113 SkIntToScalar(kImageSize), 114 SkIntToScalar(kImageSize)); 115 116 fSizes[0].set(SkIntToScalar(kImageSize), SkIntToScalar(kImageSize)); 117 118 for (int i = 1; i < kNestingDepth+1; ++i) { 119 fSizes[i].set(fSizes[i-1].fX/2, fSizes[i-1].fY/2); 120 } 121 } 122 123 protected: 124 virtual const char* onGetName() { return fName.c_str(); } 125 126 127 void recurse(SkCanvas* canvas, 128 int depth, 129 const SkPoint& offset) { 130 131 canvas->save(); 132 133 SkRect temp = SkRect::MakeLTRB(0, 0, 134 fSizes[depth].fX, fSizes[depth].fY); 135 temp.offset(offset); 136 137 SkPath path; 138 path.addRoundRect(temp, SkIntToScalar(3), SkIntToScalar(3)); 139 SkASSERT(path.isConvex()); 140 141 canvas->clipPath(path, 142 0 == depth ? SkRegion::kReplace_Op : 143 SkRegion::kIntersect_Op, 144 fDoAA); 145 146 if (kNestingDepth == depth) { 147 // we only draw the draw rect at the lowest nesting level 148 SkPaint paint; 149 paint.setColor(0xff000000 | fRandom.nextU()); 150 canvas->drawRect(fDrawRect, paint); 151 } else { 152 SkPoint childOffset = offset; 153 this->recurse(canvas, depth+1, childOffset); 154 155 childOffset += fSizes[depth+1]; 156 this->recurse(canvas, depth+1, childOffset); 157 158 childOffset.fX = offset.fX + fSizes[depth+1].fX; 159 childOffset.fY = offset.fY; 160 this->recurse(canvas, depth+1, childOffset); 161 162 childOffset.fX = offset.fX; 163 childOffset.fY = offset.fY + fSizes[depth+1].fY; 164 this->recurse(canvas, depth+1, childOffset); 165 } 166 167 canvas->restore(); 168 } 169 170 virtual void onDraw(SkCanvas* canvas) { 171 172 for (int i = 0; i < kNumDraws; ++i) { 173 SkPoint offset = SkPoint::Make(0, 0); 174 this->recurse(canvas, 0, offset); 175 } 176 } 177 178 private: 179 typedef SkBenchmark INHERITED; 180 }; 181 182 //////////////////////////////////////////////////////////////////////////////// 183 class AAClipBuilderBench : public SkBenchmark { 184 SkString fName; 185 SkPath fPath; 186 SkRect fRect; 187 SkRegion fRegion; 188 bool fDoPath; 189 bool fDoAA; 190 191 enum { 192 N = SkBENCHLOOP(200), 193 }; 194 195 public: 196 AAClipBuilderBench(void* param, bool doPath, bool doAA) : INHERITED(param) { 197 fDoPath = doPath; 198 fDoAA = doAA; 199 200 fName.printf("aaclip_build_%s_%s", doPath ? "path" : "rect", 201 doAA ? "AA" : "BW"); 202 203 fRegion.setRect(0, 0, 640, 480); 204 fRect.set(fRegion.getBounds()); 205 fRect.inset(SK_Scalar1/4, SK_Scalar1/4); 206 fPath.addRoundRect(fRect, SkIntToScalar(20), SkIntToScalar(20)); 207 } 208 209 protected: 210 virtual const char* onGetName() { return fName.c_str(); } 211 virtual void onDraw(SkCanvas* canvas) { 212 SkPaint paint; 213 this->setupPaint(&paint); 214 215 for (int i = 0; i < N; ++i) { 216 SkAAClip clip; 217 if (fDoPath) { 218 clip.setPath(fPath, &fRegion, fDoAA); 219 } else { 220 clip.setRect(fRect, fDoAA); 221 } 222 } 223 } 224 private: 225 typedef SkBenchmark INHERITED; 226 }; 227 228 //////////////////////////////////////////////////////////////////////////////// 229 class AAClipRegionBench : public SkBenchmark { 230 public: 231 AAClipRegionBench(void* param) : INHERITED(param) { 232 SkPath path; 233 // test conversion of a complex clip to a aaclip 234 path.addCircle(0, 0, SkIntToScalar(200)); 235 path.addCircle(0, 0, SkIntToScalar(180)); 236 // evenodd means we've constructed basically a stroked circle 237 path.setFillType(SkPath::kEvenOdd_FillType); 238 239 SkIRect bounds; 240 path.getBounds().roundOut(&bounds); 241 fRegion.setPath(path, SkRegion(bounds)); 242 } 243 244 protected: 245 virtual const char* onGetName() { return "aaclip_setregion"; } 246 virtual void onDraw(SkCanvas* canvas) { 247 for (int i = 0; i < N; ++i) { 248 SkAAClip clip; 249 clip.setRegion(fRegion); 250 } 251 } 252 253 private: 254 enum { 255 N = SkBENCHLOOP(400), 256 }; 257 SkRegion fRegion; 258 typedef SkBenchmark INHERITED; 259 }; 260 261 //////////////////////////////////////////////////////////////////////////////// 262 263 static SkBenchmark* Fact0(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, false, false)); } 264 static SkBenchmark* Fact1(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, false, true)); } 265 static SkBenchmark* Fact2(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, true, false)); } 266 static SkBenchmark* Fact3(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, true, true)); } 267 268 static BenchRegistry gReg0(Fact0); 269 static BenchRegistry gReg1(Fact1); 270 static BenchRegistry gReg2(Fact2); 271 static BenchRegistry gReg3(Fact3); 272 273 static SkBenchmark* Fact01(void* p) { return SkNEW_ARGS(AAClipRegionBench, (p)); } 274 static BenchRegistry gReg01(Fact01); 275 276 static SkBenchmark* Fact000(void* p) { return SkNEW_ARGS(AAClipBench, (p, false, false)); } 277 static SkBenchmark* Fact001(void* p) { return SkNEW_ARGS(AAClipBench, (p, false, true)); } 278 static SkBenchmark* Fact002(void* p) { return SkNEW_ARGS(AAClipBench, (p, true, false)); } 279 static SkBenchmark* Fact003(void* p) { return SkNEW_ARGS(AAClipBench, (p, true, true)); } 280 281 static BenchRegistry gReg000(Fact000); 282 static BenchRegistry gReg001(Fact001); 283 static BenchRegistry gReg002(Fact002); 284 static BenchRegistry gReg003(Fact003); 285 286 static SkBenchmark* Fact004(void* p) { return SkNEW_ARGS(NestedAAClipBench, (p, false)); } 287 static SkBenchmark* Fact005(void* p) { return SkNEW_ARGS(NestedAAClipBench, (p, true)); } 288 289 static BenchRegistry gReg004(Fact004); 290 static BenchRegistry gReg005(Fact005); 291