1 /* 2 * Copyright 2013 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 "SkCanvas.h" 10 #include "SkPaint.h" 11 #include "SkRandom.h" 12 #include "SkShader.h" 13 #include "SkString.h" 14 #include "SkBlurMask.h" 15 16 #define SMALL SkIntToScalar(2) 17 #define REAL SkFloatToScalar(1.5f) 18 #define BIG SkIntToScalar(10) 19 #define REALBIG SkFloatToScalar(30.5f) 20 21 class BlurRectBench: public SkBenchmark { 22 int fLoopCount; 23 SkScalar fRadius; 24 SkString fName; 25 26 public: 27 BlurRectBench(void *param, SkScalar rad) : INHERITED(param) { 28 fRadius = rad; 29 30 if (fRadius > SkIntToScalar(25)) { 31 fLoopCount = 100; 32 } else if (fRadius > SkIntToScalar(5)) { 33 fLoopCount = 1000; 34 } else { 35 fLoopCount = 10000; 36 } 37 } 38 39 protected: 40 virtual const char* onGetName() { 41 return fName.c_str(); 42 } 43 44 SkScalar radius() const { 45 return fRadius; 46 } 47 48 void setName(const SkString& name) { 49 fName = name; 50 } 51 52 virtual void onDraw(SkCanvas*) { 53 SkPaint paint; 54 this->setupPaint(&paint); 55 56 paint.setAntiAlias(true); 57 58 SkScalar pad = fRadius*3/2 + SK_Scalar1; 59 SkRect r = SkRect::MakeWH(2 * pad + SK_Scalar1, 2 * pad + SK_Scalar1); 60 61 preBenchSetup(r); 62 63 for (int i = 0; i < SkBENCHLOOP(fLoopCount); i++) { 64 makeBlurryRect(r); 65 } 66 } 67 68 virtual void makeBlurryRect(const SkRect&) = 0; 69 virtual void preBenchSetup(const SkRect&) {} 70 private: 71 typedef SkBenchmark INHERITED; 72 }; 73 74 75 class BlurRectDirectBench: public BlurRectBench { 76 public: 77 BlurRectDirectBench(void *param, SkScalar rad) : INHERITED(param, rad) { 78 SkString name; 79 80 if (SkScalarFraction(rad) != 0) { 81 name.printf("blurrect_direct_%.2f", SkScalarToFloat(rad)); 82 } else { 83 name.printf("blurrect_direct_%d", SkScalarRoundToInt(rad)); 84 } 85 86 setName(name); 87 } 88 protected: 89 virtual void makeBlurryRect(const SkRect& r) SK_OVERRIDE { 90 SkMask mask; 91 SkBlurMask::BlurRect(&mask, r, this->radius(), SkBlurMask::kNormal_Style); 92 SkMask::FreeImage(mask.fImage); 93 } 94 private: 95 typedef BlurRectBench INHERITED; 96 }; 97 98 class BlurRectSeparableBench: public BlurRectBench { 99 100 public: 101 BlurRectSeparableBench(void *param, SkScalar rad) : INHERITED(param, rad) { 102 fSrcMask.fImage = NULL; 103 } 104 105 ~BlurRectSeparableBench() { 106 SkMask::FreeImage(fSrcMask.fImage); 107 } 108 109 protected: 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; 122 private: 123 typedef BlurRectBench INHERITED; 124 }; 125 126 class BlurRectBoxFilterBench: public BlurRectSeparableBench { 127 public: 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 138 protected: 139 140 virtual void makeBlurryRect(const SkRect&) SK_OVERRIDE { 141 SkMask mask; 142 mask.fImage = NULL; 143 SkBlurMask::Blur(&mask, fSrcMask, this->radius(), 144 SkBlurMask::kNormal_Style, 145 SkBlurMask::kHigh_Quality); 146 SkMask::FreeImage(mask.fImage); 147 } 148 private: 149 typedef BlurRectSeparableBench INHERITED; 150 }; 151 152 class BlurRectGaussianBench: public BlurRectSeparableBench { 153 public: 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 164 protected: 165 166 virtual void makeBlurryRect(const SkRect&) 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 } 173 private: 174 typedef BlurRectSeparableBench INHERITED; 175 }; 176 177 DEF_BENCH(return new BlurRectBoxFilterBench(p, SMALL);) 178 DEF_BENCH(return new BlurRectBoxFilterBench(p, BIG);) 179 DEF_BENCH(return new BlurRectBoxFilterBench(p, REALBIG);) 180 DEF_BENCH(return new BlurRectBoxFilterBench(p, REAL);) 181 DEF_BENCH(return new BlurRectGaussianBench(p, SMALL);) 182 DEF_BENCH(return new BlurRectGaussianBench(p, BIG);) 183 DEF_BENCH(return new BlurRectGaussianBench(p, REALBIG);) 184 DEF_BENCH(return new BlurRectGaussianBench(p, REAL);) 185 DEF_BENCH(return new BlurRectDirectBench(p, SMALL);) 186 DEF_BENCH(return new BlurRectDirectBench(p, BIG);) 187 DEF_BENCH(return new BlurRectDirectBench(p, REALBIG);) 188 DEF_BENCH(return new BlurRectDirectBench(p, REAL);) 189 190 DEF_BENCH(return new BlurRectDirectBench(p, SkIntToScalar(5));) 191 DEF_BENCH(return new BlurRectDirectBench(p, SkIntToScalar(20));) 192 193 DEF_BENCH(return new BlurRectBoxFilterBench(p, SkIntToScalar(5));) 194 DEF_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 202 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(1));) 203 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(2));) 204 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(3));) 205 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(4));) 206 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(5));) 207 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(6));) 208 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(7));) 209 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(8));) 210 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(9));) 211 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(10));) 212 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(11));) 213 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(12));) 214 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(13));) 215 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(14));) 216 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(15));) 217 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(16));) 218 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(17));) 219 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(18));) 220 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(19));) 221 DEF_BENCH(return new BlurRectGaussianBench(p, SkIntToScalar(20));) 222 #endif 223