| /* | |
| * Copyright 2011 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "Benchmark.h" | |
| #include "SkAAClip.h" | |
| #include "SkCanvas.h" | |
| #include "SkPath.h" | |
| #include "SkRandom.h" | |
| #include "SkRegion.h" | |
| #include "SkString.h" | |
| #include "SkClipOpPriv.h" | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // This bench tests out AA/BW clipping via canvas' clipPath and clipRect calls | |
| class AAClipBench : public Benchmark { | |
| SkString fName; | |
| SkPath fClipPath; | |
| SkRect fClipRect; | |
| SkRect fDrawRect; | |
| bool fDoPath; | |
| bool fDoAA; | |
| public: | |
| AAClipBench(bool doPath, bool doAA) | |
| : fDoPath(doPath) | |
| , fDoAA(doAA) { | |
| fName.printf("aaclip_%s_%s", | |
| doPath ? "path" : "rect", | |
| doAA ? "AA" : "BW"); | |
| fClipRect.set(10.5f, 10.5f, | |
| 50.5f, 50.5f); | |
| fClipPath.addRoundRect(fClipRect, SkIntToScalar(10), SkIntToScalar(10)); | |
| fDrawRect.set(SkIntToScalar(0), SkIntToScalar(0), | |
| SkIntToScalar(100), SkIntToScalar(100)); | |
| SkASSERT(fClipPath.isConvex()); | |
| } | |
| protected: | |
| virtual const char* onGetName() { return fName.c_str(); } | |
| virtual void onDraw(int loops, SkCanvas* canvas) { | |
| SkPaint paint; | |
| this->setupPaint(&paint); | |
| for (int i = 0; i < loops; ++i) { | |
| // jostle the clip regions each time to prevent caching | |
| fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0); | |
| fClipPath.reset(); | |
| fClipPath.addRoundRect(fClipRect, | |
| SkIntToScalar(5), SkIntToScalar(5)); | |
| SkASSERT(fClipPath.isConvex()); | |
| canvas->save(); | |
| #if 1 | |
| if (fDoPath) { | |
| canvas->clipPath(fClipPath, kReplace_SkClipOp, fDoAA); | |
| } else { | |
| canvas->clipRect(fClipRect, kReplace_SkClipOp, fDoAA); | |
| } | |
| canvas->drawRect(fDrawRect, paint); | |
| #else | |
| // this path tests out directly draw the clip primitive | |
| // use it to comparing just drawing the clip vs. drawing using | |
| // the clip | |
| if (fDoPath) { | |
| canvas->drawPath(fClipPath, paint); | |
| } else { | |
| canvas->drawRect(fClipRect, paint); | |
| } | |
| #endif | |
| canvas->restore(); | |
| } | |
| } | |
| private: | |
| typedef Benchmark INHERITED; | |
| }; | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // This bench tests out nested clip stacks. It is intended to simulate | |
| // how WebKit nests clips. | |
| class NestedAAClipBench : public Benchmark { | |
| SkString fName; | |
| bool fDoAA; | |
| SkRect fDrawRect; | |
| SkRandom fRandom; | |
| static const int kNestingDepth = 3; | |
| static const int kImageSize = 400; | |
| SkPoint fSizes[kNestingDepth+1]; | |
| public: | |
| NestedAAClipBench(bool doAA) : fDoAA(doAA) { | |
| fName.printf("nested_aaclip_%s", doAA ? "AA" : "BW"); | |
| fDrawRect = SkRect::MakeLTRB(0, 0, | |
| SkIntToScalar(kImageSize), | |
| SkIntToScalar(kImageSize)); | |
| fSizes[0].set(SkIntToScalar(kImageSize), SkIntToScalar(kImageSize)); | |
| for (int i = 1; i < kNestingDepth+1; ++i) { | |
| fSizes[i].set(fSizes[i-1].fX/2, fSizes[i-1].fY/2); | |
| } | |
| } | |
| protected: | |
| virtual const char* onGetName() { return fName.c_str(); } | |
| void recurse(SkCanvas* canvas, | |
| int depth, | |
| const SkPoint& offset) { | |
| canvas->save(); | |
| SkRect temp = SkRect::MakeLTRB(0, 0, | |
| fSizes[depth].fX, fSizes[depth].fY); | |
| temp.offset(offset); | |
| SkPath path; | |
| path.addRoundRect(temp, SkIntToScalar(3), SkIntToScalar(3)); | |
| SkASSERT(path.isConvex()); | |
| canvas->clipPath(path, | |
| 0 == depth ? kReplace_SkClipOp : kIntersect_SkClipOp, | |
| fDoAA); | |
| if (kNestingDepth == depth) { | |
| // we only draw the draw rect at the lowest nesting level | |
| SkPaint paint; | |
| paint.setColor(0xff000000 | fRandom.nextU()); | |
| canvas->drawRect(fDrawRect, paint); | |
| } else { | |
| SkPoint childOffset = offset; | |
| this->recurse(canvas, depth+1, childOffset); | |
| childOffset += fSizes[depth+1]; | |
| this->recurse(canvas, depth+1, childOffset); | |
| childOffset.fX = offset.fX + fSizes[depth+1].fX; | |
| childOffset.fY = offset.fY; | |
| this->recurse(canvas, depth+1, childOffset); | |
| childOffset.fX = offset.fX; | |
| childOffset.fY = offset.fY + fSizes[depth+1].fY; | |
| this->recurse(canvas, depth+1, childOffset); | |
| } | |
| canvas->restore(); | |
| } | |
| virtual void onDraw(int loops, SkCanvas* canvas) { | |
| for (int i = 0; i < loops; ++i) { | |
| SkPoint offset = SkPoint::Make(0, 0); | |
| this->recurse(canvas, 0, offset); | |
| } | |
| } | |
| private: | |
| typedef Benchmark INHERITED; | |
| }; | |
| //////////////////////////////////////////////////////////////////////////////// | |
| class AAClipBuilderBench : public Benchmark { | |
| SkString fName; | |
| SkPath fPath; | |
| SkRect fRect; | |
| SkRegion fRegion; | |
| bool fDoPath; | |
| bool fDoAA; | |
| public: | |
| AAClipBuilderBench(bool doPath, bool doAA) { | |
| fDoPath = doPath; | |
| fDoAA = doAA; | |
| fName.printf("aaclip_build_%s_%s", doPath ? "path" : "rect", | |
| doAA ? "AA" : "BW"); | |
| fRegion.setRect(0, 0, 640, 480); | |
| fRect.set(fRegion.getBounds()); | |
| fRect.inset(SK_Scalar1/4, SK_Scalar1/4); | |
| fPath.addRoundRect(fRect, SkIntToScalar(20), SkIntToScalar(20)); | |
| } | |
| protected: | |
| virtual const char* onGetName() { return fName.c_str(); } | |
| virtual void onDraw(int loops, SkCanvas*) { | |
| SkPaint paint; | |
| this->setupPaint(&paint); | |
| for (int i = 0; i < loops; ++i) { | |
| SkAAClip clip; | |
| if (fDoPath) { | |
| clip.setPath(fPath, &fRegion, fDoAA); | |
| } else { | |
| clip.setRect(fRect, fDoAA); | |
| } | |
| } | |
| } | |
| private: | |
| typedef Benchmark INHERITED; | |
| }; | |
| //////////////////////////////////////////////////////////////////////////////// | |
| class AAClipRegionBench : public Benchmark { | |
| public: | |
| AAClipRegionBench() { | |
| SkPath path; | |
| // test conversion of a complex clip to a aaclip | |
| path.addCircle(0, 0, SkIntToScalar(200)); | |
| path.addCircle(0, 0, SkIntToScalar(180)); | |
| // evenodd means we've constructed basically a stroked circle | |
| path.setFillType(SkPath::kEvenOdd_FillType); | |
| SkIRect bounds; | |
| path.getBounds().roundOut(&bounds); | |
| fRegion.setPath(path, SkRegion(bounds)); | |
| } | |
| protected: | |
| virtual const char* onGetName() { return "aaclip_setregion"; } | |
| virtual void onDraw(int loops, SkCanvas*) { | |
| for (int i = 0; i < loops; ++i) { | |
| SkAAClip clip; | |
| clip.setRegion(fRegion); | |
| } | |
| } | |
| private: | |
| SkRegion fRegion; | |
| typedef Benchmark INHERITED; | |
| }; | |
| //////////////////////////////////////////////////////////////////////////////// | |
| DEF_BENCH(return new AAClipBuilderBench(false, false);) | |
| DEF_BENCH(return new AAClipBuilderBench(false, true);) | |
| DEF_BENCH(return new AAClipBuilderBench(true, false);) | |
| DEF_BENCH(return new AAClipBuilderBench(true, true);) | |
| DEF_BENCH(return new AAClipRegionBench();) | |
| DEF_BENCH(return new AAClipBench(false, false);) | |
| DEF_BENCH(return new AAClipBench(false, true);) | |
| DEF_BENCH(return new AAClipBench(true, false);) | |
| DEF_BENCH(return new AAClipBench(true, true);) | |
| DEF_BENCH(return new NestedAAClipBench(false);) | |
| DEF_BENCH(return new NestedAAClipBench(true);) |