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); |