| Index: src/effects/SkXfermodeImageFilter.cpp
|
| diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
|
| index 5f88240481b316c7e0c6b7d57f0a22ed815d004a..1e3544159e670b2055846c653990d01b5ad2d630 100644
|
| --- a/src/effects/SkXfermodeImageFilter.cpp
|
| +++ b/src/effects/SkXfermodeImageFilter.cpp
|
| @@ -25,12 +25,8 @@
|
| SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode,
|
| SkImageFilter* inputs[2],
|
| const CropRect* cropRect)
|
| - : INHERITED(2, inputs, cropRect), fMode(mode) {
|
| - SkSafeRef(fMode);
|
| -}
|
| -
|
| -SkXfermodeImageFilter::~SkXfermodeImageFilter() {
|
| - SkSafeUnref(fMode);
|
| + : INHERITED(2, inputs, cropRect)
|
| + , fMode(SkSafeRef(mode)) {
|
| }
|
|
|
| SkFlattenable* SkXfermodeImageFilter::CreateProc(SkReadBuffer& buffer) {
|
| @@ -45,10 +41,10 @@ void SkXfermodeImageFilter::flatten(SkWriteBuffer& buffer) const {
|
| }
|
|
|
| bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
|
| - const SkBitmap& src,
|
| - const Context& ctx,
|
| - SkBitmap* dst,
|
| - SkIPoint* offset) const {
|
| + const SkBitmap& src,
|
| + const Context& ctx,
|
| + SkBitmap* dst,
|
| + SkIPoint* offset) const {
|
| SkBitmap background = src, foreground = src;
|
| SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
|
| if (!this->filterInput(0, proxy, src, ctx, &background, &backgroundOffset)) {
|
| @@ -120,9 +116,11 @@ void SkXfermodeImageFilter::toString(SkString* str) const {
|
| #if SK_SUPPORT_GPU
|
|
|
| bool SkXfermodeImageFilter::canFilterImageGPU() const {
|
| - return fMode && fMode->asFragmentProcessor(nullptr, nullptr) && !cropRectIsSet();
|
| + return !this->cropRectIsSet();
|
| }
|
|
|
| +#include "SkXfermode_proccoeff.h"
|
| +
|
| bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
|
| const SkBitmap& src,
|
| const Context& ctx,
|
| @@ -153,8 +151,6 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
|
| return false;
|
| }
|
|
|
| - const GrFragmentProcessor* xferFP = nullptr;
|
| -
|
| GrSurfaceDesc desc;
|
| desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| desc.fWidth = bounds.width();
|
| @@ -176,18 +172,27 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
|
| GrTextureDomain::kDecal_Mode,
|
| GrTextureParams::kNone_FilterMode)
|
| );
|
| - if (!fMode || !fMode->asFragmentProcessor(&xferFP, bgFP)) {
|
| - // canFilterImageGPU() should've taken care of this
|
| - SkASSERT(false);
|
| - return false;
|
| +
|
| + // A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
|
| + SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get()));
|
| + if (!mode) {
|
| + // It would be awesome to use SkXfermode::Create here but it knows better
|
| + // than us and won't return a kSrcOver_Mode SkXfermode. That means we
|
| + // have to get one the hard way.
|
| + struct ProcCoeff rec;
|
| + rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
|
| + SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
|
| +
|
| + mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
|
| }
|
|
|
| + SkAutoTUnref<const GrFragmentProcessor> xferFP(mode->asFragmentProcessor(bgFP));
|
| +
|
| SkMatrix foregroundMatrix;
|
| foregroundMatrix.setIDiv(foregroundTex->width(), foregroundTex->height());
|
| foregroundMatrix.preTranslate(SkIntToScalar(-foregroundOffset.fX),
|
| SkIntToScalar(-foregroundOffset.fY));
|
|
|
| -
|
| SkAutoTUnref<const GrFragmentProcessor> foregroundFP(GrTextureDomainEffect::Create(
|
| foregroundTex, foregroundMatrix,
|
| GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
|
| @@ -196,8 +201,9 @@ bool SkXfermodeImageFilter::filterImageGPU(Proxy* proxy,
|
| );
|
|
|
| paint.addColorFragmentProcessor(foregroundFP.get());
|
| + // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
|
| if (xferFP) {
|
| - paint.addColorFragmentProcessor(xferFP)->unref();
|
| + paint.addColorFragmentProcessor(xferFP);
|
| }
|
| paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
|
|
|
|
|