Chromium Code Reviews| Index: src/effects/SkBlurMaskFilter.cpp |
| diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp |
| index 2169a42cb6df9e043b34209de947f3d101d908a3..bf9712d67cd968fd701a177b68dbc78d10185b35 100644 |
| --- a/src/effects/SkBlurMaskFilter.cpp |
| +++ b/src/effects/SkBlurMaskFilter.cpp |
| @@ -6,6 +6,8 @@ |
| * found in the LICENSE file. |
| */ |
| +#include <list> |
| + |
| #include "SkBlurMaskFilter.h" |
| #include "SkBlurMask.h" |
| #include "SkGpuBlurUtils.h" |
| @@ -65,6 +67,49 @@ 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, SkMask* mask) |
| + : fSigma(sigma), |
| + fRectCount(rectCount), |
| + fRects(rects), |
| + fMask(mask) {} |
| + |
| + ~BlurMaskRecord() { |
| + if (fMask) { |
| + if (fMask->fImage) |
| + SkMask::FreeImage(fMask->fImage); |
| + delete fMask; |
| + } |
| + if (fRects) { |
| + for(int i = 0; i < fRectCount; i++) { |
| + if (fRects[i]) |
| + delete fRects[i]; |
| + } |
| + delete []fRects; |
| + } |
| + } |
| + |
| + SkScalar fSigma; |
| + unsigned fRectCount; |
| + SkRect** fRects; |
| + SkMask* fMask; |
| + }; |
| + |
| + static bool getBlurMaskRecord(SkScalar sigma, |
| + unsigned rectCount, |
| + const SkRect rects[], |
| + SkMask** mask); |
| + static bool addBlurMaskRecord(BlurMaskRecord* blurMaskRecord); |
| + static void clearBlurMaskRecordList(); |
| + static unsigned getBlurMaskRecordsMemoryUsage() { return fCachedBlurMaskImageMemorySize; } |
| + static void setBlurMaskRecordsLimit(unsigned, unsigned); |
| + |
| SK_TO_STRING_OVERRIDE() |
| SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurMaskFilterImpl) |
| @@ -107,11 +152,90 @@ private: |
| return SkMinScalar(xformedSigma, kMAX_BLUR_SIGMA); |
| } |
| + typedef std::list<BlurMaskRecord*> BlurMaskRecordList; |
| + static BlurMaskRecordList fCachedBlurMaskRecordList; |
| + static unsigned fCachedBlurMaskImageMemorySize; |
| + static unsigned fMaxBlurMaskListSize; |
| + static unsigned fMaxImageMemorySize; |
| + |
| typedef SkMaskFilter INHERITED; |
| }; |
| const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128); |
| +SkBlurMaskFilterImpl::BlurMaskRecordList SkBlurMaskFilterImpl::fCachedBlurMaskRecordList; |
|
reveman
2014/05/16 18:49:16
I'm failing to see how the use of this is thread s
junj
2014/05/19 12:54:49
Yes, I should add a mutex to make it thread-safe.
|
| +unsigned SkBlurMaskFilterImpl::fCachedBlurMaskImageMemorySize = 0; |
| +unsigned SkBlurMaskFilterImpl::fMaxBlurMaskListSize = 50; |
| +unsigned SkBlurMaskFilterImpl::fMaxImageMemorySize = 2 * 1024 * 1024; |
|
reveman
2014/05/16 18:49:16
Please allow SkDiscardableMemory to be used instea
junj
2014/05/19 12:54:49
I have had a look at the interface of SkScaledImag
reveman
2014/05/19 14:09:37
Yes, I'm hoping to enable it this week and remove
|
| + |
| +bool SkBlurMaskFilterImpl::getBlurMaskRecord(SkScalar sigma, |
| + unsigned rectCount, |
| + const SkRect rects[], |
| + SkMask** mask) { |
| + 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 (int 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; |
| + 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; |
| + } |
| + if (found) { |
| + *mask = cachedBlurMaskRecord->fMask; |
| + return true; |
| + } |
| + } |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +bool SkBlurMaskFilterImpl::addBlurMaskRecord(BlurMaskRecord* blurMaskRecord) { |
| + while (fCachedBlurMaskRecordList.size() >= fMaxBlurMaskListSize |
| + || fCachedBlurMaskImageMemorySize >= fMaxImageMemorySize) { |
| + BlurMaskRecord* cachedBlurMaskRecord = fCachedBlurMaskRecordList.front(); |
| + fCachedBlurMaskRecordList.pop_front(); |
| + if (cachedBlurMaskRecord) { |
| + fCachedBlurMaskImageMemorySize -= cachedBlurMaskRecord->fMask->computeImageSize(); |
| + delete cachedBlurMaskRecord; |
| + cachedBlurMaskRecord = NULL; |
| + } |
| + } |
| + fCachedBlurMaskRecordList.push_back(blurMaskRecord); |
| + fCachedBlurMaskImageMemorySize += blurMaskRecord->fMask->computeImageSize(); |
| + return true; |
| +} |
| + |
| +void SkBlurMaskFilterImpl::clearBlurMaskRecordList() { |
| + while (!fCachedBlurMaskRecordList.empty()) { |
| + BlurMaskRecord* cachedBlurMaskRecord = fCachedBlurMaskRecordList.front(); |
| + fCachedBlurMaskRecordList.pop_front(); |
| + if (cachedBlurMaskRecord) { |
| + delete cachedBlurMaskRecord; |
| + cachedBlurMaskRecord = NULL; |
| + } |
| + } |
| + fCachedBlurMaskImageMemorySize = 0; |
| +} |
| + |
| +void SkBlurMaskFilterImpl::setBlurMaskRecordsLimit(unsigned listSize, unsigned memSize) { |
| + fMaxBlurMaskListSize = listSize; |
| + fMaxImageMemorySize = memSize; |
| +} |
| + |
| SkMaskFilter* SkBlurMaskFilter::Create(SkBlurStyle style, SkScalar sigma, uint32_t flags) { |
| if (!SkScalarIsFinite(sigma) || sigma <= 0) { |
| return NULL; |
| @@ -380,6 +504,18 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma |
| radii[SkRRect::kLowerLeft_Corner] = LL; |
| smallRR.setRectRadii(smallR, radii); |
| + SkScalar sigma = this->computeXformedSigma(matrix); |
| + SkMask* cachedBlurMask = NULL; |
| + SkRect rects[1]; |
| + rects[0] = rrect.rect(); |
| + if (getBlurMaskRecord(sigma, 1, rects, &cachedBlurMask)) { |
| + patch->fMask = *cachedBlurMask; |
| + patch->fOuterRect = dstM.fBounds; |
| + patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; |
| + patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; |
| + return kTrue_FilterReturn; |
| + } |
| + |
| bool analyticBlurWorked = false; |
| if (c_analyticBlurRRect) { |
| analyticBlurWorked = |
| @@ -403,6 +539,17 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma |
| patch->fOuterRect = dstM.fBounds; |
| patch->fCenter.fX = SkScalarCeilToInt(leftUnstretched) + 1; |
| patch->fCenter.fY = SkScalarCeilToInt(topUnstretched) + 1; |
| + if (!cachedBlurMask) { |
| + SkMask* tempMask = new SkMask; |
| + *tempMask = patch->fMask; |
| + 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; |
| } |
| @@ -482,6 +629,15 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
| smallH + (innerIR.top() - srcM.fBounds.top())); |
| } |
| + SkScalar sigma = this->computeXformedSigma(matrix); |
| + SkMask* cachedBlurMask = NULL; |
| + if (getBlurMaskRecord(sigma, count, rects, &cachedBlurMask)) { |
| + patch->fMask = *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; |
| @@ -510,7 +666,6 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
| if (!draw_rects_into_mask(smallR, count, &srcM)) { |
| return kFalse_FilterReturn; |
| } |
| - |
| SkAutoMaskFreeImage amf(srcM.fImage); |
| if (!this->filterMask(&patch->fMask, srcM, matrix, &margin)) { |
| @@ -525,6 +680,20 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count, |
| patch->fMask.fBounds.offsetTo(0, 0); |
| patch->fOuterRect = dstM.fBounds; |
| patch->fCenter = center; |
| + |
| + if (!cachedBlurMask) { |
| + SkMask* tempMask = new SkMask; |
| + *tempMask = patch->fMask; |
| + 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; |
| } |