Add Xfer Processor for GrCustomXfermodes
BUG=skia:
Review URL: https://codereview.chromium.org/852203003
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index 9469b2c..01322ca 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -33,6 +33,9 @@
## epoger will rebaseline by 25 Dec 2013
#gradtext
+# egdaniel
+colortype_xfermodes
+
# robertphillips - skia:2995
blurrects
diff --git a/include/gpu/effects/GrCustomXfermode.h b/include/gpu/effects/GrCustomXfermode.h
index e35727e..ab131ee 100644
--- a/include/gpu/effects/GrCustomXfermode.h
+++ b/include/gpu/effects/GrCustomXfermode.h
@@ -23,6 +23,8 @@
bool IsSupportedMode(SkXfermode::Mode mode);
GrFragmentProcessor* CreateFP(SkXfermode::Mode mode, GrTexture* background);
+
+ GrXPFactory* CreateXPFactory(SkXfermode::Mode mode);
};
#endif
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 9d727f0..37dbd0d 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -932,6 +932,17 @@
}
return false;
}
+
+bool SkProcCoeffXfermode::asXPFactory(GrXPFactory** xp) const {
+ if (GrCustomXfermode::IsSupportedMode(fMode)) {
+ if (xp) {
+ *xp = GrCustomXfermode::CreateXPFactory(fMode);
+ SkASSERT(*xp);
+ }
+ return true;
+ }
+ return false;
+}
#endif
const char* SkXfermode::ModeName(Mode mode) {
diff --git a/src/core/SkXfermode_proccoeff.h b/src/core/SkXfermode_proccoeff.h
index 504e64d..88b4d34 100644
--- a/src/core/SkXfermode_proccoeff.h
+++ b/src/core/SkXfermode_proccoeff.h
@@ -37,6 +37,8 @@
#if SK_SUPPORT_GPU
virtual bool asFragmentProcessor(GrFragmentProcessor**,
GrTexture* background) const SK_OVERRIDE;
+
+ virtual bool asXPFactory(GrXPFactory**) const SK_OVERRIDE;
#endif
SK_TO_STRING_OVERRIDE()
diff --git a/src/effects/SkArithmeticMode_gpu.cpp b/src/effects/SkArithmeticMode_gpu.cpp
index 3209fb9..48b7bcd 100644
--- a/src/effects/SkArithmeticMode_gpu.cpp
+++ b/src/effects/SkArithmeticMode_gpu.cpp
@@ -238,7 +238,7 @@
GrArithmeticXPFactory::GrArithmeticXPFactory(float k1, float k2, float k3, float k4,
bool enforcePMColor)
: fK1(k1), fK2(k2), fK3(k3), fK4(k4), fEnforcePMColor(enforcePMColor) {
- this->initClassID<GrArithmeticXPFactory>();
+ this->initClassID<GrArithmeticXPFactory>();
}
void GrArithmeticXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 44c8bf1..9977018 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -52,7 +52,7 @@
*/
static const int kFPFactoryCount = 37;
static const int kGPFactoryCount = 14;
-static const int kXPFactoryCount = 4;
+static const int kXPFactoryCount = 5;
template<>
void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() {
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index a78f304..9aa7153 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -416,19 +416,11 @@
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) SK_OVERRIDE {
SkXfermode::Mode mode = fp.cast<GrCustomXferFP>().mode();
- const GrTexture* backgroundTex =
- fp.cast<GrCustomXferFP>().backgroundAccess().getTexture();
GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
- const char* dstColor;
- if (backgroundTex) {
- dstColor = "bgColor";
- fsBuilder->codeAppendf("vec4 %s = ", dstColor);
- fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
- fsBuilder->codeAppendf(";");
- } else {
- dstColor = fsBuilder->dstColor();
- }
- SkASSERT(dstColor);
+ const char* dstColor = "bgColor";
+ fsBuilder->codeAppendf("vec4 %s = ", dstColor);
+ fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
+ fsBuilder->codeAppendf(";");
emit_custom_xfermode_code(mode, fsBuilder, outputColor, inputColor, dstColor);
}
@@ -452,15 +444,13 @@
GrCustomXferFP::GrCustomXferFP(SkXfermode::Mode mode, GrTexture* background)
: fMode(mode) {
this->initClassID<GrCustomXferFP>();
- if (background) {
- fBackgroundTransform.reset(kLocal_GrCoordSet, background,
- GrTextureParams::kNone_FilterMode);
- this->addCoordTransform(&fBackgroundTransform);
- fBackgroundAccess.reset(background);
- this->addTextureAccess(&fBackgroundAccess);
- } else {
- this->setWillReadDstColor();
- }
+
+ SkASSERT(background);
+ fBackgroundTransform.reset(kLocal_GrCoordSet, background,
+ GrTextureParams::kNone_FilterMode);
+ this->addCoordTransform(&fBackgroundTransform);
+ fBackgroundAccess.reset(background);
+ this->addTextureAccess(&fBackgroundAccess);
}
void GrCustomXferFP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
@@ -484,9 +474,106 @@
GrFragmentProcessor* GrCustomXferFP::TestCreate(SkRandom* rand,
GrContext*,
const GrDrawTargetCaps&,
- GrTexture*[]) {
+ GrTexture* textures[]) {
int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
- return SkNEW_ARGS(GrCustomXferFP, (static_cast<SkXfermode::Mode>(mode), NULL));
+ return SkNEW_ARGS(GrCustomXferFP, (static_cast<SkXfermode::Mode>(mode), textures[0]));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Xfer Processor
+///////////////////////////////////////////////////////////////////////////////
+
+GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) {
+ if (!GrCustomXfermode::IsSupportedMode(mode)) {
+ return NULL;
+ } else {
+ return SkNEW_ARGS(GrCustomXPFactory, (mode));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GLCustomXP : public GrGLXferProcessor {
+public:
+ GLCustomXP(const GrXferProcessor&) {}
+ ~GLCustomXP() SK_OVERRIDE {}
+
+ void emitCode(const EmitArgs& args) SK_OVERRIDE {
+ SkXfermode::Mode mode = args.fXP.cast<GrCustomXP>().mode();
+ GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
+ const char* dstColor = fsBuilder->dstColor();
+
+ emit_custom_xfermode_code(mode, fsBuilder, args.fOutputPrimary, args.fInputColor, dstColor);
+
+ fsBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
+ args.fOutputPrimary, args.fOutputPrimary, args.fInputCoverage,
+ args.fInputCoverage, dstColor);
+ }
+
+ void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}
+
+ static void GenKey(const GrXferProcessor& proc, const GrGLCaps&, GrProcessorKeyBuilder* b) {
+ uint32_t key = proc.numTextures();
+ SkASSERT(key <= 1);
+ key |= proc.cast<GrCustomXP>().mode() << 1;
+ b->add32(key);
+ }
+
+private:
+ typedef GrGLFragmentProcessor INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrCustomXP::GrCustomXP(SkXfermode::Mode mode)
+ : fMode(mode) {
+ this->initClassID<GrCustomXP>();
+ this->setWillReadDstColor();
+}
+
+void GrCustomXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
+ GLCustomXP::GenKey(*this, caps, b);
+}
+
+GrGLXferProcessor* GrCustomXP::createGLInstance() const {
+ return SkNEW_ARGS(GLCustomXP, (*this));
+}
+
+bool GrCustomXP::onIsEqual(const GrXferProcessor& other) const {
+ const GrCustomXP& s = other.cast<GrCustomXP>();
+ return fMode == s.fMode;
+}
+
+GrXferProcessor::OptFlags GrCustomXP::getOptimizations(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI,
+ bool doesStencilWrite,
+ GrColor* overrideColor,
+ const GrDrawTargetCaps& caps) {
+ return GrXferProcessor::kNone_Opt;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrCustomXPFactory::GrCustomXPFactory(SkXfermode::Mode mode)
+ : fMode(mode) {
+ this->initClassID<GrCustomXPFactory>();
+}
+
+void GrCustomXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI,
+ GrXPFactory::InvariantOutput* output) const {
+ output->fWillBlendWithDst = true;
+ output->fBlendedColorFlags = 0;
+}
+
+GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory);
+GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand,
+ GrContext*,
+ const GrDrawTargetCaps&,
+ GrTexture*[]) {
+ int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
+
+ return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode)));
}
diff --git a/src/gpu/effects/GrCustomXfermodePriv.h b/src/gpu/effects/GrCustomXfermodePriv.h
index 0c80351..48ad784 100644
--- a/src/gpu/effects/GrCustomXfermodePriv.h
+++ b/src/gpu/effects/GrCustomXfermodePriv.h
@@ -11,6 +11,7 @@
#include "GrCoordTransform.h"
#include "GrFragmentProcessor.h"
#include "GrTextureAccess.h"
+#include "GrXferProcessor.h"
#include "SkXfermode.h"
class GrGLCaps;
@@ -50,5 +51,97 @@
typedef GrFragmentProcessor INHERITED;
};
+///////////////////////////////////////////////////////////////////////////////
+// Xfer Processor
+///////////////////////////////////////////////////////////////////////////////
+
+class GrCustomXP : public GrXferProcessor {
+public:
+ static GrXferProcessor* Create(SkXfermode::Mode mode) {
+ if (!GrCustomXfermode::IsSupportedMode(mode)) {
+ return NULL;
+ } else {
+ return SkNEW_ARGS(GrCustomXP, (mode));
+ }
+ }
+
+ ~GrCustomXP() SK_OVERRIDE {};
+
+ const char* name() const SK_OVERRIDE { return "Custom Xfermode"; }
+
+ void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
+ GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
+
+ bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
+
+ GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI,
+ bool doesStencilWrite,
+ GrColor* overrideColor,
+ const GrDrawTargetCaps& caps) SK_OVERRIDE;
+
+ void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE {
+ blendInfo->fSrcBlend = kOne_GrBlendCoeff;
+ blendInfo->fDstBlend = kZero_GrBlendCoeff;
+ blendInfo->fBlendConstant = 0;
+ }
+
+ SkXfermode::Mode mode() const { return fMode; }
+
+private:
+ GrCustomXP(SkXfermode::Mode mode);
+
+ bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE;
+
+ SkXfermode::Mode fMode;
+
+ typedef GrXferProcessor INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class GrCustomXPFactory : public GrXPFactory {
+public:
+ GrCustomXPFactory(SkXfermode::Mode mode);
+
+ GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
+ return GrCustomXP::Create(fMode);
+ }
+
+ bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE {
+ return true;
+ }
+
+ bool canApplyCoverage(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
+ return true;
+ }
+
+ bool canTweakAlphaForCoverage() const SK_OVERRIDE {
+ return false;
+ }
+
+ void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
+ GrXPFactory::InvariantOutput*) const SK_OVERRIDE;
+
+ bool willReadDst(const GrProcOptInfo& colorPOI,
+ const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
+ return true;
+ }
+
+private:
+ bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
+ const GrCustomXPFactory& xpf = xpfBase.cast<GrCustomXPFactory>();
+ return fMode == xpf.fMode;
+ }
+
+ GR_DECLARE_XP_FACTORY_TEST;
+
+ SkXfermode::Mode fMode;
+
+ typedef GrXPFactory INHERITED;
+};
#endif