diff options
author | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-11-29 17:09:27 +0000 |
---|---|---|
committer | senorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-11-29 17:09:27 +0000 |
commit | 91f489a65d436d36c7fe580af2775cd0cd13c8d2 (patch) | |
tree | 99dc1569121ee3cf78b80768788d3aeafc9e19ad | |
parent | f4d1b3911831d2111a351b2742b3a94a9d17f92e (diff) |
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
-rw-r--r-- | bench/BlurBench.cpp | 25 | ||||
-rw-r--r-- | include/effects/SkBlurDrawLooper.h | 4 | ||||
-rw-r--r-- | include/effects/SkBlurMaskFilter.h | 4 | ||||
-rw-r--r-- | src/effects/SkBlurDrawLooper.cpp | 4 | ||||
-rw-r--r-- | src/effects/SkBlurMask.cpp | 53 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 14 |
6 files changed, 62 insertions, 42 deletions
diff --git a/bench/BlurBench.cpp b/bench/BlurBench.cpp index cf95610974..ab77d2b011 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 @@ static const char* gStyleName[] = { 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 @@ protected: 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::kSolid_BlurStyle);) 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 eeed1b6c20..c4107612cb 100644 --- a/include/effects/SkBlurDrawLooper.h +++ b/include/effects/SkBlurDrawLooper.h @@ -31,10 +31,8 @@ public: 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 e957a9ddd4..2ab321aa7a 100644 --- a/include/effects/SkBlurMaskFilter.h +++ b/include/effects/SkBlurMaskFilter.h @@ -29,10 +29,8 @@ public: 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 8854225636..e6e2ffdd8c 100644 --- a/src/effects/SkBlurDrawLooper.cpp +++ b/src/effects/SkBlurDrawLooper.cpp @@ -27,10 +27,6 @@ SkBlurDrawLooper::SkBlurDrawLooper(SkScalar radius, SkScalar dx, SkScalar dy, 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 65dc2bf176..658b0fd47e 100644 --- a/src/effects/SkBlurMask.cpp +++ b/src/effects/SkBlurMask.cpp @@ -860,10 +860,12 @@ bool SkBlurMask::Blur(SkMask* dst, const SkMask& src, } // 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 @@ bool SkBlurMask::Blur(SkMask* dst, const SkMask& src, 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 @@ bool SkBlurMask::Blur(SkMask* dst, const SkMask& src, 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 a32b31bedc..6e989fc506 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -97,13 +97,13 @@ bool SkBlurMaskFilterImpl::filterMask(SkMask* dst, const SkMask& src, (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" |