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
This commit is contained in:
parent
281ecc27ee
commit
5a5b4e900e
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "SkGpuBlurUtils.h"
|
||||
#include "SkReadBuffer.h"
|
||||
#include "SkWriteBuffer.h"
|
||||
#include "SkMaskCache.h"
|
||||
#include "SkMaskFilter.h"
|
||||
#include "SkRRect.h"
|
||||
#include "SkRTConf.h"
|
||||
@ -260,58 +261,6 @@ 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
|
||||
@ -420,7 +369,7 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
|
||||
smallRR.setRectRadii(smallR, radii);
|
||||
|
||||
const SkScalar sigma = this->computeXformedSigma(matrix);
|
||||
if (!find_cached_rrect(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR)) {
|
||||
if (!SkMaskCache::FindAndCopy(sigma, fBlurStyle, this->getQuality(), smallRR, &patch->fMask)) {
|
||||
bool analyticBlurWorked = false;
|
||||
if (c_analyticBlurRRect) {
|
||||
analyticBlurWorked =
|
||||
@ -439,7 +388,7 @@ SkBlurMaskFilterImpl::filterRRectToNine(const SkRRect& rrect, const SkMatrix& ma
|
||||
return kFalse_FilterReturn;
|
||||
}
|
||||
}
|
||||
add_cached_rrect(patch->fMask, sigma, fBlurStyle, this->getQuality(), smallRR);
|
||||
SkMaskCache::AddAndCopy(sigma, fBlurStyle, this->getQuality(), smallRR, patch->fMask);
|
||||
}
|
||||
|
||||
patch->fMask.fBounds.offsetTo(0, 0);
|
||||
@ -550,7 +499,8 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
|
||||
}
|
||||
|
||||
const SkScalar sigma = this->computeXformedSigma(matrix);
|
||||
if (!find_cached_rects(&patch->fMask, sigma, fBlurStyle, this->getQuality(), smallR, count)) {
|
||||
if (!SkMaskCache::FindAndCopy(sigma, fBlurStyle, this->getQuality(),
|
||||
smallR, count, &patch->fMask)) {
|
||||
if (count > 1 || !c_analyticBlurNinepatch) {
|
||||
if (!draw_rects_into_mask(smallR, count, &srcM)) {
|
||||
return kFalse_FilterReturn;
|
||||
@ -567,7 +517,7 @@ SkBlurMaskFilterImpl::filterRectsToNine(const SkRect rects[], int count,
|
||||
return kFalse_FilterReturn;
|
||||
}
|
||||
}
|
||||
add_cached_rects(patch->fMask, sigma, fBlurStyle, this->getQuality(), smallR, count);
|
||||
SkMaskCache::AddAndCopy(sigma, fBlurStyle, this->getQuality(), smallR, count, patch->fMask);
|
||||
}
|
||||
patch->fMask.fBounds.offsetTo(0, 0);
|
||||
patch->fOuterRect = dstM.fBounds;
|
||||
|
Loading…
Reference in New Issue
Block a user