diff options
author | qiankun.miao <qiankun.miao@intel.com> | 2015-01-07 18:37:47 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-07 18:37:47 -0800 |
commit | 5a5b4e900ee69540fc35952882a323c63d6d0db9 (patch) | |
tree | ad2e0f3642f3feeecdb0b8eb37a2b1b6af398635 /src/core | |
parent | 281ecc27ee93f34485d49af8de39a73656a87c9c (diff) |
Cache blur mask for rects which can not break into nine-patch
With this CL performance improves:
blurrectsnonninepatch 42.4us -> 20.5us 0.48x
BUG=431021,skia:3118
Review URL: https://codereview.chromium.org/729463002
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkMaskCache.cpp | 50 | ||||
-rw-r--r-- | src/core/SkMaskCache.h | 19 | ||||
-rw-r--r-- | src/core/SkMaskFilter.cpp | 37 |
3 files changed, 104 insertions, 2 deletions
diff --git a/src/core/SkMaskCache.cpp b/src/core/SkMaskCache.cpp index b4b8b4faf3..207ea0e77d 100644 --- a/src/core/SkMaskCache.cpp +++ b/src/core/SkMaskCache.cpp @@ -18,6 +18,28 @@ struct MaskValue { namespace { static unsigned gRRectBlurKeyNamespaceLabel; +static bool copy_cacheddata_to_mask(SkCachedData* data, SkMask* mask) { + const size_t size = data->size(); + SkASSERT(mask->computeTotalImageSize() <= size); + + mask->fImage = SkMask::AllocImage(size); + if (mask->fImage) { + memcpy(mask->fImage, data->data(), size); + return true; + } + return false; +} + +static SkCachedData* copy_mask_to_cacheddata(const SkMask& mask) { + const size_t size = mask.computeTotalImageSize(); + SkCachedData* data = SkResourceCache::NewCachedData(size); + if (data) { + memcpy(data->writable_data(), mask.fImage, size); + return data; + } + return NULL; +} + struct RRectBlurKey : public SkResourceCache::Key { public: RRectBlurKey(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, SkBlurQuality quality) @@ -90,6 +112,20 @@ void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RRectBlurRec, (key, mask, data))); } +bool SkMaskCache::FindAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, SkMask* mask) { + SkAutoTUnref<SkCachedData> data(SkMaskCache::FindAndRef(sigma, style, quality, rrect, mask)); + return data.get() && copy_cacheddata_to_mask(data, mask); +} + +void SkMaskCache::AddAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, const SkMask& mask) { + SkAutoTUnref<SkCachedData> data(copy_mask_to_cacheddata(mask)); + if (data.get()) { + SkMaskCache::Add(sigma, style, quality, rrect, mask, data); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// namespace { @@ -181,3 +217,17 @@ void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, RectsBlurKey key(sigma, style, quality, rects, count); return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RectsBlurRec, (key, mask, data))); } + +bool SkMaskCache::FindAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, SkMask* mask) { + SkAutoTUnref<SkCachedData> data(SkMaskCache::FindAndRef(sigma, style, quality, rects, count, mask)); + return data.get() && copy_cacheddata_to_mask(data, mask); +} + +void SkMaskCache::AddAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, const SkMask& mask) { + SkAutoTUnref<SkCachedData> data(copy_mask_to_cacheddata(mask)); + if (data.get()) { + SkMaskCache::Add(sigma, style, quality, rects, count, mask, data); + } +} diff --git a/src/core/SkMaskCache.h b/src/core/SkMaskCache.h index f98387b206..2cfb971dde 100644 --- a/src/core/SkMaskCache.h +++ b/src/core/SkMaskCache.h @@ -39,6 +39,25 @@ public: static void Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, const SkRect rects[], int count, const SkMask& mask, SkCachedData* data, SkResourceCache* localCache = NULL); + + /** + * On success, set mask with cached value, allocate memory for mask->fImage, + * copy pixels from SkCachedData in the cache to mask->fImage, then return true. + * + * On failure, return false, no memory allocated for mask->fImage. + */ + static bool FindAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, SkMask* mask); + static bool FindAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, SkMask* mask); + + /** + * Create a new SkCachedData, copy pixels from mask.fImage to it, then add it into cache. + */ + static void AddAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, const SkMask& mask); + static void AddAndCopy(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, const SkMask& mask); }; #endif diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp index c9783e76d6..3a4e3a41e9 100644 --- a/src/core/SkMaskFilter.cpp +++ b/src/core/SkMaskFilter.cpp @@ -10,6 +10,7 @@ #include "SkMaskFilter.h" #include "SkBlitter.h" #include "SkDraw.h" +#include "SkMaskCache.h" #include "SkRasterClip.h" #include "SkRRect.h" #include "SkTypes.h" @@ -263,9 +264,41 @@ bool SkMaskFilter::filterPath(const SkPath& devPath, const SkMatrix& matrix, } SkAutoMaskFreeImage autoSrc(srcM.fImage); - if (!this->filterMask(&dstM, srcM, matrix, NULL)) { - return false; + BlurRec rec; + if (this->asABlur(&rec) && rectCount) { + SkScalar scaledSigma = matrix.mapRadius(rec.fSigma); + if (!SkMaskCache::FindAndCopy(scaledSigma, rec.fStyle, rec.fQuality, + rects, rectCount, &dstM)) { + if (!this->filterMask(&dstM, srcM, matrix, NULL)) { + return false; + } + SkMaskCache::AddAndCopy(scaledSigma, rec.fStyle, rec.fQuality, rects, rectCount, dstM); + } else { + // Compute the correct bounds of dst mask if dst mask is got from cache. + SkMask tmpSrc, tmpDst; + tmpSrc = srcM; + tmpSrc.fImage = NULL; + if (!this->filterMask(&tmpDst, tmpSrc, matrix, NULL)) { + return false; + } + + // Fallback to original calculation if size of bounds is different with + // size of the cached mask. + if (dstM.fBounds.width() != tmpDst.fBounds.width() || + dstM.fBounds.height() != tmpDst.fBounds.height()) { + if (!this->filterMask(&dstM, srcM, matrix, NULL)) { + return false; + } + } else { + dstM.fBounds = tmpDst.fBounds; + } + } + } else { + if (!this->filterMask(&dstM, srcM, matrix, NULL)) { + return false; + } } + SkAutoMaskFreeImage autoDst(dstM.fImage); // if we get here, we need to (possibly) resolve the clip and blitter |