Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(298)

Unified Diff: src/gpu/effects/GrXfermodeFragmentProcessor.cpp

Issue 1334293003: Create fragment processor for performing input color blend with child processor (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/effects/GrSimpleTextureEffect.h ('k') | src/gpu/gl/GrGLBlend.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/effects/GrXfermodeFragmentProcessor.cpp
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index ab944d86fcbcb19f1bc157bf753fa135da503e76..942251c980942659b1795a86f85d15734b761dfd 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -9,25 +9,23 @@
#include "GrFragmentProcessor.h"
#include "effects/GrConstColorProcessor.h"
-#include "gl/GrGLBlend.h"
+#include "gl/GrGLSLBlend.h"
#include "gl/builders/GrGLProgramBuilder.h"
+#include "SkGr.h"
-
-class GrComposeTwoFragmentProcessor : public GrFragmentProcessor {
+class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
public:
- GrComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragmentProcessor* dst,
+ ComposeTwoFragmentProcessor(const GrFragmentProcessor* src, const GrFragmentProcessor* dst,
SkXfermode::Mode mode)
: fMode(mode) {
- // Only coefficient xfer modes are supported
- SkASSERT(SkXfermode::kLastCoeffMode >= mode);
- this->initClassID<GrComposeTwoFragmentProcessor>();
+ this->initClassID<ComposeTwoFragmentProcessor>();
SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(src);
SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(dst);
SkASSERT(0 == shaderAChildIndex);
SkASSERT(1 == shaderBChildIndex);
}
- const char* name() const override { return "ComposeShader"; }
+ const char* name() const override { return "ComposeTwo"; }
void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
b->add32(fMode);
@@ -37,7 +35,7 @@ public:
protected:
bool onIsEqual(const GrFragmentProcessor& other) const override {
- const GrComposeTwoFragmentProcessor& cs = other.cast<GrComposeTwoFragmentProcessor>();
+ const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
return fMode == cs.fMode;
}
@@ -57,9 +55,9 @@ private:
/////////////////////////////////////////////////////////////////////
-class GrGLComposeTwoFragmentProcessor : public GrGLFragmentProcessor {
+class GLComposeTwoFragmentProcessor : public GrGLFragmentProcessor {
public:
- GrGLComposeTwoFragmentProcessor(const GrProcessor& processor) {}
+ GLComposeTwoFragmentProcessor(const GrProcessor& processor) {}
void emitCode(EmitArgs&) override;
@@ -69,28 +67,28 @@ private:
/////////////////////////////////////////////////////////////////////
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrComposeTwoFragmentProcessor);
+GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
-const GrFragmentProcessor* GrComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
+const GrFragmentProcessor* ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
// Create two random frag procs.
SkAutoTUnref<const GrFragmentProcessor> fpA(GrProcessorUnitTest::CreateChildFP(d));
SkAutoTUnref<const GrFragmentProcessor> fpB(GrProcessorUnitTest::CreateChildFP(d));
SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
- d->fRandom->nextRangeU(0, SkXfermode::kLastCoeffMode));
- return SkNEW_ARGS(GrComposeTwoFragmentProcessor, (fpA, fpB, mode));
+ d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
+ return new ComposeTwoFragmentProcessor(fpA, fpB, mode);
}
-GrGLFragmentProcessor* GrComposeTwoFragmentProcessor::onCreateGLInstance() const{
- return SkNEW_ARGS(GrGLComposeTwoFragmentProcessor, (*this));
+GrGLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLInstance() const{
+ return new GLComposeTwoFragmentProcessor(*this);
}
/////////////////////////////////////////////////////////////////////
-void GrGLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
+void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
- const GrComposeTwoFragmentProcessor& cs = args.fFp.cast<GrComposeTwoFragmentProcessor>();
+ const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
// Store alpha of input color and un-premultiply the input color by its alpha. We will
// re-multiply by this alpha after blending the output colors of the two child procs.
@@ -122,8 +120,8 @@ void GrGLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
SkXfermode::Mode mode = cs.getMode();
fsBuilder->codeAppend("{");
fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
- GrGLBlend::AppendPorterDuffBlend(fsBuilder, outputColorSrc.c_str(),
- outputColorDst.c_str(), args.fOutputColor, mode);
+ GrGLSLBlend::AppendMode(fsBuilder, outputColorSrc.c_str(),
+ outputColorDst.c_str(), args.fOutputColor, mode);
fsBuilder->codeAppend("}");
// re-multiply the output color by the input color's alpha
@@ -134,21 +132,184 @@ void GrGLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromTwoProcessors(
const GrFragmentProcessor* src, const GrFragmentProcessor* dst, SkXfermode::Mode mode) {
- if (SkXfermode::kLastCoeffMode < mode) {
- return nullptr;
- }
switch (mode) {
case SkXfermode::kClear_Mode:
- return GrConstColorProcessor::Create(GrColor_TRANS_BLACK,
+ return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
GrConstColorProcessor::kIgnore_InputMode);
- break;
case SkXfermode::kSrc_Mode:
return SkRef(src);
- break;
case SkXfermode::kDst_Mode:
return SkRef(dst);
- break;
default:
- return new GrComposeTwoFragmentProcessor(src, dst, mode);
+ return new ComposeTwoFragmentProcessor(src, dst, mode);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+class ComposeOneFragmentProcessor : public GrFragmentProcessor {
+public:
+ enum Child {
+ kDst_Child,
+ kSrc_Child,
+ };
+
+ ComposeOneFragmentProcessor(const GrFragmentProcessor* dst, SkXfermode::Mode mode, Child child)
+ : fMode(mode)
+ , fChild(child) {
+ this->initClassID<ComposeOneFragmentProcessor>();
+ SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(dst);
+ SkASSERT(0 == dstIndex);
+ }
+
+ const char* name() const override { return "ComposeOne"; }
+
+ void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
+ GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLastMode);
+ b->add32(fMode | (fChild << 16));
+ }
+
+ SkXfermode::Mode mode() const { return fMode; }
+
+ Child child() const { return fChild; }
+
+protected:
+ bool onIsEqual(const GrFragmentProcessor& that) const override {
+ return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
+ }
+
+ void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
+ SkXfermode::Coeff skSrcCoeff, skDstCoeff;
+ if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) {
+ GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff);
+ GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff);
+ GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlags, false);
+ this->childProcessor(0).computeInvariantOutput(&childOutput);
+ GrColor blendColor;
+ GrColorComponentFlags blendFlags;
+ if (kDst_Child == fChild) {
+ GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
+ inout->color(), inout->validFlags(),
+ childOutput.color(), childOutput.validFlags(),
+ &blendColor, &blendFlags);
+ } else {
+ GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
+ childOutput.color(), childOutput.validFlags(),
+ inout->color(), inout->validFlags(),
+ &blendColor, &blendFlags);
+ }
+ // will the shader code reference the input color?
+ GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNot_ReadInput;
+ if (kDst_Child == fChild) {
+ if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff)) {
+ readsInput = GrInvariantOutput::kWill_ReadInput;
+ }
+ } else {
+ if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoeff)) {
+ readsInput = GrInvariantOutput::kWill_ReadInput;
+ }
+ }
+ inout->setToOther(blendFlags, blendColor, readsInput);
+ } else {
+ inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
+ }
+ }
+
+private:
+ GrGLFragmentProcessor* onCreateGLInstance() const override;
+
+ SkXfermode::Mode fMode;
+ Child fChild;
+
+ GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
+
+ typedef GrFragmentProcessor INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class GLComposeOneFragmentProcessor : public GrGLFragmentProcessor {
+public:
+ GLComposeOneFragmentProcessor(const GrProcessor& processor) {}
+
+ void emitCode(EmitArgs& args) override {
+ GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
+ SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
+ ComposeOneFragmentProcessor::Child child =
+ args.fFp.cast<ComposeOneFragmentProcessor>().child();
+ // declare _dstColor and emit the code for the two child
+ fsBuilder->codeAppendf("vec4 _child;");
+ this->emitChild(0, nullptr, "_child", args);
+
+ const char* inputColor = args.fInputColor;
+ // We don't try to optimize for this case at all
+ if (!inputColor) {
+ fsBuilder->codeAppendf("const vec4 ones = vec4(1);");
+ inputColor = "ones";
+ }
+
+ // emit blend code
+ fsBuilder->codeAppend("{");
+ fsBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
+ if (ComposeOneFragmentProcessor::kDst_Child == child) {
+ GrGLSLBlend::AppendMode(fsBuilder, inputColor, "_child", args.fOutputColor, mode);
+ } else {
+ GrGLSLBlend::AppendMode(fsBuilder, "_child", inputColor, args.fOutputColor, mode);
+ }
+ fsBuilder->codeAppend("}");
+ }
+
+private:
+ typedef GrGLFragmentProcessor INHERITED;
+};
+
+/////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
+
+const GrFragmentProcessor* ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
+ // Create one random frag procs.
+ // For now, we'll prevent either children from being a shader with children to prevent the
+ // possibility of an arbitrarily large tree of procs.
+ SkAutoTUnref<const GrFragmentProcessor> dst(GrProcessorUnitTest::CreateChildFP(d));
+ SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
+ d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
+ ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
+ ComposeOneFragmentProcessor::kDst_Child :
+ ComposeOneFragmentProcessor::kSrc_Child;
+ return new ComposeOneFragmentProcessor(dst, mode, child);
+}
+
+GrGLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLInstance() const {
+ return new GLComposeOneFragmentProcessor(*this);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromDstProcessor(
+ const GrFragmentProcessor* dst, SkXfermode::Mode mode) {
+ switch (mode) {
+ case SkXfermode::kClear_Mode:
+ return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
+ GrConstColorProcessor::kIgnore_InputMode);
+ case SkXfermode::kSrc_Mode:
+ return nullptr;
+ default:
+ return new ComposeOneFragmentProcessor(dst, mode,
+ ComposeOneFragmentProcessor::kDst_Child);
+ }
+}
+
+const GrFragmentProcessor* GrXfermodeFragmentProcessor::CreateFromSrcProcessor(
+ const GrFragmentProcessor* src, SkXfermode::Mode mode) {
+ switch (mode) {
+ case SkXfermode::kClear_Mode:
+ return GrConstColorProcessor::Create(GrColor_TRANSPARENT_BLACK,
+ GrConstColorProcessor::kIgnore_InputMode);
+ case SkXfermode::kDst_Mode:
+ return nullptr;
+ default:
+ return new ComposeOneFragmentProcessor(src, mode,
+ ComposeOneFragmentProcessor::kSrc_Child);
}
}
« no previous file with comments | « src/gpu/effects/GrSimpleTextureEffect.h ('k') | src/gpu/gl/GrGLBlend.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698