diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/core/SkXfermode.h | 4 | ||||
-rw-r--r-- | include/gpu/GrPaint.h | 32 | ||||
-rw-r--r-- | include/gpu/GrXferProcessor.h | 111 | ||||
-rw-r--r-- | include/gpu/effects/GrPorterDuffXferProcessor.h | 50 |
4 files changed, 163 insertions, 34 deletions
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h index 35e9837483..05fd81152a 100644 --- a/include/core/SkXfermode.h +++ b/include/core/SkXfermode.h @@ -217,10 +217,10 @@ public: or a fragment processor. This helper calls the asCoeff(), asXPFactory(), and asFragmentProcessor() virtuals. If the xfermode is NULL, it is treated as kSrcOver_Mode. It is legal to call this with all params NULL to simply test the return value. - fp, xpf, src, and dst must all be NULL or all non-NULL. + fp and xpf must both be NULL or all non-NULL. */ static bool AsFragmentProcessorOrXPFactory(SkXfermode*, GrFragmentProcessor**, - GrXPFactory**, Coeff* src, Coeff* dst); + GrXPFactory**); SK_TO_STRING_PUREVIRT() SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h index f31830bb2b..49b95b8449 100644 --- a/include/gpu/GrPaint.h +++ b/include/gpu/GrPaint.h @@ -13,6 +13,7 @@ #include "GrColor.h" #include "GrFragmentStage.h" #include "GrXferProcessor.h" +#include "effects/GrPorterDuffXferProcessor.h" #include "SkXfermode.h" @@ -51,17 +52,6 @@ public: ~GrPaint() {} /** - * Sets the blending coefficients to use to blend the final primitive color with the - * destination color. Defaults to kOne for src and kZero for dst (i.e. src mode). - */ - void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { - fSrcBlendCoeff = srcCoeff; - fDstBlendCoeff = dstCoeff; - } - GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlendCoeff; } - GrBlendCoeff getDstBlendCoeff() const { return fDstBlendCoeff; } - - /** * The initial color of the drawn primitive. Defaults to solid white. */ void setColor(GrColor color) { fColor = color; } @@ -84,6 +74,14 @@ public: return xpFactory; } + void setPorterDuffXPFactory(SkXfermode::Mode mode) { + fXPFactory.reset(GrPorterDuffXPFactory::Create(mode)); + } + + void setPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) { + fXPFactory.reset(GrPorterDuffXPFactory::Create(src, dst)); + } + /** * Appends an additional color processor to the color computation. */ @@ -121,8 +119,6 @@ public: const GrFragmentStage& getCoverageStage(int s) const { return fCoverageStages[s]; } GrPaint& operator=(const GrPaint& paint) { - fSrcBlendCoeff = paint.fSrcBlendCoeff; - fDstBlendCoeff = paint.fDstBlendCoeff; fAntiAlias = paint.fAntiAlias; fDither = paint.fDither; @@ -140,7 +136,6 @@ public: * Resets the paint to the defaults. */ void reset() { - this->resetBlend(); this->resetOptions(); this->resetColor(); this->resetStages(); @@ -211,18 +206,11 @@ private: SkSTArray<4, GrFragmentStage> fColorStages; SkSTArray<2, GrFragmentStage> fCoverageStages; - GrBlendCoeff fSrcBlendCoeff; - GrBlendCoeff fDstBlendCoeff; bool fAntiAlias; bool fDither; GrColor fColor; - void resetBlend() { - fSrcBlendCoeff = kOne_GrBlendCoeff; - fDstBlendCoeff = kZero_GrBlendCoeff; - } - void resetOptions() { fAntiAlias = false; fDither = false; @@ -232,7 +220,7 @@ private: fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff); } - void resetStages(); + void resetStages(); }; #endif diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h index 10ecf54c75..b7d0bdd9fa 100644 --- a/include/gpu/GrXferProcessor.h +++ b/include/gpu/GrXferProcessor.h @@ -13,6 +13,8 @@ #include "GrTypes.h" #include "SkXfermode.h" +class GrProcOptInfo; + /** * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst * color. It does this by emitting fragment shader code and controlling the fixed-function blend @@ -27,11 +29,83 @@ * GrXPFactory once we have finalized the state of our draw. */ class GrXferProcessor : public GrFragmentProcessor { +public: + /** + * Optimizations for blending / coverage that an OptDrawState should apply to itself. + */ + enum OptFlags { + /** + * No optimizations needed + */ + kNone_Opt = 0, + /** + * The draw can be skipped completely. + */ + kSkipDraw_OptFlag = 0x1, + /** + * Clear color stages, remove color vertex attribs, and use input color + */ + kClearColorStages_OptFlag = 0x2, + /** + * Clear coverage stages, remove coverage vertex attribs, and use input coverage + */ + kClearCoverageStages_OptFlag = 0x4, + /** + * Set CoverageDrawing_StateBit + */ + kSetCoverageDrawing_OptFlag = 0x8, + }; + + GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags); + + /** + * Determines which optimizations (as described by the ptFlags above) can be performed by + * the draw with this xfer processor. If this function is called, the xfer processor may change + * its state to reflected the given blend optimizations. It will also set the output parameters, + * color and coverage, to specific values if it decides to remove all color or coverage stages. + * A caller who calls this function on a XP is required to honor the returned OptFlags + * and color/coverage values for its draw. + */ + // TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP. + // TODO: remove need for colorWriteDisabled once colorWriteDisabled is its own XP. + virtual OptFlags getOptimizations(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI, + bool isCoverageDrawing, + bool colorWriteDisabled, + bool doesStencilWrite, + GrColor* color, + uint8_t* coverage) = 0; + + struct BlendInfo { + GrBlendCoeff fSrcBlend; + GrBlendCoeff fDstBlend; + GrColor fBlendConstant; + }; + + virtual void getBlendInfo(BlendInfo* blendInfo) const = 0; + + /** Will this prceossor read the destination pixel value? */ + bool willReadDstColor() const { return fWillReadDstColor; } + +protected: + GrXferProcessor() : fWillReadDstColor(false) {} + + /** + * If the prceossor subclass will read the destination pixel value then it must call this + * function from its constructor. Otherwise, when its generated backend-specific prceossor class + * attempts to generate code that reads the destination pixel it will fail. + */ + void setWillReadDstColor() { fWillReadDstColor = true; } + private: + bool fWillReadDstColor; + typedef GrFragmentProcessor INHERITED; }; +GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags); + /** * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the @@ -45,7 +119,8 @@ private: */ class GrXPFactory : public SkRefCnt { public: - virtual const GrXferProcessor* createXferProcessor() const = 0; + virtual GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI) const = 0; /** * This function returns true if the GrXferProcessor generated from this factory will be able to @@ -54,6 +129,40 @@ public: */ virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0; + /** + * Depending on color blend mode requested it may or may not be possible to correctly blend with + * fractional pixel coverage generated by the fragment shader. + * + * This function considers the known color and coverage input into the xfer processor and + * certain state information (isCoverageDrawing and colorWriteDisabled) to determine whether + * coverage can be handled correctly. + */ + // TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP. + // TODO: remove need for colorWriteDisabled once colorWriteDisabled is its own XP. + virtual bool canApplyCoverage(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, + bool isCoverageDrawing, bool colorWriteDisabled) const = 0; + + /** + * This function returns true if the destination pixel values will be read for blending during + * draw. + */ + // TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP. + // TODO: remove need for colorWriteDisabled once only XP can read dst. + virtual bool willBlendWithDst(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, + bool isCoverageDrawing, bool colorWriteDisabled) const = 0; + + /** + * Determines whether multiplying the computed per-pixel color by the pixel's fractional + * coverage before the blend will give the correct final destination color. In general it + * will not as coverage is applied after blending. + */ + // TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP. + virtual bool canTweakAlphaForCoverage(bool isCoverageDrawing) const = 0; + + virtual bool getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI, GrColor* solidColor, + uint32_t* solidColorKnownComponents) const = 0; + bool isEqual(const GrXPFactory& that) const { if (this->classID() != that.classID()) { return false; diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h index 9ff3bea2ed..0ddfcdcd2a 100644 --- a/include/gpu/effects/GrPorterDuffXferProcessor.h +++ b/include/gpu/effects/GrPorterDuffXferProcessor.h @@ -17,8 +17,9 @@ class GrInvariantOutput; class GrPorterDuffXferProcessor : public GrXferProcessor { public: - static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend) { - return SkNEW_ARGS(GrPorterDuffXferProcessor, (srcBlend, dstBlend)); + static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, + GrColor constant = 0) { + return SkNEW_ARGS(GrPorterDuffXferProcessor, (srcBlend, dstBlend, constant)); } virtual ~GrPorterDuffXferProcessor(); @@ -30,12 +31,28 @@ public: virtual GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE; + virtual GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI, + bool isCoverageDrawing, + bool colorWriteDisabled, + bool doesStencilWrite, + GrColor* color, + uint8_t* coverage) SK_OVERRIDE; + + virtual void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE { + blendInfo->fSrcBlend = fSrcBlend; + blendInfo->fDstBlend = fDstBlend; + blendInfo->fBlendConstant = fBlendConstant; + } + private: - GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend); + GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColor constant); virtual bool onIsEqual(const GrFragmentProcessor& fpBase) const SK_OVERRIDE { const GrPorterDuffXferProcessor& xp = fpBase.cast<GrPorterDuffXferProcessor>(); - if (fSrcBlend != xp.fSrcBlend || fDstBlend != xp.fDstBlend) { + if (fSrcBlend != xp.fSrcBlend || + fDstBlend != xp.fDstBlend || + fBlendConstant != xp.fBlendConstant) { return false; } return true; @@ -45,7 +62,8 @@ private: GrBlendCoeff fSrcBlend; GrBlendCoeff fDstBlend; - + GrColor fBlendConstant; + typedef GrXferProcessor INHERITED; }; @@ -63,20 +81,34 @@ public: return SkNEW_ARGS(GrPorterDuffXPFactory, (src, dst)); } - const GrXferProcessor* createXferProcessor() const SK_OVERRIDE; + GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI) const SK_OVERRIDE; bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE; + bool canApplyCoverage(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, + bool isCoverageDrawing, bool colorWriteDisabled) const SK_OVERRIDE; + + bool willBlendWithDst(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, + bool isCoverageDrawing, bool colorWriteDisabled) const SK_OVERRIDE; + + bool canTweakAlphaForCoverage(bool isCoverageDrawing) const SK_OVERRIDE; + + bool getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI, + const GrProcOptInfo& coveragePOI, + GrColor* solidColor, + uint32_t* solidColorKnownComponents) const SK_OVERRIDE; + private: GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst); bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE { const GrPorterDuffXPFactory& xpf = xpfBase.cast<GrPorterDuffXPFactory>(); - return (fSrc == xpf.fSrc && fDst == xpf.fDst); + return (fSrcCoeff == xpf.fSrcCoeff && fDstCoeff == xpf.fDstCoeff); } - GrBlendCoeff fSrc; - GrBlendCoeff fDst; + GrBlendCoeff fSrcCoeff; + GrBlendCoeff fDstCoeff; typedef GrXPFactory INHERITED; }; |