diff options
-rw-r--r-- | src/core/SkMaskCache.cpp | 44 | ||||
-rw-r--r-- | src/core/SkMaskCache.h | 18 | ||||
-rw-r--r-- | src/effects/SkBlurMaskFilter.cpp | 114 | ||||
-rw-r--r-- | tests/MaskCacheTest.cpp | 13 |
4 files changed, 127 insertions, 62 deletions
diff --git a/src/core/SkMaskCache.cpp b/src/core/SkMaskCache.cpp index 4520e9775f..e203081655 100644 --- a/src/core/SkMaskCache.cpp +++ b/src/core/SkMaskCache.cpp @@ -22,17 +22,18 @@ struct RRectBlurKey : public SkResourceCache::Key { public: RRectBlurKey(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, SkBlurQuality quality) : fSigma(sigma) - , fRRect(rrect) , fStyle(style) - , fQuality(quality) { + , fQuality(quality) + , fRRect(rrect) + { this->init(&gRRectBlurKeyNamespaceLabel, - sizeof(fSigma) + sizeof(fRRect) + sizeof(fStyle) + sizeof(fQuality)); + sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fRRect)); } SkScalar fSigma; - SkRRect fRRect; int32_t fStyle; int32_t fQuality; + SkRRect fRRect; }; struct RRectBlurRec : public SkResourceCache::Rec { @@ -69,9 +70,8 @@ struct RRectBlurRec : public SkResourceCache::Rec { }; } // namespace -SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, - SkBlurQuality quality, SkMask* mask, - SkResourceCache* localCache) { +SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, SkMask* mask, SkResourceCache* localCache) { MaskValue result; RRectBlurKey key(sigma, rrect, style, quality); if (!CHECK_LOCAL(localCache, find, Find, key, RRectBlurRec::Visitor, &result)) { @@ -83,8 +83,8 @@ SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, const SkRRect& rrect, SkBl return result.fData; } -void SkMaskCache::Add(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, - SkBlurQuality quality, const SkMask& mask, SkCachedData* data, +void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, const SkMask& mask, SkCachedData* data, SkResourceCache* localCache) { RRectBlurKey key(sigma, rrect, style, quality); return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RRectBlurRec, (key, mask, data))); @@ -97,10 +97,12 @@ static unsigned gRectsBlurKeyNamespaceLabel; struct RectsBlurKey : public SkResourceCache::Key { public: - RectsBlurKey(SkScalar sigma, int count, const SkRect rects[], SkBlurStyle style) + RectsBlurKey(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count) : fSigma(sigma) - , fRecCount(count) - , fStyle(style){ + , fStyle(style) + , fQuality(quality) + { SkASSERT(1 == count || 2 == count); fRects[0] = SkRect::MakeEmpty(); fRects[1] = SkRect::MakeEmpty(); @@ -108,13 +110,13 @@ public: fRects[i] = rects[i]; } this->init(&gRectsBlurKeyNamespaceLabel, - sizeof(fSigma) + sizeof(fRecCount) + sizeof(fRects) + sizeof(fStyle)); + sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fRects)); } SkScalar fSigma; - int fRecCount; - SkRect fRects[2]; int32_t fStyle; + int32_t fQuality; + SkRect fRects[2]; }; struct RectsBlurRec : public SkResourceCache::Rec { @@ -151,11 +153,11 @@ struct RectsBlurRec : public SkResourceCache::Rec { }; } // namespace -SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, const SkRect rects[], int count, - SkBlurStyle style, SkMask* mask, +SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, SkMask* mask, SkResourceCache* localCache) { MaskValue result; - RectsBlurKey key(sigma, count, rects, style); + RectsBlurKey key(sigma, style, quality, rects, count); if (!CHECK_LOCAL(localCache, find, Find, key, RectsBlurRec::Visitor, &result)) { return NULL; } @@ -165,9 +167,9 @@ SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, const SkRect rects[], int return result.fData; } -void SkMaskCache::Add(SkScalar sigma, const SkRect rects[], int count, SkBlurStyle style, - const SkMask& mask, SkCachedData* data, +void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, const SkMask& mask, SkCachedData* data, SkResourceCache* localCache) { - RectsBlurKey key(sigma, count, rects, style); + RectsBlurKey key(sigma, style, quality, rects, count); return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RectsBlurRec, (key, mask, data))); } diff --git a/src/core/SkMaskCache.h b/src/core/SkMaskCache.h index f44ed3874c..f98387b206 100644 --- a/src/core/SkMaskCache.h +++ b/src/core/SkMaskCache.h @@ -23,20 +23,22 @@ public: * * On failure, return NULL. */ - static SkCachedData* FindAndRef(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, - SkBlurQuality quality, SkMask* mask, + static SkCachedData* FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, SkMask* mask, SkResourceCache* localCache = NULL); - static SkCachedData* FindAndRef(SkScalar sigma, const SkRect rects[], int count, - SkBlurStyle style,SkMask* mask, + static SkCachedData* FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, SkMask* mask, SkResourceCache* localCache = NULL); /** * Add a mask and its pixel-data to the cache. */ - static void Add(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, SkBlurQuality quality, - const SkMask& mask, SkCachedData* data, SkResourceCache* localCache = NULL); - static void Add(SkScalar sigma, const SkRect rects[], int count, SkBlurStyle style, - const SkMask& mask, SkCachedData* data, SkResourceCache* localCache = NULL); + static void Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRRect& rrect, const SkMask& mask, SkCachedData* data, + SkResourceCache* localCache = NULL); + static void Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, + const SkRect rects[], int count, const SkMask& mask, SkCachedData* data, + SkResourceCache* localCache = NULL); }; #endif diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp index 6f69aaf4ab..f0bd3757a6 100644 --- a/src/effects/SkBlurMaskFilter.cpp +++ b/src/effects/SkBlurMaskFilter.cpp @@ -257,6 +257,58 @@ static bool rect_exceeds(const SkRect& r, SkScalar v) { r.width() > v || r.height() > v; } +#include "SkMaskCache.h" + +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; +} + +static bool find_cached_rrect(SkMask* mask, SkScalar sigma, SkBlurStyle style, + SkBlurQuality quality, const SkRRect& rrect) { + SkAutoTUnref<SkCachedData> data(SkMaskCache::FindAndRef(sigma, style, quality, rrect, mask)); + return data.get() && copy_cacheddata_to_mask(data, mask); +} + +static void add_cached_rrect(const SkMask& mask, SkScalar sigma, SkBlurStyle style, + SkBlurQuality quality, const SkRRect& rrect) { + SkAutoTUnref<SkCachedData> data(copy_mask_to_cacheddata(mask)); + if (data.get()) { + SkMaskCache::Add(sigma, style, quality, rrect, mask, data); + } +} + +static bool find_cached_rects(SkMask* mask, SkScalar sigma, SkBlurStyle style, + SkBlurQuality quality, const SkRect rects[], int count) { + SkAutoTUnref<SkCachedData> data(SkMaskCache::FindAndRef(sigma, style, quality, rects, count, mask)); + return data.get() && copy_cacheddata_to_mask(data, mask); +} + +static void add_cached_rects(const SkMask& mask, SkScalar sigma, SkBlurStyle style, + SkBlurQuality quality, const SkRect rects[], int count) { + SkAutoTUnref<SkCachedData> data(copy_mask_to_cacheddata(mask)); + if (data.get()) { + SkMaskCache::Add(sigma, style, quality, rects, count, mask, data); + } +} + #ifdef SK_IGNORE_FAST_RRECT_BLUR SK_CONF_DECLARE( bool, c_analyticBlurRRect, "mask.filter.blur.analyticblurrrect", false, "Use the faster analytic blur approach for ninepatch rects" ); #else @@ -368,23 +420,27 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma radii[SkRRect::kLowerLeft_Corner] = LL; smallRR.setRectRadii(smallR, radii); - bool analyticBlurWorked = false; - if (c_analyticBlurRRect) { - analyticBlurWorked = - this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, - SkMask::kComputeBoundsAndRenderImage_CreateMode); - } - - if (!analyticBlurWorked) { - if (!draw_rrect_into_mask(smallRR, &srcM)) { - return kFalse_FilterReturn; + const SkScalar sigma = this->computeXformedSigma(matrix); + if (!find_cached_rrect(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR)) { + bool analyticBlurWorked = false; + if (c_analyticBlurRRect) { + analyticBlurWorked = + this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, + SkMask::kComputeBoundsAndRenderImage_CreateMode); } - SkAutoMaskFreeImage amf(srcM.fImage); + if (!analyticBlurWorked) { + if (!draw_rrect_into_mask(smallRR, &srcM)) { + return kFalse_FilterReturn; + } - if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { - return kFalse_FilterReturn; + SkAutoMaskFreeImage amf(srcM.fImage); + + if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { + return kFalse_FilterReturn; + } } + add_cached_rrect(patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR); } patch->fMask.fBounds.offsetTo(0, 0); @@ -494,21 +550,25 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, SkASSERT(!smallR[1].isEmpty()); } - if (count > 1 || !c_analyticBlurNinepatch) { - if (!draw_rects_into_mask(smallR, count, &srcM)) { - return kFalse_FilterReturn; - } - - SkAutoMaskFreeImage amf(srcM.fImage); - - if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { - return kFalse_FilterReturn; - } - } else { - if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, - SkMask::kComputeBoundsAndRenderImage_CreateMode)) { - return kFalse_FilterReturn; + const SkScalar sigma = this->computeXformedSigma(matrix); + if (!find_cached_rects(&patch->fMask, sigma, fBlurStyle, this->getQuality(), rects, count)) { + if (count > 1 || !c_analyticBlurNinepatch) { + if (!draw_rects_into_mask(smallR, count, &srcM)) { + return kFalse_FilterReturn; + } + + SkAutoMaskFreeImage amf(srcM.fImage); + + if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { + return kFalse_FilterReturn; + } + } else { + if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, + SkMask::kComputeBoundsAndRenderImage_CreateMode)) { + return kFalse_FilterReturn; + } } + add_cached_rects(patch->fMask, sigma, fBlurStyle, this->getQuality(), rects, count); } patch->fMask.fBounds.offsetTo(0, 0); patch->fOuterRect = dstM.fBounds; diff --git a/tests/MaskCacheTest.cpp b/tests/MaskCacheTest.cpp index 0b83c62c00..f4e316c6c9 100644 --- a/tests/MaskCacheTest.cpp +++ b/tests/MaskCacheTest.cpp @@ -39,7 +39,7 @@ DEF_TEST(RRectMaskCache, reporter) { SkBlurQuality quality = kLow_SkBlurQuality; SkMask mask; - SkCachedData* data = SkMaskCache::FindAndRef(sigma, rrect, style, quality, &mask, &cache); + SkCachedData* data = SkMaskCache::FindAndRef(sigma, style, quality, rrect, &mask, &cache); REPORTER_ASSERT(reporter, NULL == data); size_t size = 256; @@ -48,14 +48,14 @@ DEF_TEST(RRectMaskCache, reporter) { mask.fBounds.setXYWH(0, 0, 100, 100); mask.fRowBytes = 100; mask.fFormat = SkMask::kBW_Format; - SkMaskCache::Add(sigma, rrect, style, quality, mask, data, &cache); + SkMaskCache::Add(sigma, style, quality, rrect, mask, data, &cache); check_data(reporter, data, 2, kInCache, kLocked); data->unref(); check_data(reporter, data, 1, kInCache, kUnlocked); sk_bzero(&mask, sizeof(mask)); - data = SkMaskCache::FindAndRef(sigma, rrect, style, quality, &mask, &cache); + data = SkMaskCache::FindAndRef(sigma, style, quality, rrect, &mask, &cache); REPORTER_ASSERT(reporter, data); REPORTER_ASSERT(reporter, data->size() == size); REPORTER_ASSERT(reporter, mask.fBounds.top() == 0 && mask.fBounds.bottom() == 100); @@ -74,9 +74,10 @@ DEF_TEST(RectsMaskCache, reporter) { SkRect rect = SkRect::MakeWH(100, 100); SkRect rects[2] = {rect}; SkBlurStyle style = kNormal_SkBlurStyle; + SkBlurQuality quality = kLow_SkBlurQuality; SkMask mask; - SkCachedData* data = SkMaskCache::FindAndRef(sigma, rects, 1, style, &mask, &cache); + SkCachedData* data = SkMaskCache::FindAndRef(sigma, style, quality, rects, 1, &mask, &cache); REPORTER_ASSERT(reporter, NULL == data); size_t size = 256; @@ -85,14 +86,14 @@ DEF_TEST(RectsMaskCache, reporter) { mask.fBounds.setXYWH(0, 0, 100, 100); mask.fRowBytes = 100; mask.fFormat = SkMask::kBW_Format; - SkMaskCache::Add(sigma, rects, 1, style, mask, data, &cache); + SkMaskCache::Add(sigma, style, quality, rects, 1, mask, data, &cache); check_data(reporter, data, 2, kInCache, kLocked); data->unref(); check_data(reporter, data, 1, kInCache, kUnlocked); sk_bzero(&mask, sizeof(mask)); - data = SkMaskCache::FindAndRef(sigma, rects, 1, style, &mask, &cache); + data = SkMaskCache::FindAndRef(sigma, style, quality, rects, 1, &mask, &cache); REPORTER_ASSERT(reporter, data); REPORTER_ASSERT(reporter, data->size() == size); REPORTER_ASSERT(reporter, mask.fBounds.top() == 0 && mask.fBounds.bottom() == 100); |