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
This commit is contained in:
parent
3e8012e74f
commit
04a44d0fd4
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Benchmark.h"
|
#include "Benchmark.h"
|
||||||
|
#include "Resources.h"
|
||||||
#include "SkBlurImageFilter.h"
|
#include "SkBlurImageFilter.h"
|
||||||
#include "SkDisplacementMapEffect.h"
|
#include "SkDisplacementMapEffect.h"
|
||||||
#include "SkCanvas.h"
|
#include "SkCanvas.h"
|
||||||
@ -45,6 +46,45 @@ private:
|
|||||||
typedef Benchmark INHERITED;
|
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.
|
// Exercise a blur filter connected to both inputs of an SkDisplacementMapEffect.
|
||||||
|
|
||||||
class ImageFilterDisplacedBlur : public Benchmark {
|
class ImageFilterDisplacedBlur : public Benchmark {
|
||||||
@ -77,4 +117,5 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DEF_BENCH(return new ImageFilterDAGBench;)
|
DEF_BENCH(return new ImageFilterDAGBench;)
|
||||||
|
DEF_BENCH(return new ImageMakeWithFilterDAGBench;)
|
||||||
DEF_BENCH(return new ImageFilterDisplacedBlur;)
|
DEF_BENCH(return new ImageFilterDisplacedBlur;)
|
||||||
|
@ -48,6 +48,8 @@ struct SkImageFilterCacheKey {
|
|||||||
// (result, offset).
|
// (result, offset).
|
||||||
class SkImageFilterCache : public SkRefCnt {
|
class SkImageFilterCache : public SkRefCnt {
|
||||||
public:
|
public:
|
||||||
|
enum { kDefaultTransientSize = 32 * 1024 * 1024 };
|
||||||
|
|
||||||
virtual ~SkImageFilterCache() {}
|
virtual ~SkImageFilterCache() {}
|
||||||
static SkImageFilterCache* Create(size_t maxBytes);
|
static SkImageFilterCache* Create(size_t maxBytes);
|
||||||
static SkImageFilterCache* Get();
|
static SkImageFilterCache* Get();
|
||||||
|
@ -53,8 +53,6 @@
|
|||||||
#define ASSERT_SINGLE_OWNER \
|
#define ASSERT_SINGLE_OWNER \
|
||||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->debugSingleOwner());)
|
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->debugSingleOwner());)
|
||||||
|
|
||||||
enum { kDefaultImageFilterCacheSize = 32 * 1024 * 1024 };
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
extern bool (*gShouldDrawProc)();
|
extern bool (*gShouldDrawProc)();
|
||||||
#define CHECK_SHOULD_DRAW(draw) \
|
#define CHECK_SHOULD_DRAW(draw) \
|
||||||
@ -1818,7 +1816,7 @@ SkImageFilterCache* SkGpuDevice::getImageFilterCache() {
|
|||||||
ASSERT_SINGLE_OWNER
|
ASSERT_SINGLE_OWNER
|
||||||
// We always return a transient cache, so it is freed after each
|
// We always return a transient cache, so it is freed after each
|
||||||
// filter traversal.
|
// filter traversal.
|
||||||
return SkImageFilterCache::Create(kDefaultImageFilterCacheSize);
|
return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "SkData.h"
|
#include "SkData.h"
|
||||||
#include "SkImageEncoder.h"
|
#include "SkImageEncoder.h"
|
||||||
#include "SkImageFilter.h"
|
#include "SkImageFilter.h"
|
||||||
|
#include "SkImageFilterCache.h"
|
||||||
#include "SkImageGenerator.h"
|
#include "SkImageGenerator.h"
|
||||||
#include "SkImagePriv.h"
|
#include "SkImagePriv.h"
|
||||||
#include "SkImageShader.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,
|
sk_sp<SkImage> SkImage::makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,
|
||||||
const SkIRect& clipBounds, SkIRect* outSubset,
|
const SkIRect& clipBounds, SkIRect* outSubset,
|
||||||
SkIPoint* offset) const {
|
SkIPoint* offset) const {
|
||||||
if (!filter || !outSubset || !offset || !this->bounds().contains(subset)) {
|
if (!filter || !outSubset || !offset || !this->bounds().contains(subset)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
sk_sp<SkSpecialImage> srcSpecialImage = SkSpecialImage::MakeFromImage(
|
sk_sp<SkSpecialImage> srcSpecialImage = SkSpecialImage::MakeFromImage(
|
||||||
subset, sk_ref_sp(const_cast<SkImage*>(this)));
|
subset, sk_ref_sp(const_cast<SkImage*>(this)));
|
||||||
if (!srcSpecialImage) {
|
if (!srcSpecialImage) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: build a cache here.
|
SkAutoTUnref<SkImageFilterCache> cache(
|
||||||
SkImageFilter::Context context(SkMatrix::I(), clipBounds, nullptr);
|
SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize));
|
||||||
sk_sp<SkSpecialImage> result =
|
SkImageFilter::Context context(SkMatrix::I(), clipBounds, cache.get());
|
||||||
filter->filterImage(srcSpecialImage.get(), context, offset);
|
sk_sp<SkSpecialImage> result =
|
||||||
|
filter->filterImage(srcSpecialImage.get(), context, offset);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkIRect fullSize = SkIRect::MakeWH(result->width(), result->height());
|
SkIRect fullSize = SkIRect::MakeWH(result->width(), result->height());
|
||||||
#if SK_SUPPORT_GPU
|
#if SK_SUPPORT_GPU
|
||||||
if (result->isTextureBacked()) {
|
if (result->isTextureBacked()) {
|
||||||
GrContext* context = result->getContext();
|
GrContext* context = result->getContext();
|
||||||
sk_sp<GrTexture> texture = result->asTextureRef(context);
|
sk_sp<GrTexture> texture = result->asTextureRef(context);
|
||||||
fullSize = SkIRect::MakeWH(texture->width(), texture->height());
|
fullSize = SkIRect::MakeWH(texture->width(), texture->height());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
*outSubset = SkIRect::MakeWH(result->width(), result->height());
|
*outSubset = SkIRect::MakeWH(result->width(), result->height());
|
||||||
if (!outSubset->intersect(clipBounds.makeOffset(-offset->x(), -offset->y()))) {
|
if (!outSubset->intersect(clipBounds.makeOffset(-offset->x(), -offset->y()))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
offset->fX += outSubset->x();
|
offset->fX += outSubset->x();
|
||||||
offset->fY += outSubset->y();
|
offset->fY += outSubset->y();
|
||||||
// This isn't really a "tight" subset, but includes any texture padding.
|
// This isn't really a "tight" subset, but includes any texture padding.
|
||||||
return result->makeTightSubset(fullSize);
|
return result->makeTightSubset(fullSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkImage::isLazyGenerated() const {
|
bool SkImage::isLazyGenerated() const {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "SkDraw.h"
|
#include "SkDraw.h"
|
||||||
#include "SkDrawFilter.h"
|
#include "SkDrawFilter.h"
|
||||||
#include "SkGlyphCache.h"
|
#include "SkGlyphCache.h"
|
||||||
|
#include "SkImageFilterCache.h"
|
||||||
#include "SkMakeUnique.h"
|
#include "SkMakeUnique.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
#include "SkPathEffect.h"
|
#include "SkPathEffect.h"
|
||||||
@ -2286,8 +2287,8 @@ void SkPDFDevice::drawSpecial(const SkDraw& draw, SkSpecialImage* srcImg, int x,
|
|||||||
SkMatrix matrix = *draw.fMatrix;
|
SkMatrix matrix = *draw.fMatrix;
|
||||||
matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
|
matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y));
|
||||||
const SkIRect clipBounds = draw.fRC->getBounds().makeOffset(-x, -y);
|
const SkIRect clipBounds = draw.fRC->getBounds().makeOffset(-x, -y);
|
||||||
// SkAutoTUnref<SkImageFilterCache> cache(this->getImageFilterCache());
|
SkAutoTUnref<SkImageFilterCache> cache(this->getImageFilterCache());
|
||||||
SkImageFilter::Context ctx(matrix, clipBounds, nullptr /*cache.get()*/);
|
SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
|
||||||
|
|
||||||
sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset));
|
sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset));
|
||||||
if (resultImg) {
|
if (resultImg) {
|
||||||
@ -2316,3 +2317,9 @@ sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) {
|
|||||||
sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() {
|
sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkImageFilterCache* SkPDFDevice::getImageFilterCache() {
|
||||||
|
// We always return a transient cache, so it is freed after each
|
||||||
|
// filter traversal.
|
||||||
|
return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize);
|
||||||
|
}
|
||||||
|
@ -181,6 +181,7 @@ protected:
|
|||||||
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
|
sk_sp<SkSpecialImage> makeSpecial(const SkBitmap&) override;
|
||||||
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
|
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
|
||||||
sk_sp<SkSpecialImage> snapSpecial() override;
|
sk_sp<SkSpecialImage> snapSpecial() override;
|
||||||
|
SkImageFilterCache* getImageFilterCache() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct RectWithData {
|
struct RectWithData {
|
||||||
|
Loading…
Reference in New Issue
Block a user