| /* | |
| * Copyright 2013 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "bench/Benchmark.h" | |
| #include "include/core/SkBlurTypes.h" | |
| #include "include/core/SkCanvas.h" | |
| #include "include/core/SkPaint.h" | |
| #include "include/core/SkShader.h" | |
| #include "include/core/SkString.h" | |
| #include "src/core/SkBlurMask.h" | |
| #include "src/core/SkRandom.h" | |
| #define SMALL SkIntToScalar(2) | |
| #define REAL 1.5f | |
| static const SkScalar kMedium = SkIntToScalar(5); | |
| #define BIG SkIntToScalar(10) | |
| static const SkScalar kMedBig = SkIntToScalar(20); | |
| #define REALBIG 30.5f | |
| class BlurRectBench: public Benchmark { | |
| int fLoopCount; | |
| SkScalar fRadius; | |
| SkString fName; | |
| public: | |
| BlurRectBench(SkScalar rad) { | |
| fRadius = rad; | |
| if (fRadius > SkIntToScalar(25)) { | |
| fLoopCount = 100; | |
| } else if (fRadius > SkIntToScalar(5)) { | |
| fLoopCount = 1000; | |
| } else { | |
| fLoopCount = 10000; | |
| } | |
| } | |
| protected: | |
| const char* onGetName() override { | |
| return fName.c_str(); | |
| } | |
| SkScalar radius() const { | |
| return fRadius; | |
| } | |
| void setName(const SkString& name) { | |
| fName = name; | |
| } | |
| void onDraw(int loops, SkCanvas*) override { | |
| SkPaint paint; | |
| this->setupPaint(&paint); | |
| paint.setAntiAlias(true); | |
| SkScalar pad = fRadius*3/2 + SK_Scalar1; | |
| SkRect r = SkRect::MakeWH(2 * pad + SK_Scalar1, 2 * pad + SK_Scalar1); | |
| preBenchSetup(r); | |
| for (int i = 0; i < loops; i++) { | |
| this->makeBlurryRect(r); | |
| } | |
| } | |
| virtual void makeBlurryRect(const SkRect&) = 0; | |
| virtual void preBenchSetup(const SkRect&) {} | |
| private: | |
| using INHERITED = Benchmark; | |
| }; | |
| class BlurRectDirectBench: public BlurRectBench { | |
| public: | |
| BlurRectDirectBench(SkScalar rad) : INHERITED(rad) { | |
| SkString name; | |
| if (SkScalarFraction(rad) != 0) { | |
| name.printf("blurrect_direct_%.2f", rad); | |
| } else { | |
| name.printf("blurrect_direct_%d", SkScalarRoundToInt(rad)); | |
| } | |
| this->setName(name); | |
| } | |
| protected: | |
| void makeBlurryRect(const SkRect& r) override { | |
| SkMaskBuilder mask; | |
| if (!SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(this->radius()), | |
| &mask, r, kNormal_SkBlurStyle)) { | |
| return; | |
| } | |
| SkMaskBuilder::FreeImage(mask.image()); | |
| } | |
| private: | |
| using INHERITED = BlurRectBench; | |
| }; | |
| class BlurRectSeparableBench: public BlurRectBench { | |
| public: | |
| BlurRectSeparableBench(SkScalar rad) : INHERITED(rad) { } | |
| ~BlurRectSeparableBench() override { | |
| SkMaskBuilder::FreeImage(fSrcMask.image()); | |
| } | |
| protected: | |
| void preBenchSetup(const SkRect& r) override { | |
| SkMaskBuilder::FreeImage(fSrcMask.image()); | |
| r.roundOut(&fSrcMask.bounds()); | |
| fSrcMask.format() = SkMask::kA8_Format; | |
| fSrcMask.rowBytes() = fSrcMask.fBounds.width(); | |
| fSrcMask.image() = SkMaskBuilder::AllocImage(fSrcMask.computeTotalImageSize()); | |
| memset(fSrcMask.image(), 0xff, fSrcMask.computeTotalImageSize()); | |
| } | |
| SkMaskBuilder fSrcMask; | |
| private: | |
| using INHERITED = BlurRectBench; | |
| }; | |
| class BlurRectBoxFilterBench: public BlurRectSeparableBench { | |
| public: | |
| BlurRectBoxFilterBench(SkScalar rad) : INHERITED(rad) { | |
| SkString name; | |
| if (SkScalarFraction(rad) != 0) { | |
| name.printf("blurrect_boxfilter_%.2f", rad); | |
| } else { | |
| name.printf("blurrect_boxfilter_%d", SkScalarRoundToInt(rad)); | |
| } | |
| this->setName(name); | |
| } | |
| protected: | |
| void makeBlurryRect(const SkRect&) override { | |
| SkMaskBuilder mask; | |
| if (!SkBlurMask::BoxBlur(&mask, fSrcMask, SkBlurMask::ConvertRadiusToSigma(this->radius()), | |
| kNormal_SkBlurStyle)) { | |
| return; | |
| } | |
| SkMaskBuilder::FreeImage(mask.image()); | |
| } | |
| private: | |
| using INHERITED = BlurRectSeparableBench; | |
| }; | |
| class BlurRectGaussianBench: public BlurRectSeparableBench { | |
| public: | |
| BlurRectGaussianBench(SkScalar rad) : INHERITED(rad) { | |
| SkString name; | |
| if (SkScalarFraction(rad) != 0) { | |
| name.printf("blurrect_gaussian_%.2f", rad); | |
| } else { | |
| name.printf("blurrect_gaussian_%d", SkScalarRoundToInt(rad)); | |
| } | |
| this->setName(name); | |
| } | |
| protected: | |
| void makeBlurryRect(const SkRect&) override { | |
| SkMaskBuilder mask; | |
| if (!SkBlurMask::BlurGroundTruth(SkBlurMask::ConvertRadiusToSigma(this->radius()), | |
| &mask, fSrcMask, kNormal_SkBlurStyle)) { | |
| return; | |
| } | |
| SkMaskBuilder::FreeImage(mask.image()); | |
| } | |
| private: | |
| using INHERITED = BlurRectSeparableBench; | |
| }; | |
| DEF_BENCH(return new BlurRectBoxFilterBench(SMALL);) | |
| DEF_BENCH(return new BlurRectBoxFilterBench(BIG);) | |
| DEF_BENCH(return new BlurRectBoxFilterBench(REALBIG);) | |
| DEF_BENCH(return new BlurRectBoxFilterBench(REAL);) | |
| DEF_BENCH(return new BlurRectGaussianBench(SMALL);) | |
| DEF_BENCH(return new BlurRectGaussianBench(BIG);) | |
| DEF_BENCH(return new BlurRectGaussianBench(REALBIG);) | |
| DEF_BENCH(return new BlurRectGaussianBench(REAL);) | |
| DEF_BENCH(return new BlurRectDirectBench(SMALL);) | |
| DEF_BENCH(return new BlurRectDirectBench(BIG);) | |
| DEF_BENCH(return new BlurRectDirectBench(REALBIG);) | |
| DEF_BENCH(return new BlurRectDirectBench(REAL);) | |
| DEF_BENCH(return new BlurRectDirectBench(kMedium);) | |
| DEF_BENCH(return new BlurRectDirectBench(kMedBig);) | |
| DEF_BENCH(return new BlurRectBoxFilterBench(kMedium);) | |
| DEF_BENCH(return new BlurRectBoxFilterBench(kMedBig);) | |
| #if 0 | |
| // disable Gaussian benchmarks; the algorithm works well enough | |
| // and serves as a baseline for ground truth, but it's too slow | |
| // to use in production for non-trivial radii, so no real point | |
| // in having the bots benchmark it all the time. | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(1));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(2));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(3));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(4));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(5));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(6));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(7));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(8));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(9));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(10));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(11));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(12));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(13));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(14));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(15));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(16));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(17));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(18));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(19));) | |
| DEF_BENCH(return new BlurRectGaussianBench(SkIntToScalar(20));) | |
| #endif |