aboutsummaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/core/SkXfermode.h4
-rw-r--r--include/gpu/GrPaint.h32
-rw-r--r--include/gpu/GrXferProcessor.h111
-rw-r--r--include/gpu/effects/GrPorterDuffXferProcessor.h50
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;
};