aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar qiankun.miao <qiankun.miao@intel.com>2015-01-07 18:37:47 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-01-07 18:37:47 -0800
commit5a5b4e900ee69540fc35952882a323c63d6d0db9 (patch)
treead2e0f3642f3feeecdb0b8eb37a2b1b6af398635 /src/core
parent281ecc27ee93f34485d49af8de39a73656a87c9c (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.cpp50
-rw-r--r--src/core/SkMaskCache.h19
-rw-r--r--src/core/SkMaskFilter.cpp37
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