From 718a5adc6da857f08578cae434bcf81ea3f5aa3d Mon Sep 17 00:00:00 2001 From: robertphillips Date: Tue, 19 Apr 2016 10:21:02 -0700 Subject: [PATCH] Switch SkColorFilterImageFilter over to new onFilterImage interface (again) Back when this was originally reverted I was able to easily repro the perf regression locally. At ToT Skia/Chrome I can no longer repro the perf regression with this CL (in fact there is a modest perf improvement). I propose landing this and then watching the Chromium perf bots. BUG=602300,598028 TBR=reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1901513002 Review URL: https://codereview.chromium.org/1901513002 --- include/effects/SkColorFilterImageFilter.h | 4 +- src/effects/SkColorFilterImageFilter.cpp | 62 ++++++++++++---------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/include/effects/SkColorFilterImageFilter.h b/include/effects/SkColorFilterImageFilter.h index 2aa04d1644..5ed051c0de 100644 --- a/include/effects/SkColorFilterImageFilter.h +++ b/include/effects/SkColorFilterImageFilter.h @@ -33,8 +33,8 @@ public: protected: void flatten(SkWriteBuffer&) const override; - bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, SkBitmap* result, - SkIPoint* loc) const override; + sk_sp onFilterImage(SkSpecialImage* source, const Context&, + SkIPoint* offset) const override; bool onIsColorFilterNode(SkColorFilter**) const override; bool affectsTransparentBlack() const override; diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp index 63dded6a18..8d412cc2f5 100644 --- a/src/effects/SkColorFilterImageFilter.cpp +++ b/src/effects/SkColorFilterImageFilter.cpp @@ -9,8 +9,9 @@ #include "SkCanvas.h" #include "SkColorFilter.h" -#include "SkDevice.h" #include "SkReadBuffer.h" +#include "SkSpecialImage.h" +#include "SkSpecialSurface.h" #include "SkWriteBuffer.h" sk_sp SkColorFilterImageFilter::Make(sk_sp cf, @@ -56,55 +57,62 @@ void SkColorFilterImageFilter::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(fColorFilter.get()); } -bool SkColorFilterImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& source, - const Context& ctx, - SkBitmap* result, - SkIPoint* offset) const { - SkBitmap src = source; - SkIPoint srcOffset = SkIPoint::Make(0, 0); - bool inputResult = this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset); - - SkIRect srcBounds; +sk_sp SkColorFilterImageFilter::onFilterImage(SkSpecialImage* source, + const Context& ctx, + SkIPoint* offset) const { + SkIPoint inputOffset = SkIPoint::Make(0, 0); + sk_sp input(this->filterInput(0, source, ctx, &inputOffset)); + SkIRect inputBounds; if (fColorFilter->affectsTransparentBlack()) { // If the color filter affects transparent black, the bounds are the entire clip. - srcBounds = ctx.clipBounds(); - } else if (!inputResult) { - return false; + inputBounds = ctx.clipBounds(); + } else if (!input) { + return nullptr; } else { - srcBounds = src.bounds(); - srcBounds.offset(srcOffset); + inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(), + input->width(), input->height()); } SkIRect bounds; - if (!this->applyCropRect(ctx, srcBounds, &bounds)) { - return false; + if (!this->applyCropRect(ctx, inputBounds, &bounds)) { + return nullptr; } - SkAutoTUnref device(proxy->createDevice(bounds.width(), bounds.height())); - if (nullptr == device.get()) { - return false; + SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), kPremul_SkAlphaType); + sk_sp surf(source->makeSurface(info)); + if (!surf) { + return nullptr; } - SkCanvas canvas(device.get()); + + SkCanvas* canvas = surf->getCanvas(); + SkASSERT(canvas); SkPaint paint; + paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setColorFilter(fColorFilter); // TODO: it may not be necessary to clear or drawPaint inside the input bounds // (see skbug.com/5075) if (fColorFilter->affectsTransparentBlack()) { - // The subsequent drawBitmap call may not fill the entire canvas. For filters which + // The subsequent input->draw() call may not fill the entire canvas. For filters which // affect transparent black, ensure that the filter is applied everywhere. - canvas.drawPaint(paint); + canvas->drawPaint(paint); + } else { + canvas->clear(0x0); + } + + if (input) { + input->draw(canvas, + SkIntToScalar(inputOffset.fX - bounds.fLeft), + SkIntToScalar(inputOffset.fY - bounds.fTop), + &paint); } - canvas.drawBitmap(src, SkIntToScalar(srcOffset.fX - bounds.fLeft), - SkIntToScalar(srcOffset.fY - bounds.fTop), &paint); - *result = device.get()->accessBitmap(false); offset->fX = bounds.fLeft; offset->fY = bounds.fTop; - return true; + return surf->makeImageSnapshot(); } bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const {