aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gypi3
-rw-r--r--include/core/SkXfermode.h27
-rw-r--r--include/gpu/GrBackendProcessorFactory.h11
-rw-r--r--include/gpu/GrInvariantOutput.h2
-rw-r--r--include/gpu/GrPaint.h30
-rw-r--r--include/gpu/GrXferProcessor.h62
-rw-r--r--src/core/SkXfermode.cpp34
-rwxr-xr-xsrc/gpu/GrBitmapTextContext.cpp7
-rwxr-xr-xsrc/gpu/GrDistanceFieldTextContext.cpp8
-rw-r--r--src/gpu/GrDrawState.cpp11
-rw-r--r--src/gpu/GrDrawState.h4
-rw-r--r--src/gpu/GrOptDrawState.cpp5
-rw-r--r--src/gpu/GrOptDrawState.h5
-rw-r--r--src/gpu/GrPaint.cpp9
-rw-r--r--src/gpu/GrProcOptInfo.h1
-rw-r--r--src/gpu/GrProcessor.cpp15
-rw-r--r--src/gpu/SkGr.cpp25
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp76
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.h78
-rw-r--r--src/gpu/gl/GrGLProcessor.h12
20 files changed, 387 insertions, 38 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 943e610520..4c5657dbd9 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -35,6 +35,7 @@
'<(skia_include_path)/gpu/GrTextureAccess.h',
'<(skia_include_path)/gpu/GrTypes.h',
'<(skia_include_path)/gpu/GrUserConfig.h',
+ '<(skia_include_path)/gpu/GrXferProcessor.h',
'<(skia_include_path)/gpu/gl/GrGLConfig.h',
'<(skia_include_path)/gpu/gl/GrGLExtensions.h',
@@ -195,6 +196,8 @@
'<(skia_src_path)/gpu/effects/GrMatrixConvolutionEffect.h',
'<(skia_src_path)/gpu/effects/GrOvalEffect.cpp',
'<(skia_src_path)/gpu/effects/GrOvalEffect.h',
+ '<(skia_src_path)/gpu/effects/GrPorterDuffXferProcessor.cpp',
+ '<(skia_src_path)/gpu/effects/GrPorterDuffXferProcessor.h',
'<(skia_src_path)/gpu/effects/GrRRectEffect.cpp',
'<(skia_src_path)/gpu/effects/GrRRectEffect.h',
'<(skia_src_path)/gpu/effects/GrSimpleTextureEffect.cpp',
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index 6d723e8fc2..35e9837483 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -15,6 +15,7 @@
class GrFragmentProcessor;
class GrTexture;
+class GrXPFactory;
class SkString;
/** \class SkXfermode
@@ -198,16 +199,28 @@ public:
fragment shader. If NULL, the effect should request access to destination color
(setWillReadDstColor()), and use that in the fragment shader (builder->dstColor()).
*/
+ // TODO: Once all custom xp's have been created the background parameter will be required here.
+ // We will always use the XPFactory if there is no background texture and the fragment if
+ // there is one.
virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture* background = NULL) const;
- /** Returns true if the xfermode can be expressed as coeffs (src, dst), or as an effect
- (effect). This helper calls the asCoeff() 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. effect, src, and dst must all be NULL or all
- non-NULL.
+ /** A subclass may implement this factory function to work with the GPU backend. It is legal
+ to call this with xpf NULL to simply test the return value. If xpf is non-NULL then the
+ xfermode may optionally allocate a factory to return to the caller as *xpf. The caller
+ will install it and own a ref to it. Since the xfermode may or may not assign *xpf, the
+ caller should set *xpf to NULL beforehand. XP's cannot use a background texture since they
+ have no coord transforms.
+ */
+ virtual bool asXPFactory(GrXPFactory** xpf) const;
+
+ /** Returns true if the xfermode can be expressed as an xfer processor factory (xpFactory),
+ 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.
*/
- static bool asFragmentProcessorOrCoeff(SkXfermode*, GrFragmentProcessor**, Coeff* src,
- Coeff* dst, GrTexture* background = NULL);
+ static bool AsFragmentProcessorOrXPFactory(SkXfermode*, GrFragmentProcessor**,
+ GrXPFactory**, Coeff* src, Coeff* dst);
SK_TO_STRING_PUREVIRT()
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
diff --git a/include/gpu/GrBackendProcessorFactory.h b/include/gpu/GrBackendProcessorFactory.h
index 9dda1659d0..acbc12c192 100644
--- a/include/gpu/GrBackendProcessorFactory.h
+++ b/include/gpu/GrBackendProcessorFactory.h
@@ -115,8 +115,10 @@ private:
class GrFragmentProcessor;
class GrGeometryProcessor;
+class GrXferProcessor;
class GrGLFragmentProcessor;
class GrGLGeometryProcessor;
+class GrGLXferProcessor;
/**
* Backend processor factory cannot actually create anything, it is up to subclasses to implement
@@ -132,6 +134,15 @@ public:
virtual GrGLFragmentProcessor* createGLInstance(const GrFragmentProcessor&) const = 0;
};
+class GrBackendXferProcessorFactory : public GrBackendProcessorFactory {
+public:
+ /**
+ * Creates a GrGLProcessor instance that is used both to generate code for the GrProcessor in a
+ * GLSL program and to manage updating uniforms for the program when it is used.
+ */
+ virtual GrGLXferProcessor* createGLInstance(const GrXferProcessor&) const = 0;
+};
+
class GrBackendGeometryProcessorFactory : public GrBackendProcessorFactory {
public:
/**
diff --git a/include/gpu/GrInvariantOutput.h b/include/gpu/GrInvariantOutput.h
index 0805ac7933..4f61999dcd 100644
--- a/include/gpu/GrInvariantOutput.h
+++ b/include/gpu/GrInvariantOutput.h
@@ -142,6 +142,8 @@ private:
return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
}
+ bool isSingleComponent() const { return fIsSingleComponent; }
+
bool willUseInputColor() const { return fWillUseInputColor; }
void resetWillUseInputColor() { fWillUseInputColor = true; }
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h
index 6a40a71ffc..f31830bb2b 100644
--- a/include/gpu/GrPaint.h
+++ b/include/gpu/GrPaint.h
@@ -12,6 +12,7 @@
#include "GrColor.h"
#include "GrFragmentStage.h"
+#include "GrXferProcessor.h"
#include "SkXfermode.h"
@@ -78,6 +79,11 @@ public:
void setDither(bool dither) { fDither = dither; }
bool isDither() const { return fDither; }
+ const GrXPFactory* setXPFactory(const GrXPFactory* xpFactory) {
+ fXPFactory.reset(SkRef(xpFactory));
+ return xpFactory;
+ }
+
/**
* Appends an additional color processor to the color computation.
*/
@@ -109,6 +115,8 @@ public:
int numCoverageStages() const { return fCoverageStages.count(); }
int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
+ const GrXPFactory* getXPFactory() const { return fXPFactory.get(); }
+
const GrFragmentStage& getColorStage(int s) const { return fColorStages[s]; }
const GrFragmentStage& getCoverageStage(int s) const { return fCoverageStages[s]; }
@@ -123,6 +131,8 @@ public:
fColorStages = paint.fColorStages;
fCoverageStages = paint.fCoverageStages;
+ fXPFactory.reset(SkRef(paint.getXPFactory()));
+
return *this;
}
@@ -197,15 +207,16 @@ private:
friend class GrContext; // To access above two functions
friend class GrStencilAndCoverTextContext; // To access above two functions
- SkSTArray<4, GrFragmentStage> fColorStages;
- SkSTArray<2, GrFragmentStage> fCoverageStages;
+ SkAutoTUnref<const GrXPFactory> fXPFactory;
+ SkSTArray<4, GrFragmentStage> fColorStages;
+ SkSTArray<2, GrFragmentStage> fCoverageStages;
- GrBlendCoeff fSrcBlendCoeff;
- GrBlendCoeff fDstBlendCoeff;
- bool fAntiAlias;
- bool fDither;
+ GrBlendCoeff fSrcBlendCoeff;
+ GrBlendCoeff fDstBlendCoeff;
+ bool fAntiAlias;
+ bool fDither;
- GrColor fColor;
+ GrColor fColor;
void resetBlend() {
fSrcBlendCoeff = kOne_GrBlendCoeff;
@@ -221,10 +232,7 @@ private:
fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
}
- void resetStages() {
- fColorStages.reset();
- fCoverageStages.reset();
- }
+ void resetStages();
};
#endif
diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h
new file mode 100644
index 0000000000..139ac96a99
--- /dev/null
+++ b/include/gpu/GrXferProcessor.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrXferProcessor_DEFINED
+#define GrXferProcessor_DEFINED
+
+#include "GrColor.h"
+#include "GrFragmentProcessor.h"
+#include "GrTypes.h"
+#include "SkXfermode.h"
+
+/**
+ * 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
+ * state. The inputs to its shader code are the final computed src color and fractional pixel
+ * coverage. The GrXferProcessor's shader code writes the fragment shader output color that goes
+ * into the fixed-function blend. When dual-source blending is available, it may also write a
+ * seconday fragment shader output color. When allowed by the backend API, the GrXferProcessor may
+ * read the destination color. The GrXferProcessor is responsible for setting the blend coefficients
+ * and blend constant color.
+ *
+ * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
+ * GrXPFactory once we have finalized the state of our draw.
+ */
+class GrXferProcessor : public GrFragmentProcessor {
+private:
+
+ typedef GrFragmentProcessor INHERITED;
+};
+
+/**
+ * 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
+ * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
+ * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
+ * the draw.
+ *
+ * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
+ * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
+ * blend with the destination color.
+ */
+class GrXPFactory : public GrProgramElement {
+public:
+ virtual const GrXferProcessor* createXferProcessor() const = 0;
+
+ /**
+ * This function returns true if the GrXferProcessor generated from this factory will be able to
+ * correctly blend when using RGB coverage. The knownColor and knownColorFlags represent the
+ * final computed color from the color stages.
+ */
+ virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0;
+
+private:
+ typedef GrProgramElement INHERITED;
+};
+
+#endif
+
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index e0abb4ebdd..ef44b1e747 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -6,7 +6,6 @@
* found in the LICENSE file.
*/
-
#include "SkXfermode.h"
#include "SkXfermode_opts_SSE2.h"
#include "SkXfermode_proccoeff.h"
@@ -680,16 +679,41 @@ bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
return false;
}
-bool SkXfermode::asFragmentProcessorOrCoeff(SkXfermode* xfermode, GrFragmentProcessor** fp,
- Coeff* src, Coeff* dst, GrTexture* background) {
+bool SkXfermode::asXPFactory(GrXPFactory**) const {
+ return false;
+}
+
+
+#if SK_SUPPORT_GPU
+#include "effects/GrPorterDuffXferProcessor.h"
+
+bool SkXfermode::AsFragmentProcessorOrXPFactory(SkXfermode* xfermode,
+ GrFragmentProcessor** fp,
+ GrXPFactory** xpf,
+ Coeff* src, Coeff* dst) {
if (NULL == xfermode) {
- return ModeAsCoeff(kSrcOver_Mode, src, dst);
+ SkAssertResult(ModeAsCoeff(kSrcOver_Mode, src, dst));
+ *xpf = GrPorterDuffXPFactory::Create(*src, *dst);
+ return true;
} else if (xfermode->asCoeff(src, dst)) {
+ *xpf = GrPorterDuffXPFactory::Create(*src, *dst);
+ return true;
+ } else if (xfermode->asXPFactory(xpf)) {
+ *src = SkXfermode::kOne_Coeff;
+ *dst = SkXfermode::kZero_Coeff;
return true;
} else {
- return xfermode->asFragmentProcessor(fp, background);
+ return xfermode->asFragmentProcessor(fp);
}
}
+#else
+bool SkXfermode::AsFragmentProcessorOrXPFactory(SkXfermode* xfermode,
+ GrFragmentProcessor** fp,
+ GrXPFactory** xpf,
+ Coeff* src, Coeff* dst) {
+ return false;
+}
+#endif
SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
// no-op. subclasses should override this
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 3b0bddb8e7..f5e2c298f1 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -561,9 +561,10 @@ void GrBitmapTextContext::flush() {
break;
// LCD text
case kA565_GrMaskFormat: {
- if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
- kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
- fPaint.numColorStages()) {
+ // TODO: move supportsRGBCoverage check to setupCoverageEffect and only add LCD
+ // processor if the xp can support it. For now we will simply assume that if
+ // fUseLCDText is true, then we have a known color output.
+ if (!drawState.getXPFactory()->supportsRGBCoverage(0, kRGBA_GrColorComponentFlags)) {
SkDebugf("LCD Text will not draw correctly.\n");
}
SkASSERT(!drawState.hasColorVertexAttribute());
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index f5983ac723..f296244d3e 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -628,9 +628,11 @@ void GrDistanceFieldTextContext::flush() {
// Set draw state
if (fUseLCDText) {
GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
- if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
- kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
- fPaint.numColorStages()) {
+
+ // TODO: move supportsRGBCoverage check to setupCoverageEffect and only add LCD
+ // processor if the xp can support it. For now we will simply assume that if
+ // fUseLCDText is true, then we have a known color output.
+ if (!drawState.getXPFactory()->supportsRGBCoverage(0, kRGBA_GrColorComponentFlags)) {
SkDebugf("LCD Text will not draw correctly.\n");
}
SkASSERT(!drawState.hasColorVertexAttribute());
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index ff58c4899a..0fd098740c 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -11,8 +11,10 @@
#include "GrOptDrawState.h"
#include "GrPaint.h"
#include "GrProcOptInfo.h"
+#include "GrXferProcessor.h"
+#include "effects/GrPorterDuffXferProcessor.h"
-//////////////////////////////////////////////////////////////////////////////s
+///////////////////////////////////////////////////////////////////////////////
bool GrDrawState::isEqual(const GrDrawState& that) const {
bool usingVertexColors = this->hasColorVertexAttribute();
@@ -92,6 +94,7 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
fCoverage = that.fCoverage;
fDrawFace = that.fDrawFace;
fGeometryProcessor.reset(SkSafeRef(that.fGeometryProcessor.get()));
+ fXPFactory.reset(SkRef(that.getXPFactory()));
fColorStages = that.fColorStages;
fCoverageStages = that.fCoverageStages;
@@ -113,6 +116,8 @@ void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
fRenderTarget.reset(NULL);
fGeometryProcessor.reset(NULL);
+ fXPFactory.reset(GrPorterDuffXPFactory::Create(kOne_GrBlendCoeff,
+ kZero_GrBlendCoeff));
fColorStages.reset();
fCoverageStages.reset();
@@ -169,6 +174,9 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
fCoverageStages.push_back(paint.getCoverageStage(i));
}
+ fXPFactory.reset(SkRef(paint.getXPFactory()));
+
+ this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
this->setRenderTarget(rt);
fViewMatrix = vm;
@@ -187,7 +195,6 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
this->setState(GrDrawState::kDither_StateBit, paint.isDither());
this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
- this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
this->setCoverage(0xFF);
fColorProcInfoValid = false;
fCoverageProcInfoValid = false;
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index a236d1a559..39163ff5ee 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -203,6 +203,9 @@ public:
bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
const GrGeometryProcessor* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+
+ const GrXPFactory* getXPFactory() const { return fXPFactory.get(); }
+
const GrFragmentStage& getColorStage(int idx) const { return fColorStages[idx]; }
const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
@@ -721,6 +724,7 @@ private:
GrBlendCoeff fSrcBlend;
GrBlendCoeff fDstBlend;
SkAutoTUnref<const GrGeometryProcessor> fGeometryProcessor;
+ SkAutoTUnref<const GrXPFactory> fXPFactory;
FragmentStageArray fColorStages;
FragmentStageArray fCoverageStages;
uint32_t fHints;
diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp
index 41a34c4ed2..6f6f0af888 100644
--- a/src/gpu/GrOptDrawState.cpp
+++ b/src/gpu/GrOptDrawState.cpp
@@ -100,6 +100,11 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
drawState.hasGeometryProcessor());
fGeometryProcessor.reset(drawState.getGeometryProcessor());
+ // Create XferProcessor from DS's XPFactory
+ const GrXferProcessor* xpProcessor = drawState.getXPFactory()->createXferProcessor();
+ fXferProcessor.reset(xpProcessor);
+ xpProcessor->unref();
+
// Copy Stages from DS to ODS
for (int i = firstColorStageIdx; i < drawState.numColorStages(); ++i) {
SkNEW_APPEND_TO_TARRAY(&fFragmentStages,
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index 542172fd64..ac7ec16402 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -84,6 +84,9 @@ public:
bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
const GrGeometryProcessor* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+
+ const GrXferProcessor* getXferProcessor() const { return fXferProcessor.get(); }
+
const GrPendingFragmentStage& getColorStage(int idx) const {
SkASSERT(idx < this->numColorStages());
return fFragmentStages[idx];
@@ -230,6 +233,7 @@ private:
typedef GrPendingIOResource<GrRenderTarget, kWrite_GrIOType> RenderTarget;
typedef SkSTArray<8, GrPendingFragmentStage> FragmentStageArray;
typedef GrPendingProgramElement<const GrGeometryProcessor> ProgramGeometryProcessor;
+ typedef GrPendingProgramElement<const GrXferProcessor> ProgramXferProcessor;
RenderTarget fRenderTarget;
ScissorState fScissorState;
GrColor fColor;
@@ -243,6 +247,7 @@ private:
GrBlendCoeff fDstBlend;
uint32_t fFlags;
ProgramGeometryProcessor fGeometryProcessor;
+ ProgramXferProcessor fXferProcessor;
FragmentStageArray fFragmentStages;
// This function is equivalent to the offset into fFragmentStages where coverage stages begin.
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index 7d89535a11..bd5b2860f4 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -10,6 +10,7 @@
#include "GrBlend.h"
#include "GrProcOptInfo.h"
+#include "effects/GrPorterDuffXferProcessor.h"
#include "effects/GrSimpleTextureEffect.h"
void GrPaint::addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
@@ -48,6 +49,13 @@ bool GrPaint::isOpaqueAndConstantColor(GrColor* color) const {
return false;
}
+void GrPaint::resetStages() {
+ fColorStages.reset();
+ fCoverageStages.reset();
+ fXPFactory.reset(GrPorterDuffXPFactory::Create(kOne_GrBlendCoeff,
+ kZero_GrBlendCoeff));
+}
+
bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
uint32_t* solidColorKnownComponents) const {
@@ -114,3 +122,4 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor,
}
return opaque;
}
+
diff --git a/src/gpu/GrProcOptInfo.h b/src/gpu/GrProcOptInfo.h
index 5252e85354..bb657d27c0 100644
--- a/src/gpu/GrProcOptInfo.h
+++ b/src/gpu/GrProcOptInfo.h
@@ -35,6 +35,7 @@ public:
bool isSolidWhite() const { return fInOut.isSolidWhite(); }
bool isOpaque() const { return fInOut.isOpaque(); }
+ bool isSingleComponent() const { return fInOut.isSingleComponent(); }
GrColor color() const { return fInOut.color(); }
uint8_t validFlags() const { return fInOut.validFlags(); }
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index d850d6894a..8aeef04b48 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -28,6 +28,13 @@ GrProcessorTestFactory<GrFragmentProcessor>::GetFactories() {
}
template<>
+SkTArray<GrProcessorTestFactory<GrXferProcessor>*, true>*
+GrProcessorTestFactory<GrXferProcessor>::GetFactories() {
+ static SkTArray<GrProcessorTestFactory<GrXferProcessor>*, true> gFactories;
+ return &gFactories;
+}
+
+template<>
SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>*
GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() {
static SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true> gFactories;
@@ -41,6 +48,7 @@ GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() {
*/
static const int kFPFactoryCount = 37;
static const int kGPFactoryCount = 14;
+static const int kXPFactoryCount = 0;
template<>
void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() {
@@ -56,6 +64,13 @@ void GrProcessorTestFactory<GrGeometryProcessor>::VerifyFactoryCount() {
}
}
+template<>
+void GrProcessorTestFactory<GrXferProcessor>::VerifyFactoryCount() {
+ if (kXPFactoryCount != GetFactories()->count()) {
+ SkFAIL("Wrong number of xfer processor factories!");
+ }
+}
+
#endif
namespace GrProcessorUnitTest {
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index d71b05ad7d..dadf9f23ee 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -6,15 +6,18 @@
*/
#include "SkGr.h"
+
+#include "GrDrawTargetCaps.h"
+#include "GrGpu.h"
+#include "GrXferProcessor.h"
#include "SkColorFilter.h"
#include "SkConfig8888.h"
#include "SkData.h"
#include "SkMessageBus.h"
#include "SkPixelRef.h"
#include "SkTextureCompressor.h"
-#include "GrGpu.h"
#include "effects/GrDitherEffect.h"
-#include "GrDrawTargetCaps.h"
+#include "effects/GrPorterDuffXferProcessor.h"
#include "effects/GrYUVtoRGBEffect.h"
#ifndef SK_IGNORE_ETC1_SUPPORT
@@ -465,19 +468,27 @@ void SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor
SkXfermode::Coeff dm;
SkXfermode* mode = skPaint.getXfermode();
- GrFragmentProcessor* xferProcessor = NULL;
- if (SkXfermode::asFragmentProcessorOrCoeff(mode, &xferProcessor, &sm, &dm)) {
- if (xferProcessor) {
- grPaint->addColorProcessor(xferProcessor)->unref();
+ GrFragmentProcessor* fragmentProcessor = NULL;
+ GrXPFactory* xpFactory = NULL;
+ if (SkXfermode::AsFragmentProcessorOrXPFactory(mode, &fragmentProcessor, &xpFactory,
+ &sm, &dm)) {
+ if (fragmentProcessor) {
+ SkASSERT(NULL == xpFactory);
+ grPaint->addColorProcessor(fragmentProcessor)->unref();
+ xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kOne_Coeff,
+ SkXfermode::kZero_Coeff);
sm = SkXfermode::kOne_Coeff;
dm = SkXfermode::kZero_Coeff;
}
} else {
- //SkDEBUGCODE(SkDebugf("Unsupported xfer mode.\n");)
// Fall back to src-over
+ xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kOne_Coeff,
+ SkXfermode::kISA_Coeff);
sm = SkXfermode::kOne_Coeff;
dm = SkXfermode::kISA_Coeff;
}
+ SkASSERT(xpFactory);
+ grPaint->setXPFactory(xpFactory)->unref();
grPaint->setBlendFunc(sk_blend_to_grblend(sm), sk_blend_to_grblend(dm));
//set the color of the paint to the one of the parameter
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
new file mode 100644
index 0000000000..fdbcbbe656
--- /dev/null
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrPorterDuffXferProcessor.h"
+
+#include "GrBackendProcessorFactory.h"
+#include "GrDrawState.h"
+#include "GrInvariantOutput.h"
+#include "GrProcessor.h"
+#include "GrTBackendProcessorFactory.h"
+#include "GrTypes.h"
+#include "GrXferProcessor.h"
+#include "gl/GrGLProcessor.h"
+#include "gl/builders/GrGLFragmentShaderBuilder.h"
+#include "gl/builders/GrGLProgramBuilder.h"
+
+class GrGLPorterDuffXferProcessor : public GrGLXferProcessor {
+public:
+ GrGLPorterDuffXferProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
+ : INHERITED(factory) {}
+
+ virtual ~GrGLPorterDuffXferProcessor() {}
+
+ virtual void emitCode(GrGLFPBuilder* builder,
+ const GrFragmentProcessor& fp,
+ const char* outputColor,
+ const char* inputColor,
+ const TransformedCoordsArray& coords,
+ const TextureSamplerArray& samplers) SK_OVERRIDE {
+ GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor);
+ }
+
+ virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {};
+
+ static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b) {};
+
+private:
+ typedef GrGLXferProcessor INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend)
+ : fSrcBlend(srcBlend), fDstBlend(dstBlend) {}
+
+GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() {
+}
+
+const GrBackendFragmentProcessorFactory& GrPorterDuffXferProcessor::getFactory() const {
+ return GrTBackendFragmentProcessorFactory<GrPorterDuffXferProcessor>::getInstance();
+}
+
+void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const {
+ inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+const GrXferProcessor* GrPorterDuffXPFactory::createXferProcessor() const {
+ return GrPorterDuffXferProcessor::Create(fSrc, fDst);
+}
+
+bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
+ uint32_t knownColorFlags) const {
+ if (kOne_GrBlendCoeff == fSrc && kISA_GrBlendCoeff == fDst &&
+ kRGBA_GrColorComponentFlags == knownColorFlags) {
+ return true;
+ }
+ return false;
+}
+
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.h b/src/gpu/effects/GrPorterDuffXferProcessor.h
new file mode 100644
index 0000000000..474285d829
--- /dev/null
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrPorterDuffXferProcessor_DEFINED
+#define GrPorterDuffXferProcessor_DEFINED
+
+#include "GrTypes.h"
+#include "GrXferProcessor.h"
+#include "SkXfermode.h"
+
+class GrBackendFragmentProcessorFactory;
+class GrDrawState;
+class GrGLPorterDuffXferProcessor;
+class GrInvariantOutput;
+
+class GrPorterDuffXferProcessor : public GrXferProcessor {
+public:
+ static GrXferProcessor* Create(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend) {
+ return SkNEW_ARGS(GrPorterDuffXferProcessor, (srcBlend, dstBlend));
+ }
+
+ virtual ~GrPorterDuffXferProcessor();
+
+ virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
+
+ typedef GrGLPorterDuffXferProcessor GLProcessor;
+ static const char* Name() { return "Porter Duff"; }
+
+private:
+ GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend);
+
+ virtual bool onIsEqual(const GrFragmentProcessor& fpBase) const SK_OVERRIDE {
+ const GrPorterDuffXferProcessor& xp = fpBase.cast<GrPorterDuffXferProcessor>();
+ if (fSrcBlend != xp.fSrcBlend || fDstBlend != xp.fDstBlend) {
+ return false;
+ }
+ return true;
+ }
+
+ virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
+
+ GrBlendCoeff fSrcBlend;
+ GrBlendCoeff fDstBlend;
+
+ typedef GrXferProcessor INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GrPorterDuffXPFactory : public GrXPFactory {
+public:
+ static GrXPFactory* Create(SkXfermode::Coeff src, SkXfermode::Coeff dst) {
+ return SkNEW_ARGS(GrPorterDuffXPFactory, ((GrBlendCoeff)(src), (GrBlendCoeff)(dst)));
+ }
+
+ static GrXPFactory* Create(GrBlendCoeff src, GrBlendCoeff dst) {
+ return SkNEW_ARGS(GrPorterDuffXPFactory, (src, dst));
+ }
+
+ const GrXferProcessor* createXferProcessor() const SK_OVERRIDE;
+
+ bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE;
+
+private:
+ GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst)
+ : fSrc(src), fDst(dst) {}
+
+ GrBlendCoeff fSrc;
+ GrBlendCoeff fDst;
+
+ typedef GrXPFactory INHERITED;
+};
+
+#endif
diff --git a/src/gpu/gl/GrGLProcessor.h b/src/gpu/gl/GrGLProcessor.h
index 4bc3dd019b..ca4fa2459f 100644
--- a/src/gpu/gl/GrGLProcessor.h
+++ b/src/gpu/gl/GrGLProcessor.h
@@ -125,4 +125,16 @@ private:
typedef GrGLProcessor INHERITED;
};
+class GrGLXferProcessor : public GrGLFragmentProcessor {
+public:
+ GrGLXferProcessor(const GrBackendProcessorFactory& factory)
+ : INHERITED(factory) {
+ }
+
+ virtual ~GrGLXferProcessor() {}
+
+private:
+ typedef GrGLFragmentProcessor INHERITED;
+};
+
#endif