Modify the blur bench to add tests for high-quality blurs, and large non-integer blurs.  Change the Coarse flag (which just turns on separable blurs) to an #ifdef, since separable is no longer just Coarse.  (This #ifdef will hopefully be shortlived, once Chrome has switched).

The separable blur algorithm gives +45% on SampleBlur, +84% on SampleBigBlur, +31% on TheVerge, +35 to +85% on blurbench in HQ (depending on size), +8 to +35% in low quality.  (All of these on 32bit MacPro).

Review URL: https://codereview.appspot.com/6851117

git-svn-id: http://skia.googlecode.com/svn/trunk@6601 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/BlurBench.cpp b/bench/BlurBench.cpp
index cf95610..ab77d2b 100644
--- a/bench/BlurBench.cpp
+++ b/bench/BlurBench.cpp
@@ -16,6 +16,7 @@
 #define SMALL   SkIntToScalar(2)
 #define REAL    SkFloatToScalar(1.5f)
 #define BIG     SkIntToScalar(10)
+#define REALBIG SkFloatToScalar(100.5f)
 
 static const char* gStyleName[] = {
     "normal",
@@ -27,17 +28,20 @@
 class BlurBench : public SkBenchmark {
     SkScalar    fRadius;
     SkBlurMaskFilter::BlurStyle fStyle;
+    uint32_t                    fFlags;
     SkString    fName;
 
 public:
-    BlurBench(void* param, SkScalar rad, SkBlurMaskFilter::BlurStyle bs) : INHERITED(param) {
+    BlurBench(void* param, SkScalar rad, SkBlurMaskFilter::BlurStyle bs, uint32_t flags = 0) : INHERITED(param) {
         fRadius = rad;
         fStyle = bs;
+        fFlags = flags;
         const char* name = rad > 0 ? gStyleName[bs] : "none";
+        const char* quality = flags & SkBlurMaskFilter::kHighQuality_BlurFlag ? "high_quality" : "low_quality";
         if (SkScalarFraction(rad) != 0) {
-            fName.printf("blur_%.2f_%s", SkScalarToFloat(rad), name);
+            fName.printf("blur_%.2f_%s_%s", SkScalarToFloat(rad), name, quality);
         } else {
-            fName.printf("blur_%d_%s", SkScalarRound(rad), name);
+            fName.printf("blur_%d_%s_%s", SkScalarRound(rad), name, quality);
         }
     }
 
@@ -59,7 +63,7 @@
             r.offset(fRadius, fRadius);
 
             if (fRadius > 0) {
-                SkMaskFilter* mf = SkBlurMaskFilter::Create(fRadius, fStyle, 0);
+                SkMaskFilter* mf = SkBlurMaskFilter::Create(fRadius, fStyle, fFlags);
                 paint.setMaskFilter(mf)->unref();
             }
             canvas->drawOval(r, paint);
@@ -80,10 +84,23 @@
 DEF_BENCH(return new BlurBench(p, BIG, SkBlurMaskFilter::kOuter_BlurStyle);)
 DEF_BENCH(return new BlurBench(p, BIG, SkBlurMaskFilter::kInner_BlurStyle);)
 
+DEF_BENCH(return new BlurBench(p, REALBIG, SkBlurMaskFilter::kNormal_BlurStyle);)
+DEF_BENCH(return new BlurBench(p, REALBIG, SkBlurMaskFilter::kSolid_BlurStyle);)
+DEF_BENCH(return new BlurBench(p, REALBIG, SkBlurMaskFilter::kOuter_BlurStyle);)
+DEF_BENCH(return new BlurBench(p, REALBIG, SkBlurMaskFilter::kInner_BlurStyle);)
+
 DEF_BENCH(return new BlurBench(p, REAL, SkBlurMaskFilter::kNormal_BlurStyle);)
 DEF_BENCH(return new BlurBench(p, REAL, SkBlurMaskFilter::kSolid_BlurStyle);)
 DEF_BENCH(return new BlurBench(p, REAL, SkBlurMaskFilter::kOuter_BlurStyle);)
 DEF_BENCH(return new BlurBench(p, REAL, SkBlurMaskFilter::kInner_BlurStyle);)
 
+DEF_BENCH(return new BlurBench(p, SMALL, SkBlurMaskFilter::kNormal_BlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
+DEF_BENCH(return new BlurBench(p, BIG, SkBlurMaskFilter::kNormal_BlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
+DEF_BENCH(return new BlurBench(p, REALBIG, SkBlurMaskFilter::kNormal_BlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
+DEF_BENCH(return new BlurBench(p, REAL, SkBlurMaskFilter::kNormal_BlurStyle, SkBlurMaskFilter::kHighQuality_BlurFlag);)
+
 DEF_BENCH(return new BlurBench(p, 0, SkBlurMaskFilter::kNormal_BlurStyle);)
 
diff --git a/include/effects/SkBlurDrawLooper.h b/include/effects/SkBlurDrawLooper.h
index eeed1b6..c410761 100644
--- a/include/effects/SkBlurDrawLooper.h
+++ b/include/effects/SkBlurDrawLooper.h
@@ -31,10 +31,8 @@
         kIgnoreTransform_BlurFlag   = 0x01,
         kOverrideColor_BlurFlag     = 0x02,
         kHighQuality_BlurFlag       = 0x04,
-        /** faster, but may discretize the radius */
-        kCoarseRadius_BlurFlag      = 0x08,
         /** mask for all blur flags */
-        kAll_BlurFlag               = 0x0F
+        kAll_BlurFlag               = 0x07
     };
 
     SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, SkColor color,
diff --git a/include/effects/SkBlurMaskFilter.h b/include/effects/SkBlurMaskFilter.h
index e957a9d..2ab321a 100644
--- a/include/effects/SkBlurMaskFilter.h
+++ b/include/effects/SkBlurMaskFilter.h
@@ -29,10 +29,8 @@
         kIgnoreTransform_BlurFlag   = 0x01,
         /** Use a smother, higher qulity blur algorithm */
         kHighQuality_BlurFlag       = 0x02,
-        /** Do faster blurs by rounding the radius to a set of sub-integer values */
-        kCoarseRadius_BlurFlag      = 0x04,
         /** mask for all blur flags */
-        kAll_BlurFlag = 0x07
+        kAll_BlurFlag = 0x03
     };
 
     /** Create a blur maskfilter.
diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp
index 8854225..e6e2ffd 100644
--- a/src/effects/SkBlurDrawLooper.cpp
+++ b/src/effects/SkBlurDrawLooper.cpp
@@ -27,10 +27,6 @@
             SkBlurMaskFilter::kHighQuality_BlurFlag :
             SkBlurMaskFilter::kNone_BlurFlag;
 
-        blurFlags |= flags & kCoarseRadius_BlurFlag ?
-            SkBlurMaskFilter::kCoarseRadius_BlurFlag :
-            SkBlurMaskFilter::kNone_BlurFlag;
-
         fBlur = SkBlurMaskFilter::Create(radius,
                                          SkBlurMaskFilter::kNormal_BlurStyle,
                                          blurFlags);
diff --git a/src/effects/SkBlurMask.cpp b/src/effects/SkBlurMask.cpp
index 65dc2bf..658b0fd 100644
--- a/src/effects/SkBlurMask.cpp
+++ b/src/effects/SkBlurMask.cpp
@@ -860,10 +860,12 @@
     }
 
     // Force high quality off for small radii (performance)
-    if (radius < SkIntToScalar(3) && !separable) quality = kLow_Quality;
+    if (radius < SkIntToScalar(3)) {
+        quality = kLow_Quality;
+    }
 
     // highQuality: use three box blur passes as a cheap way to approximate a Gaussian blur
-    int passCount = (quality == kHigh_Quality || separable) ? 3 : 1;
+    int passCount = (kHigh_Quality == quality) ? 3 : 1;
     SkScalar passRadius = SkScalarDiv(radius, SkScalarSqrt(SkIntToScalar(passCount)));
 
     int rx = SkScalarCeil(passRadius);
@@ -907,27 +909,36 @@
             uint8_t*                tp = tmpBuffer.get();
             int w = sw, h = sh;
 
-            if (outer_weight == 255 || quality == kLow_Quality) {
-                // For separable blurs, low quality means no interpolation.
+            if (outer_weight == 255) {
                 int loRadius, hiRadius;
                 get_adjusted_radii(passRadius, &loRadius, &hiRadius);
-                // Do three X blurs, with a transpose on the final one.
-                w = boxBlur(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h, false);
-                w = boxBlur(tp, w,             dp, hiRadius, loRadius, w, h, false);
-                w = boxBlur(dp, w,             tp, hiRadius, hiRadius, w, h, true);
-                // Do three Y blurs, with a transpose on the final one.
-                h = boxBlur(tp, h,             dp, loRadius, hiRadius, h, w, false);
-                h = boxBlur(dp, h,             tp, hiRadius, loRadius, h, w, false);
-                h = boxBlur(tp, h,             dp, hiRadius, hiRadius, h, w, true);
+                if (kHigh_Quality == quality) {
+                    // Do three X blurs, with a transpose on the final one.
+                    w = boxBlur(sp, src.fRowBytes, tp, loRadius, hiRadius, w, h, false);
+                    w = boxBlur(tp, w,             dp, hiRadius, loRadius, w, h, false);
+                    w = boxBlur(dp, w,             tp, hiRadius, hiRadius, w, h, true);
+                    // Do three Y blurs, with a transpose on the final one.
+                    h = boxBlur(tp, h,             dp, loRadius, hiRadius, h, w, false);
+                    h = boxBlur(dp, h,             tp, hiRadius, loRadius, h, w, false);
+                    h = boxBlur(tp, h,             dp, hiRadius, hiRadius, h, w, true);
+                } else {
+                    w = boxBlur(sp, src.fRowBytes, tp, rx, rx, w, h, true);
+                    h = boxBlur(tp, h,             dp, ry, ry, h, w, true);
+                }
             } else {
-                // Do three X blurs, with a transpose on the final one.
-                w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, false, outer_weight);
-                w = boxBlurInterp(tp, w,             dp, rx, w, h, false, outer_weight);
-                w = boxBlurInterp(dp, w,             tp, rx, w, h, true, outer_weight);
-                // Do three Y blurs, with a transpose on the final one.
-                h = boxBlurInterp(tp, h,             dp, ry, h, w, false, outer_weight);
-                h = boxBlurInterp(dp, h,             tp, ry, h, w, false, outer_weight);
-                h = boxBlurInterp(tp, h,             dp, ry, h, w, true, outer_weight);
+                if (kHigh_Quality == quality) {
+                    // Do three X blurs, with a transpose on the final one.
+                    w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, false, outer_weight);
+                    w = boxBlurInterp(tp, w,             dp, rx, w, h, false, outer_weight);
+                    w = boxBlurInterp(dp, w,             tp, rx, w, h, true, outer_weight);
+                    // Do three Y blurs, with a transpose on the final one.
+                    h = boxBlurInterp(tp, h,             dp, ry, h, w, false, outer_weight);
+                    h = boxBlurInterp(dp, h,             tp, ry, h, w, false, outer_weight);
+                    h = boxBlurInterp(tp, h,             dp, ry, h, w, true, outer_weight);
+                } else {
+                    w = boxBlurInterp(sp, src.fRowBytes, tp, rx, w, h, true, outer_weight);
+                    h = boxBlurInterp(tp, h,             dp, ry, h, w, true, outer_weight);
+                }
             }
         } else {
             const size_t storageW = sw + 2 * (passCount - 1) * rx + 1;
@@ -943,7 +954,7 @@
                 apply_kernel_interp(dp, rx, ry, sumBuffer, sw, sh, outer_weight);
             }
 
-            if (quality == kHigh_Quality) {
+            if (kHigh_Quality == quality) {
                 //pass2: dp is source, tmpBuffer is destination
                 int tmp_sw = sw + 2 * rx;
                 int tmp_sh = sh + 2 * ry;
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index a32b31b..6e989fc 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -97,13 +97,13 @@
         (fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag) ?
             SkBlurMask::kHigh_Quality : SkBlurMask::kLow_Quality;
 
-    if (fBlurFlags & SkBlurMaskFilter::kCoarseRadius_BlurFlag) {
-        return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
-                                blurQuality, margin);
-    } else {
-        return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
-                                blurQuality, margin);
-    }
+#ifdef SK_BLUR_MASK_SEPARABLE
+    return SkBlurMask::BlurSeparable(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
+                            blurQuality, margin);
+#else
+    return SkBlurMask::Blur(dst, src, radius, (SkBlurMask::Style)fBlurStyle,
+                            blurQuality, margin);
+#endif
 }
 
 #include "SkCanvas.h"