Chromium Code Reviews| Index: src/effects/SkBlurMaskFilter.cpp |
| diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp |
| index e808885dddbe8a3143db1a7973dce6b11dd6aa28..1340ee750c578aa7228ee33f681fd5325e05f86d 100644 |
| --- a/src/effects/SkBlurMaskFilter.cpp |
| +++ b/src/effects/SkBlurMaskFilter.cpp |
| @@ -6,6 +6,8 @@ |
| * found in the LICENSE file. |
| */ |
| +#include <list> |
|
Stephen White
2014/06/09 18:03:58
I'm not sure what the Skia project's official stan
|
| + |
| #include "SkBlurMaskFilter.h" |
| #include "SkBlurMask.h" |
| #include "SkGpuBlurUtils.h" |
| @@ -14,6 +16,7 @@ |
| #include "SkMaskFilter.h" |
| #include "SkRRect.h" |
| #include "SkRTConf.h" |
| +#include "SkScaledImageCache.h" |
| #include "SkStringUtils.h" |
| #include "SkStrokeRec.h" |
| @@ -65,6 +68,45 @@ public: |
| virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; |
| virtual bool asABlur(BlurRec*) const SK_OVERRIDE; |
| + class BlurMaskRecord { |
| + public: |
| + BlurMaskRecord(): fSigma(0), |
| + fRectCount(0), |
| + fRects(NULL), |
| + fMask(NULL) {} |
| + |
| + BlurMaskRecord(SkScalar sigma, unsigned rectCount, SkRect** rects, SkDiscardableMemoryMask* mask) |
| + : fSigma(sigma), |
| + fRectCount(rectCount), |
| + fRects(rects), |
| + fMask(mask) {} |
| + |
| + ~BlurMaskRecord() { |
| + if (fMask) { |
| + delete fMask; |
| + } |
| + if (fRects) { |
| + for(unsigned i = 0; i < fRectCount; i++) { |
| + if (fRects[i]) |
| + delete fRects[i]; |
| + } |
| + delete []fRects; |
| + } |
| + } |
| + |
| + SkScalar fSigma; |
| + unsigned fRectCount; |
| + SkRect** fRects; |
| + SkDiscardableMemoryMask* fMask; |
| + }; |
| + |
| + static bool getBlurMaskRecord(SkScalar sigma, |
| + unsigned rectCount, |
| + const SkRect rects[], |
| + SkDiscardableMemoryMask** mask); |
| + static bool addBlurMaskRecord(BlurMaskRecord* blurMaskRecord); |
| + static void clearBlurMaskRecordList(); |
| + |
| SK_TO_STRING_OVERRIDE() |
| SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) |
| @@ -107,11 +149,84 @@ private: |
| return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); |
| } |
| + typedef std::list<BlurMaskRecord*> BlurMaskRecordList; |
| + static BlurMaskRecordList fCachedBlurMaskRecordList; |
| + |
| typedef SkMaskFilter INHERITED; |
| }; |
| const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); |
| +SkBlurMaskFilterImpl::BlurMaskRecordList SkBlurMaskFilterImpl::fCachedBlurMaskRecordList; |
| +SK_DECLARE_STATIC_MUTEX(gMutex); |
| + |
| +bool SkBlurMaskFilterImpl::getBlurMaskRecord(SkScalar sigma, |
| + unsigned rectCount, |
| + const SkRect rects[], |
| + SkDiscardableMemoryMask** mask) { |
| + SkAutoMutexAcquire am(gMutex); |
| + if (!fCachedBlurMaskRecordList.empty()) { |
| + for (BlurMaskRecordList::reverse_iterator it = fCachedBlurMaskRecordList.rbegin(); |
| + it != fCachedBlurMaskRecordList.rend(); ++it) { |
| + BlurMaskRecord* cachedBlurMaskRecord = *it; |
| + if (cachedBlurMaskRecord->fSigma == sigma |
| + && cachedBlurMaskRecord->fRectCount == rectCount) { |
| + bool found = true; |
| + SkRect* tempRects[2] = {NULL, NULL}; |
| + for (unsigned i = 0; i < rectCount; i++) { |
| + tempRects[i] = *(cachedBlurMaskRecord->fRects + i); |
| + if (tempRects[i]->width() != rects[i].width() || |
| + tempRects[i]->height() != rects[i].height()) { |
| + found = false; |
|
Stephen White
2014/06/09 18:03:58
Perhaps this inner loop could be in its own functi
|
| + break; |
| + } |
| + } |
| + if (found && rectCount == 2) { |
| + if ((tempRects[0]->x() - rects[0].x()) != (tempRects[1]->x() - rects[1].x()) || |
| + (tempRects[0]->y() - rects[0].y()) != (tempRects[1]->y() - rects[1].y())) |
| + found = false; |
|
Stephen White
2014/06/09 18:03:58
Same here.
|
| + } |
| + if (found) { |
| + SkBitmap bitmap; |
| + void* scaledCacheId = SkScaledImageCache::FindAndLock(cachedBlurMaskRecord->fMask->fPixelGenerationID, |
| + cachedBlurMaskRecord->fMask->fMask.fBounds.width(), |
| + cachedBlurMaskRecord->fMask->fMask.fBounds.height(), |
| + &bitmap); |
| + if (scaledCacheId) { |
| + SkAutoLockPixels autoLockPixels(bitmap); |
| + if (bitmap.getPixels()) { |
| + cachedBlurMaskRecord->fMask->fCacheId = scaledCacheId; |
| + *mask = cachedBlurMaskRecord->fMask; |
| + return true; |
| + } |
| + } |
| + fCachedBlurMaskRecordList.erase(--it.base()); |
| + return false; |
| + } |
| + } |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +bool SkBlurMaskFilterImpl::addBlurMaskRecord(BlurMaskRecord* blurMaskRecord) { |
| + SkAutoMutexAcquire am(gMutex); |
| + fCachedBlurMaskRecordList.push_back(blurMaskRecord); |
| + return true; |
| +} |
| + |
| +void SkBlurMaskFilterImpl::clearBlurMaskRecordList() { |
| + SkAutoMutexAcquire am(gMutex); |
| + while (!fCachedBlurMaskRecordList.empty()) { |
| + BlurMaskRecord* cachedBlurMaskRecord = fCachedBlurMaskRecordList.front(); |
| + fCachedBlurMaskRecordList.pop_front(); |
| + if (cachedBlurMaskRecord) { |
| + delete cachedBlurMaskRecord; |
| + cachedBlurMaskRecord = NULL; |
| + } |
| + } |
| +} |
| + |
| SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32_t flags) { |
| if (!SkScalarIsFinite(sigma) || sigma <= 0) { |
| return NULL; |
| @@ -365,10 +480,24 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma |
| radii[SkRRect::kLowerLeft_Corner] = LL; |
| smallRR.setRectRadii(smallR, radii); |
| + SkScalar sigma = this->computeXformedSigma(matrix); |
| + SkDiscardableMemoryMask* cachedBlurMask = NULL; |
| + SkRect rects[1]; |
| + rects[0] = rrect.rect(); |
| + if (getBlurMaskRecord(sigma, 1, rects, &cachedBlurMask)) { |
| + patch->fDiscardableMemoryMask = *cachedBlurMask; |
| + patch->fOuterRect = dstM.fBounds; |
| + patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; |
| + patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; |
| + return kTrue_FilterReturn; |
| + } |
| + |
| + SkBlurMask::addDiscardableMemoryMaskToMap(&(patch->fDiscardableMemoryMask.fMask), |
| + &(patch->fDiscardableMemoryMask)); |
| bool analyticBlurWorked = false; |
| if (c_analyticBlurRRect) { |
| analyticBlurWorked = |
| - this->filterRRectMask(&patch->fMask, smallRR, matrix, &margin, |
| + this->filterRRectMask(&(patch->fDiscardableMemoryMask.fMask), smallRR, matrix, &margin, |
| SkMask::kComputeBoundsAndRenderImage_CreateMode); |
| } |
| @@ -379,15 +508,27 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma |
| SkAutoMaskFreeImage amf(srcM.fImage); |
| - if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { |
| + if (!this->filterMask(&(patch->fDiscardableMemoryMask.fMask), srcM, matrix, &margin)) { |
| return kFalse_FilterReturn; |
| } |
| } |
| - patch->fMask.fBounds.offsetTo(0, 0); |
| + SkBlurMask::removeDiscardableMemoryMaskFromMap(&(patch->fDiscardableMemoryMask.fMask)); |
| + patch->fDiscardableMemoryMask.fMask.fBounds.offsetTo(0, 0); |
| patch->fOuterRect = dstM.fBounds; |
| patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; |
| patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; |
| + if (!cachedBlurMask) { |
| + SkDiscardableMemoryMask* tempMask = new SkDiscardableMemoryMask; |
| + *tempMask = patch->fDiscardableMemoryMask; |
| + SkRect** tempRects = new SkRect* [1]; |
| + tempRects[0] = new SkRect; |
| + *(tempRects[0]) = rrect.rect(); |
| + BlurMaskRecord * blurMaskRecord = new BlurMaskRecord(sigma, 1, tempRects, tempMask); |
| + if (blurMaskRecord) |
| + addBlurMaskRecord(blurMaskRecord); |
| + } |
| + |
| return kTrue_FilterReturn; |
| } |
| @@ -467,6 +608,15 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
| smallH + (innerIR.top() - srcM.fBounds.top())); |
| } |
| + SkScalar sigma = this->computeXformedSigma(matrix); |
| + SkDiscardableMemoryMask* cachedBlurMask = NULL; |
| + if (getBlurMaskRecord(sigma, count, rects, &cachedBlurMask)) { |
| + patch->fDiscardableMemoryMask = *cachedBlurMask; |
| + patch->fOuterRect = dstM.fBounds; |
| + patch->fCenter = center; |
| + return kTrue_FilterReturn; |
| + } |
| + |
| // +1 so we get a clean, stretchable, center row/col |
| smallW += 1; |
| smallH += 1; |
| @@ -491,25 +641,40 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
| SkASSERT(!smallR[1].isEmpty()); |
| } |
| + SkBlurMask::addDiscardableMemoryMaskToMap(&(patch->fDiscardableMemoryMask.fMask), |
| + &(patch->fDiscardableMemoryMask)); |
| 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)) { |
| + if (!this->filterMask(&patch->fDiscardableMemoryMask.fMask, srcM, matrix, &margin)) { |
| return kFalse_FilterReturn; |
| } |
| } else { |
| - if (!this->filterRectMask(&patch->fMask, smallR[0], matrix, &margin, |
| + if (!this->filterRectMask(&patch->fDiscardableMemoryMask.fMask, smallR[0], matrix, &margin, |
| SkMask::kComputeBoundsAndRenderImage_CreateMode)) { |
| return kFalse_FilterReturn; |
| } |
| } |
| - patch->fMask.fBounds.offsetTo(0, 0); |
| + patch->fDiscardableMemoryMask.fMask.fBounds.offsetTo(0, 0); |
| patch->fOuterRect = dstM.fBounds; |
| patch->fCenter = center; |
| + SkBlurMask::removeDiscardableMemoryMaskFromMap(&(patch->fDiscardableMemoryMask.fMask)); |
| + if (!cachedBlurMask) { |
| + SkDiscardableMemoryMask* tempMask = new SkDiscardableMemoryMask; |
| + *tempMask = patch->fDiscardableMemoryMask; |
| + SkRect** tempRects = new SkRect* [count]; |
| + for (int i = 0; i < count; i++) { |
| + tempRects[i] = new SkRect; |
| + *(tempRects[i]) = rects[i]; |
| + } |
| + BlurMaskRecord * blurMaskRecord = new BlurMaskRecord(sigma, count, tempRects, tempMask); |
| + if (blurMaskRecord) |
| + addBlurMaskRecord(blurMaskRecord); |
| + } |
| + |
| return kTrue_FilterReturn; |
| } |