BlurRectBench.cpp revision a99a92cebaa46cf792cf86eaad1a4c3f9d6162f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2013 Google Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkBenchmark.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkCanvas.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkPaint.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkRandom.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "SkShader.h"
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "SkString.h"
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "SkBlurMask.h"
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#define SMALL   SkIntToScalar(2)
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#define REAL    SkFloatToScalar(1.5f)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BIG     SkIntToScalar(10)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define REALBIG SkFloatToScalar(30.5f)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BlurRectBench: public SkBenchmark {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int         fLoopCount;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkScalar    fRadius;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkString    fName;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BlurRectBench(void *param, SkScalar rad) : INHERITED(param) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fRadius = rad;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (fRadius > SkIntToScalar(25)) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fLoopCount = 100;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (fRadius > SkIntToScalar(5)) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fLoopCount = 1000;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fLoopCount = 10000;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)protected:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual const char* onGetName() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return fName.c_str();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkScalar radius() const {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return fRadius;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void setName(const SkString& name) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fName = name;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void onDraw(SkCanvas* canvas) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkPaint paint;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this->setupPaint(&paint);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        paint.setAntiAlias(true);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkScalar pad = fRadius*3/2 + SK_Scalar1;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkRect r = SkRect::MakeWH(2 * pad + SK_Scalar1, 2 * pad + SK_Scalar1);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        preBenchSetup(r);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int i = 0; i < SkBENCHLOOP(fLoopCount); i++) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            makeBlurryRect(r);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void makeBlurryRect(const SkRect&) = 0;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void preBenchSetup(const SkRect&) {}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef SkBenchmark INHERITED;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BlurRectDirectBench: public BlurRectBench {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BlurRectDirectBench(void *param, SkScalar rad) : INHERITED(param, rad) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkString name;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (SkScalarFraction(rad) != 0) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            name.printf("blurrect_direct_%.2f", SkScalarToFloat(rad));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            name.printf("blurrect_direct_%d", SkScalarRoundToInt(rad));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        setName(name);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)protected:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void makeBlurryRect(const SkRect& r) SK_OVERRIDE {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkMask mask;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkBlurMask::BlurRect(&mask, r, this->radius(), SkBlurMask::kNormal_Style);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkMask::FreeImage(mask.fImage);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef BlurRectBench INHERITED;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BlurRectSeparableBench: public BlurRectBench {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100public:
101    BlurRectSeparableBench(void *param, SkScalar rad) : INHERITED(param, rad) {
102        fSrcMask.fImage = NULL;
103    }
104
105    ~BlurRectSeparableBench() {
106        SkMask::FreeImage(fSrcMask.fImage);
107    }
108
109protected:
110    virtual void preBenchSetup(const SkRect& r) SK_OVERRIDE {
111        SkMask::FreeImage(fSrcMask.fImage);
112
113        r.roundOut(&fSrcMask.fBounds);
114        fSrcMask.fFormat = SkMask::kA8_Format;
115        fSrcMask.fRowBytes = fSrcMask.fBounds.width();
116        fSrcMask.fImage = SkMask::AllocImage(fSrcMask.computeTotalImageSize());
117
118        memset(fSrcMask.fImage, 0xff, fSrcMask.computeTotalImageSize());
119    }
120
121    SkMask fSrcMask;
122private:
123    typedef BlurRectBench INHERITED;
124};
125
126class BlurRectBoxFilterBench: public BlurRectSeparableBench {
127public:
128    BlurRectBoxFilterBench(void *param, SkScalar rad) : INHERITED(param, rad) {
129        SkString name;
130        if (SkScalarFraction(rad) != 0) {
131            name.printf("blurrect_boxfilter_%.2f", SkScalarToFloat(rad));
132        } else {
133            name.printf("blurrect_boxfilter_%d", SkScalarRoundToInt(rad));
134        }
135        setName(name);
136    }
137
138protected:
139
140    virtual void makeBlurryRect(const SkRect& r) SK_OVERRIDE {
141        SkMask mask;
142        mask.fImage = NULL;
143        SkBlurMask::BlurSeparable(&mask, fSrcMask, this->radius(),
144                                  SkBlurMask::kNormal_Style,
145                                  SkBlurMask::kHigh_Quality);
146        SkMask::FreeImage(mask.fImage);
147    }
148private:
149    typedef BlurRectSeparableBench INHERITED;
150};
151
152class BlurRectGaussianBench: public BlurRectSeparableBench {
153public:
154    BlurRectGaussianBench(void *param, SkScalar rad) : INHERITED(param, rad) {
155        SkString name;
156        if (SkScalarFraction(rad) != 0) {
157            name.printf("blurrect_gaussian_%.2f", SkScalarToFloat(rad));
158        } else {
159            name.printf("blurrect_gaussian_%d", SkScalarRoundToInt(rad));
160        }
161        setName(name);
162    }
163
164protected:
165
166    virtual void makeBlurryRect(const SkRect& r) SK_OVERRIDE {
167        SkMask mask;
168        mask.fImage = NULL;
169        SkBlurMask::BlurGroundTruth(&mask, fSrcMask, this->radius(),
170                                    SkBlurMask::kNormal_Style);
171        SkMask::FreeImage(mask.fImage);
172    }
173private:
174    typedef BlurRectSeparableBench INHERITED;
175};
176
177DEF_BENCH(return new BlurRectBoxFilterBench(p, SMALL);)
178DEF_BENCH(return new BlurRectBoxFilterBench(p, BIG);)
179DEF_BENCH(return new BlurRectBoxFilterBench(p, REALBIG);)
180DEF_BENCH(return new BlurRectBoxFilterBench(p, REAL);)
181DEF_BENCH(return new BlurRectGaussianBench(p, SMALL);)
182DEF_BENCH(return new BlurRectGaussianBench(p, BIG);)
183DEF_BENCH(return new BlurRectGaussianBench(p, REALBIG);)
184DEF_BENCH(return new BlurRectGaussianBench(p, REAL);)
185DEF_BENCH(return new BlurRectDirectBench(p, SMALL);)
186DEF_BENCH(return new BlurRectDirectBench(p, BIG);)
187DEF_BENCH(return new BlurRectDirectBench(p, REALBIG);)
188DEF_BENCH(return new BlurRectDirectBench(p, REAL);)
189
190DEF_BENCH(return new BlurRectDirectBench(p, SkIntToScalar(5));)
191DEF_BENCH(return new BlurRectDirectBench(p, SkIntToScalar(20));)
192
193DEF_BENCH(return new BlurRectBoxFilterBench(p, SkIntToScalar(5));)
194DEF_BENCH(return new BlurRectBoxFilterBench(p, SkIntToScalar(20));)
195
196#if 0
197// disable Gaussian benchmarks; the algorithm works well enough
198// and serves as a baseline for ground truth, but it's too slow
199// to use in production for non-trivial radii, so no real point
200// in having the bots benchmark it all the time.
201
202DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(1));)
203DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(2));)
204DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(3));)
205DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(4));)
206DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(5));)
207DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(6));)
208DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(7));)
209DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(8));)
210DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(9));)
211DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(10));)
212DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(11));)
213DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(12));)
214DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(13));)
215DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(14));)
216DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(15));)
217DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(16));)
218DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(17));)
219DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(18));)
220DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(19));)
221DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(20));)
222#endif
223