1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #include "bench/Benchmark.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRegion.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkAAClip.h" 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////// 17*c8dee2aaSAndroid Build Coastguard Worker // This bench tests out AA/BW clipping via canvas' clipPath and clipRect calls 18*c8dee2aaSAndroid Build Coastguard Worker class AAClipBench : public Benchmark { 19*c8dee2aaSAndroid Build Coastguard Worker SkString fName; 20*c8dee2aaSAndroid Build Coastguard Worker SkPath fClipPath; 21*c8dee2aaSAndroid Build Coastguard Worker SkRect fClipRect; 22*c8dee2aaSAndroid Build Coastguard Worker SkRect fDrawRect; 23*c8dee2aaSAndroid Build Coastguard Worker bool fDoPath; 24*c8dee2aaSAndroid Build Coastguard Worker bool fDoAA; 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker public: AAClipBench(bool doPath,bool doAA)27*c8dee2aaSAndroid Build Coastguard Worker AAClipBench(bool doPath, bool doAA) 28*c8dee2aaSAndroid Build Coastguard Worker : fDoPath(doPath) 29*c8dee2aaSAndroid Build Coastguard Worker , fDoAA(doAA) { 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Worker fName.printf("aaclip_%s_%s", 32*c8dee2aaSAndroid Build Coastguard Worker doPath ? "path" : "rect", 33*c8dee2aaSAndroid Build Coastguard Worker doAA ? "AA" : "BW"); 34*c8dee2aaSAndroid Build Coastguard Worker 35*c8dee2aaSAndroid Build Coastguard Worker fClipRect.setLTRB(10.5f, 10.5f, 50.5f, 50.5f); 36*c8dee2aaSAndroid Build Coastguard Worker fClipPath.addRoundRect(fClipRect, SkIntToScalar(10), SkIntToScalar(10)); 37*c8dee2aaSAndroid Build Coastguard Worker fDrawRect.setWH(100, 100); 38*c8dee2aaSAndroid Build Coastguard Worker 39*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fClipPath.isConvex()); 40*c8dee2aaSAndroid Build Coastguard Worker } 41*c8dee2aaSAndroid Build Coastguard Worker 42*c8dee2aaSAndroid Build Coastguard Worker protected: onGetName()43*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { return fName.c_str(); } onDraw(int loops,SkCanvas * canvas)44*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* canvas) override { 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint; 47*c8dee2aaSAndroid Build Coastguard Worker this->setupPaint(&paint); 48*c8dee2aaSAndroid Build Coastguard Worker 49*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; ++i) { 50*c8dee2aaSAndroid Build Coastguard Worker // jostle the clip regions each time to prevent caching 51*c8dee2aaSAndroid Build Coastguard Worker fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0); 52*c8dee2aaSAndroid Build Coastguard Worker fClipPath.reset(); 53*c8dee2aaSAndroid Build Coastguard Worker fClipPath.addRoundRect(fClipRect, 54*c8dee2aaSAndroid Build Coastguard Worker SkIntToScalar(5), SkIntToScalar(5)); 55*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fClipPath.isConvex()); 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker canvas->save(); 58*c8dee2aaSAndroid Build Coastguard Worker #if 1 59*c8dee2aaSAndroid Build Coastguard Worker if (fDoPath) { 60*c8dee2aaSAndroid Build Coastguard Worker canvas->clipPath(fClipPath, SkClipOp::kIntersect, fDoAA); 61*c8dee2aaSAndroid Build Coastguard Worker } else { 62*c8dee2aaSAndroid Build Coastguard Worker canvas->clipRect(fClipRect, SkClipOp::kIntersect, fDoAA); 63*c8dee2aaSAndroid Build Coastguard Worker } 64*c8dee2aaSAndroid Build Coastguard Worker 65*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(fDrawRect, paint); 66*c8dee2aaSAndroid Build Coastguard Worker #else 67*c8dee2aaSAndroid Build Coastguard Worker // this path tests out directly draw the clip primitive 68*c8dee2aaSAndroid Build Coastguard Worker // use it to comparing just drawing the clip vs. drawing using 69*c8dee2aaSAndroid Build Coastguard Worker // the clip 70*c8dee2aaSAndroid Build Coastguard Worker if (fDoPath) { 71*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(fClipPath, paint); 72*c8dee2aaSAndroid Build Coastguard Worker } else { 73*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(fClipRect, paint); 74*c8dee2aaSAndroid Build Coastguard Worker } 75*c8dee2aaSAndroid Build Coastguard Worker #endif 76*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 77*c8dee2aaSAndroid Build Coastguard Worker } 78*c8dee2aaSAndroid Build Coastguard Worker } 79*c8dee2aaSAndroid Build Coastguard Worker private: 80*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 81*c8dee2aaSAndroid Build Coastguard Worker }; 82*c8dee2aaSAndroid Build Coastguard Worker 83*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////// 84*c8dee2aaSAndroid Build Coastguard Worker // This bench tests out nested clip stacks. It is intended to simulate 85*c8dee2aaSAndroid Build Coastguard Worker // how WebKit nests clips. 86*c8dee2aaSAndroid Build Coastguard Worker class NestedAAClipBench : public Benchmark { 87*c8dee2aaSAndroid Build Coastguard Worker SkString fName; 88*c8dee2aaSAndroid Build Coastguard Worker bool fDoAA; 89*c8dee2aaSAndroid Build Coastguard Worker SkRect fDrawRect; 90*c8dee2aaSAndroid Build Coastguard Worker SkRandom fRandom; 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker static const int kNestingDepth = 3; 93*c8dee2aaSAndroid Build Coastguard Worker static const int kImageSize = 400; 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Worker SkPoint fSizes[kNestingDepth+1]; 96*c8dee2aaSAndroid Build Coastguard Worker 97*c8dee2aaSAndroid Build Coastguard Worker public: NestedAAClipBench(bool doAA)98*c8dee2aaSAndroid Build Coastguard Worker NestedAAClipBench(bool doAA) : fDoAA(doAA) { 99*c8dee2aaSAndroid Build Coastguard Worker fName.printf("nested_aaclip_%s", doAA ? "AA" : "BW"); 100*c8dee2aaSAndroid Build Coastguard Worker 101*c8dee2aaSAndroid Build Coastguard Worker fDrawRect = SkRect::MakeLTRB(0, 0, 102*c8dee2aaSAndroid Build Coastguard Worker SkIntToScalar(kImageSize), 103*c8dee2aaSAndroid Build Coastguard Worker SkIntToScalar(kImageSize)); 104*c8dee2aaSAndroid Build Coastguard Worker 105*c8dee2aaSAndroid Build Coastguard Worker fSizes[0].set(SkIntToScalar(kImageSize), SkIntToScalar(kImageSize)); 106*c8dee2aaSAndroid Build Coastguard Worker 107*c8dee2aaSAndroid Build Coastguard Worker for (int i = 1; i < kNestingDepth+1; ++i) { 108*c8dee2aaSAndroid Build Coastguard Worker fSizes[i].set(fSizes[i-1].fX/2, fSizes[i-1].fY/2); 109*c8dee2aaSAndroid Build Coastguard Worker } 110*c8dee2aaSAndroid Build Coastguard Worker } 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker protected: onGetName()113*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { return fName.c_str(); } 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker recurse(SkCanvas * canvas,int depth,const SkPoint & offset)116*c8dee2aaSAndroid Build Coastguard Worker void recurse(SkCanvas* canvas, 117*c8dee2aaSAndroid Build Coastguard Worker int depth, 118*c8dee2aaSAndroid Build Coastguard Worker const SkPoint& offset) { 119*c8dee2aaSAndroid Build Coastguard Worker 120*c8dee2aaSAndroid Build Coastguard Worker canvas->save(); 121*c8dee2aaSAndroid Build Coastguard Worker 122*c8dee2aaSAndroid Build Coastguard Worker SkRect temp = SkRect::MakeLTRB(0, 0, 123*c8dee2aaSAndroid Build Coastguard Worker fSizes[depth].fX, fSizes[depth].fY); 124*c8dee2aaSAndroid Build Coastguard Worker temp.offset(offset); 125*c8dee2aaSAndroid Build Coastguard Worker 126*c8dee2aaSAndroid Build Coastguard Worker SkPath path; 127*c8dee2aaSAndroid Build Coastguard Worker path.addRoundRect(temp, SkIntToScalar(3), SkIntToScalar(3)); 128*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(path.isConvex()); 129*c8dee2aaSAndroid Build Coastguard Worker 130*c8dee2aaSAndroid Build Coastguard Worker canvas->clipPath(path, SkClipOp::kIntersect, fDoAA); 131*c8dee2aaSAndroid Build Coastguard Worker 132*c8dee2aaSAndroid Build Coastguard Worker if (kNestingDepth == depth) { 133*c8dee2aaSAndroid Build Coastguard Worker // we only draw the draw rect at the lowest nesting level 134*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint; 135*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(0xff000000 | fRandom.nextU()); 136*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(fDrawRect, paint); 137*c8dee2aaSAndroid Build Coastguard Worker } else { 138*c8dee2aaSAndroid Build Coastguard Worker SkPoint childOffset = offset; 139*c8dee2aaSAndroid Build Coastguard Worker this->recurse(canvas, depth+1, childOffset); 140*c8dee2aaSAndroid Build Coastguard Worker 141*c8dee2aaSAndroid Build Coastguard Worker childOffset += fSizes[depth+1]; 142*c8dee2aaSAndroid Build Coastguard Worker this->recurse(canvas, depth+1, childOffset); 143*c8dee2aaSAndroid Build Coastguard Worker 144*c8dee2aaSAndroid Build Coastguard Worker childOffset.fX = offset.fX + fSizes[depth+1].fX; 145*c8dee2aaSAndroid Build Coastguard Worker childOffset.fY = offset.fY; 146*c8dee2aaSAndroid Build Coastguard Worker this->recurse(canvas, depth+1, childOffset); 147*c8dee2aaSAndroid Build Coastguard Worker 148*c8dee2aaSAndroid Build Coastguard Worker childOffset.fX = offset.fX; 149*c8dee2aaSAndroid Build Coastguard Worker childOffset.fY = offset.fY + fSizes[depth+1].fY; 150*c8dee2aaSAndroid Build Coastguard Worker this->recurse(canvas, depth+1, childOffset); 151*c8dee2aaSAndroid Build Coastguard Worker } 152*c8dee2aaSAndroid Build Coastguard Worker 153*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 154*c8dee2aaSAndroid Build Coastguard Worker } 155*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas * canvas)156*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* canvas) override { 157*c8dee2aaSAndroid Build Coastguard Worker 158*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; ++i) { 159*c8dee2aaSAndroid Build Coastguard Worker SkPoint offset = SkPoint::Make(0, 0); 160*c8dee2aaSAndroid Build Coastguard Worker this->recurse(canvas, 0, offset); 161*c8dee2aaSAndroid Build Coastguard Worker } 162*c8dee2aaSAndroid Build Coastguard Worker } 163*c8dee2aaSAndroid Build Coastguard Worker 164*c8dee2aaSAndroid Build Coastguard Worker private: 165*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 166*c8dee2aaSAndroid Build Coastguard Worker }; 167*c8dee2aaSAndroid Build Coastguard Worker 168*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////// 169*c8dee2aaSAndroid Build Coastguard Worker class AAClipBuilderBench : public Benchmark { 170*c8dee2aaSAndroid Build Coastguard Worker SkString fName; 171*c8dee2aaSAndroid Build Coastguard Worker SkPath fPath; 172*c8dee2aaSAndroid Build Coastguard Worker SkRect fRect; 173*c8dee2aaSAndroid Build Coastguard Worker SkIRect fBounds; 174*c8dee2aaSAndroid Build Coastguard Worker bool fDoPath; 175*c8dee2aaSAndroid Build Coastguard Worker bool fDoAA; 176*c8dee2aaSAndroid Build Coastguard Worker 177*c8dee2aaSAndroid Build Coastguard Worker public: AAClipBuilderBench(bool doPath,bool doAA)178*c8dee2aaSAndroid Build Coastguard Worker AAClipBuilderBench(bool doPath, bool doAA) { 179*c8dee2aaSAndroid Build Coastguard Worker fDoPath = doPath; 180*c8dee2aaSAndroid Build Coastguard Worker fDoAA = doAA; 181*c8dee2aaSAndroid Build Coastguard Worker 182*c8dee2aaSAndroid Build Coastguard Worker fName.printf("aaclip_build_%s_%s", doPath ? "path" : "rect", 183*c8dee2aaSAndroid Build Coastguard Worker doAA ? "AA" : "BW"); 184*c8dee2aaSAndroid Build Coastguard Worker fBounds = {0, 0, 640, 480}; 185*c8dee2aaSAndroid Build Coastguard Worker fRect.set(fBounds); 186*c8dee2aaSAndroid Build Coastguard Worker fRect.inset(SK_Scalar1/4, SK_Scalar1/4); 187*c8dee2aaSAndroid Build Coastguard Worker fPath.addRoundRect(fRect, SkIntToScalar(20), SkIntToScalar(20)); 188*c8dee2aaSAndroid Build Coastguard Worker } 189*c8dee2aaSAndroid Build Coastguard Worker 190*c8dee2aaSAndroid Build Coastguard Worker protected: onGetName()191*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { return fName.c_str(); } onDraw(int loops,SkCanvas *)192*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas*) override { 193*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint; 194*c8dee2aaSAndroid Build Coastguard Worker this->setupPaint(&paint); 195*c8dee2aaSAndroid Build Coastguard Worker 196*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; ++i) { 197*c8dee2aaSAndroid Build Coastguard Worker SkAAClip clip; 198*c8dee2aaSAndroid Build Coastguard Worker if (fDoPath) { 199*c8dee2aaSAndroid Build Coastguard Worker clip.setPath(fPath, fBounds, fDoAA); 200*c8dee2aaSAndroid Build Coastguard Worker } else { 201*c8dee2aaSAndroid Build Coastguard Worker if (fDoAA) { 202*c8dee2aaSAndroid Build Coastguard Worker clip.setPath(SkPath::Rect(fRect), fBounds, fDoAA); 203*c8dee2aaSAndroid Build Coastguard Worker } else { 204*c8dee2aaSAndroid Build Coastguard Worker clip.setRect(fBounds); 205*c8dee2aaSAndroid Build Coastguard Worker } 206*c8dee2aaSAndroid Build Coastguard Worker } 207*c8dee2aaSAndroid Build Coastguard Worker } 208*c8dee2aaSAndroid Build Coastguard Worker } 209*c8dee2aaSAndroid Build Coastguard Worker private: 210*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 211*c8dee2aaSAndroid Build Coastguard Worker }; 212*c8dee2aaSAndroid Build Coastguard Worker 213*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////// 214*c8dee2aaSAndroid Build Coastguard Worker class AAClipRegionBench : public Benchmark { 215*c8dee2aaSAndroid Build Coastguard Worker public: AAClipRegionBench()216*c8dee2aaSAndroid Build Coastguard Worker AAClipRegionBench() { 217*c8dee2aaSAndroid Build Coastguard Worker SkPath path; 218*c8dee2aaSAndroid Build Coastguard Worker // test conversion of a complex clip to a aaclip 219*c8dee2aaSAndroid Build Coastguard Worker path.addCircle(0, 0, SkIntToScalar(200)); 220*c8dee2aaSAndroid Build Coastguard Worker path.addCircle(0, 0, SkIntToScalar(180)); 221*c8dee2aaSAndroid Build Coastguard Worker // evenodd means we've constructed basically a stroked circle 222*c8dee2aaSAndroid Build Coastguard Worker path.setFillType(SkPathFillType::kEvenOdd); 223*c8dee2aaSAndroid Build Coastguard Worker 224*c8dee2aaSAndroid Build Coastguard Worker SkIRect bounds; 225*c8dee2aaSAndroid Build Coastguard Worker path.getBounds().roundOut(&bounds); 226*c8dee2aaSAndroid Build Coastguard Worker fRegion.setPath(path, SkRegion(bounds)); 227*c8dee2aaSAndroid Build Coastguard Worker } 228*c8dee2aaSAndroid Build Coastguard Worker 229*c8dee2aaSAndroid Build Coastguard Worker protected: onGetName()230*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { return "aaclip_setregion"; } onDraw(int loops,SkCanvas *)231*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas*) override { 232*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; ++i) { 233*c8dee2aaSAndroid Build Coastguard Worker SkAAClip clip; 234*c8dee2aaSAndroid Build Coastguard Worker clip.setRegion(fRegion); 235*c8dee2aaSAndroid Build Coastguard Worker } 236*c8dee2aaSAndroid Build Coastguard Worker } 237*c8dee2aaSAndroid Build Coastguard Worker 238*c8dee2aaSAndroid Build Coastguard Worker private: 239*c8dee2aaSAndroid Build Coastguard Worker SkRegion fRegion; 240*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 241*c8dee2aaSAndroid Build Coastguard Worker }; 242*c8dee2aaSAndroid Build Coastguard Worker 243*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////// 244*c8dee2aaSAndroid Build Coastguard Worker 245*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBuilderBench(false, false);) 246*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBuilderBench(false, true);) 247*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBuilderBench(true, false);) 248*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBuilderBench(true, true);) 249*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipRegionBench();) 250*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBench(false, false);) 251*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBench(false, true);) 252*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBench(true, false);) 253*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new AAClipBench(true, true);) 254*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new NestedAAClipBench(false);) 255*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new NestedAAClipBench(true);) 256