diff options
author | brianosman <brianosman@google.com> | 2016-09-21 09:46:57 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-09-21 09:46:57 -0700 |
commit | 04a44d0fd45f5596c716e99e7a3bbcc03db0e05a (patch) | |
tree | 2dbd1b8dc623cdf1a72d4ed0e2f90851265be145 | |
parent | 3e8012e74f70bf49427a7422f9e5996c9882d4f3 (diff) |
Add a transient image filter cache to SkImage::makeWithFilter & PDF
Added a bench for makeWithFilter (~23 ms -> ~6 ms median locally).
Also fixed indentation.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2360663002
Review-Url: https://codereview.chromium.org/2360663002
-rw-r--r-- | bench/ImageFilterDAGBench.cpp | 41 | ||||
-rw-r--r-- | src/core/SkImageFilterCache.h | 2 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 4 | ||||
-rw-r--r-- | src/image/SkImage.cpp | 66 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 11 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 1 |
6 files changed, 88 insertions, 37 deletions
diff --git a/bench/ImageFilterDAGBench.cpp b/bench/ImageFilterDAGBench.cpp index 776ee787fd..60bcb62dd8 100644 --- a/bench/ImageFilterDAGBench.cpp +++ b/bench/ImageFilterDAGBench.cpp @@ -6,6 +6,7 @@ */ #include "Benchmark.h" +#include "Resources.h" #include "SkBlurImageFilter.h" #include "SkDisplacementMapEffect.h" #include "SkCanvas.h" @@ -45,6 +46,45 @@ private: typedef Benchmark INHERITED; }; +class ImageMakeWithFilterDAGBench : public Benchmark { +public: + ImageMakeWithFilterDAGBench() {} + +protected: + const char* onGetName() override { + return "image_make_with_filter_dag"; + } + + void onDelayedSetup() override { + fImage = GetResourceAsImage("mandrill_512.png"); + } + + void onDraw(int loops, SkCanvas* canvas) override { + SkIRect subset = SkIRect::MakeSize(fImage->dimensions()); + SkIPoint offset = SkIPoint::Make(0, 0); + SkIRect discardSubset; + sk_sp<SkImage> image = fImage; + + for (int j = 0; j < loops; j++) { + sk_sp<SkImageFilter> blur(SkBlurImageFilter::Make(20.0f, 20.0f, nullptr)); + sk_sp<SkImageFilter> inputs[kNumInputs]; + for (int i = 0; i < kNumInputs; ++i) { + inputs[i] = blur; + } + sk_sp<SkImageFilter> mergeFilter = SkMergeImageFilter::Make(inputs, kNumInputs); + image = image->makeWithFilter(mergeFilter.get(), subset, subset, &discardSubset, + &offset); + SkASSERT(image && image->dimensions() == fImage->dimensions()); + } + } + +private: + static const int kNumInputs = 5; + sk_sp<SkImage> fImage; + + typedef Benchmark INHERITED; +}; + // Exercise a blur filter connected to both inputs of an SkDisplacementMapEffect. class ImageFilterDisplacedBlur : public Benchmark { @@ -77,4 +117,5 @@ private: }; DEF_BENCH(return new ImageFilterDAGBench;) +DEF_BENCH(return new ImageMakeWithFilterDAGBench;) DEF_BENCH(return new ImageFilterDisplacedBlur;) diff --git a/src/core/SkImageFilterCache.h b/src/core/SkImageFilterCache.h index 25079e194f..a65357f69c 100644 --- a/src/core/SkImageFilterCache.h +++ b/src/core/SkImageFilterCache.h @@ -48,6 +48,8 @@ struct SkImageFilterCacheKey { // (result, offset). class SkImageFilterCache : public SkRefCnt { public: + enum { kDefaultTransientSize = 32 * 1024 * 1024 }; + virtual ~SkImageFilterCache() {} static SkImageFilterCache* Create(size_t maxBytes); static SkImageFilterCache* Get(); diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 9ee71bc708..79b358cc0c 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -53,8 +53,6 @@ #define ASSERT_SINGLE_OWNER \ SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->debugSingleOwner());) -enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 }; - #if 0 extern bool (*gShouldDrawProc)(); #define CHECK_SHOULD_DRAW(draw) \ @@ -1818,7 +1816,7 @@ SkImageFilterCache* SkGpuDevice::getImageFilterCache() { ASSERT_SINGLE_OWNER // We always return a transient cache, so it is freed after each // filter traversal. - return SkImageFilterCache::Create(kDefaultImageFilterCacheSize); + return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize); } #endif diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp index b8a321cea1..6e65050a65 100644 --- a/src/image/SkImage.cpp +++ b/src/image/SkImage.cpp @@ -11,6 +11,7 @@ #include "SkData.h" #include "SkImageEncoder.h" #include "SkImageFilter.h" +#include "SkImageFilterCache.h" #include "SkImageGenerator.h" #include "SkImagePriv.h" #include "SkImageShader.h" @@ -334,40 +335,41 @@ sk_sp<SkImage> SkImage::MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& sk_sp<SkImage> SkImage::makeWithFilter(const SkImageFilter* filter, const SkIRect& subset, const SkIRect& clipBounds, SkIRect* outSubset, SkIPoint* offset) const { - if (!filter || !outSubset || !offset || !this->bounds().contains(subset)) { - return nullptr; - } - sk_sp<SkSpecialImage> srcSpecialImage = SkSpecialImage::MakeFromImage( - subset, sk_ref_sp(const_cast<SkImage*>(this))); - if (!srcSpecialImage) { - return nullptr; - } - - // FIXME: build a cache here. - SkImageFilter::Context context(SkMatrix::I(), clipBounds, nullptr); - sk_sp<SkSpecialImage> result = - filter->filterImage(srcSpecialImage.get(), context, offset); - - if (!result) { - return nullptr; - } - - SkIRect fullSize = SkIRect::MakeWH(result->width(), result->height()); + if (!filter || !outSubset || !offset || !this->bounds().contains(subset)) { + return nullptr; + } + sk_sp<SkSpecialImage> srcSpecialImage = SkSpecialImage::MakeFromImage( + subset, sk_ref_sp(const_cast<SkImage*>(this))); + if (!srcSpecialImage) { + return nullptr; + } + + SkAutoTUnref<SkImageFilterCache> cache( + SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize)); + SkImageFilter::Context context(SkMatrix::I(), clipBounds, cache.get()); + sk_sp<SkSpecialImage> result = + filter->filterImage(srcSpecialImage.get(), context, offset); + + if (!result) { + return nullptr; + } + + SkIRect fullSize = SkIRect::MakeWH(result->width(), result->height()); #if SK_SUPPORT_GPU - if (result->isTextureBacked()) { - GrContext* context = result->getContext(); - sk_sp<GrTexture> texture = result->asTextureRef(context); - fullSize = SkIRect::MakeWH(texture->width(), texture->height()); - } + if (result->isTextureBacked()) { + GrContext* context = result->getContext(); + sk_sp<GrTexture> texture = result->asTextureRef(context); + fullSize = SkIRect::MakeWH(texture->width(), texture->height()); + } #endif - *outSubset = SkIRect::MakeWH(result->width(), result->height()); - if (!outSubset->intersect(clipBounds.makeOffset(-offset->x(), -offset->y()))) { - return nullptr; - } - offset->fX += outSubset->x(); - offset->fY += outSubset->y(); - // This isn't really a "tight" subset, but includes any texture padding. - return result->makeTightSubset(fullSize); + *outSubset = SkIRect::MakeWH(result->width(), result->height()); + if (!outSubset->intersect(clipBounds.makeOffset(-offset->x(), -offset->y()))) { + return nullptr; + } + offset->fX += outSubset->x(); + offset->fY += outSubset->y(); + // This isn't really a "tight" subset, but includes any texture padding. + return result->makeTightSubset(fullSize); } bool SkImage::isLazyGenerated() const { diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 5299d70d0e..e79c915283 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -16,6 +16,7 @@ #include "SkDraw.h" #include "SkDrawFilter.h" #include "SkGlyphCache.h" +#include "SkImageFilterCache.h" #include "SkMakeUnique.h" #include "SkPath.h" #include "SkPathEffect.h" @@ -2286,8 +2287,8 @@ void SkPDFDevice::drawSpecial(const SkDraw& draw, SkSpecialImage* srcImg, int x, SkMatrix matrix = *draw.fMatrix; matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); const SkIRect clipBounds = draw.fRC->getBounds().makeOffset(-x, -y); -// SkAutoTUnref<SkImageFilterCache> cache(this->getImageFilterCache()); - SkImageFilter::Context ctx(matrix, clipBounds, nullptr /*cache.get()*/); + SkAutoTUnref<SkImageFilterCache> cache(this->getImageFilterCache()); + SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset)); if (resultImg) { @@ -2316,3 +2317,9 @@ sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) { sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { return nullptr; } + +SkImageFilterCache* SkPDFDevice::getImageFilterCache() { + // We always return a transient cache, so it is freed after each + // filter traversal. + return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize); +} diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index dba5d06818..db6f9b2b19 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -181,6 +181,7 @@ protected: sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override; sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override; sk_sp<SkSpecialImage> snapSpecial() override; + SkImageFilterCache* getImageFilterCache() override; private: struct RectWithData { |