diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h index 930403f8da..0a0099f3e2 100644 --- a/include/core/SkXfermode.h +++ b/include/core/SkXfermode.h @@ -13,6 +13,8 @@ #include "SkFlattenable.h" #include "SkColor.h" +class GrContext; +class GrEffectRef; class SkString; /** \class SkXfermode @@ -74,7 +76,7 @@ public: /** * The same as calling xfermode->asCoeff(..), except that this also checks - * if the xfermode is NULL, and if so, treats its as kSrcOver_Mode. + * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode. */ static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst); @@ -136,7 +138,7 @@ public: /** * The same as calling xfermode->asMode(mode), except that this also checks - * if the xfermode is NULL, and if so, treats its as kSrcOver_Mode. + * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode. */ static bool AsMode(const SkXfermode*, Mode* mode); @@ -181,6 +183,22 @@ public: return AsMode(xfer, mode); } + /** A subclass may implement this factory function to work with the GPU backend. It is legal + to call this with all but the context param NULL to simply test the return value. effect, + src, and dst must all be NULL or all non-NULL. If effect is non-NULL then the xfermode may + optionally allocate an effect to return and the caller as *effect. The caller will install + it and own a ref to it. Since the xfermode may or may not assign *effect, the caller should + set *effect to NULL beforehand. If the function returns true then the src and dst coeffs + will be applied to the draw regardless of whether an effect was returned. + */ + virtual bool asNewEffect(GrContext*, GrEffectRef** effect, Coeff* src, Coeff* dst) const; + + /** + * The same as calling xfermode->asNewEffect(...), except that this also checks if the xfermode + * is NULL, and if so, treats it as kSrcOver_Mode. + */ + static bool AsNewEffect(SkXfermode*, GrContext*, GrEffectRef** effect, Coeff* src, Coeff* dst); + SkDEVCODE(virtual void toString(SkString* str) const = 0;) SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() protected: diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp index de18c26fd1..09710a393d 100644 --- a/src/core/SkXfermode.cpp +++ b/src/core/SkXfermode.cpp @@ -680,6 +680,22 @@ bool SkXfermode::asMode(Mode* mode) const { return false; } +bool SkXfermode::asNewEffect(GrContext*, GrEffectRef**, Coeff*, Coeff*) const { + return false; +} + +bool SkXfermode::AsNewEffect(SkXfermode* xfermode, + GrContext* context, + GrEffectRef** effect, + Coeff* src, + Coeff* dst) { + if (NULL == xfermode) { + return ModeAsCoeff(kSrcOver_Mode, src, dst); + } else { + return xfermode->asNewEffect(context, effect, src, dst); + } +} + SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{ // no-op. subclasses should override this return dst; @@ -958,6 +974,10 @@ public: return true; } + virtual bool asNewEffect(GrContext*, GrEffectRef**, Coeff* src, Coeff* dst) const SK_OVERRIDE { + return this->asCoeff(src, dst); + } + SK_DEVELOPER_TO_STRING() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 77c4bd1115..ad65d17214 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -484,13 +484,15 @@ inline bool skPaint2GrPaintNoShader(SkGpuDevice* dev, SkXfermode::Coeff dm = SkXfermode::kISA_Coeff; SkXfermode* mode = skPaint.getXfermode(); - if (mode) { - if (!mode->asCoeff(&sm, &dm)) { - //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");) + GrEffectRef* xferEffect; + if (SkXfermode::AsNewEffect(mode, dev->context(), &xferEffect, &sm, &dm)) { + // We're not ready for xfermode effects yet + GrAssert(NULL == xferEffect); + } else { + //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");) #if 0 - return false; + return false; #endif - } } grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));