2 * Copyright 2015 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "effects/GrXfermodeFragmentProcessor.h"
10 #include "GrFragmentProcessor.h"
11 #include "GrInvariantOutput.h"
12 #include "effects/GrConstColorProcessor.h"
13 #include "glsl/GrGLSLFragmentProcessor.h"
14 #include "glsl/GrGLSLBlend.h"
15 #include "glsl/GrGLSLFragmentShaderBuilder.h"
18 class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
20 ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
21 SkXfermode::Mode mode)
23 this->initClassID<ComposeTwoFragmentProcessor>();
24 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
25 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
26 SkASSERT(0 == shaderAChildIndex);
27 SkASSERT(1 == shaderBChildIndex);
30 const char* name() const override { return "ComposeTwo"; }
32 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
36 SkXfermode::Mode getMode() const { return fMode; }
39 bool onIsEqual(const GrFragmentProcessor& other) const override {
40 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
41 return fMode == cs.fMode;
44 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
45 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
49 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
51 SkXfermode::Mode fMode;
53 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
55 typedef GrFragmentProcessor INHERITED;
58 /////////////////////////////////////////////////////////////////////
60 class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
62 void emitCode(EmitArgs&) override;
65 typedef GrGLSLFragmentProcessor INHERITED;
68 /////////////////////////////////////////////////////////////////////
70 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
72 sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
73 // Create two random frag procs.
74 sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
75 sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
77 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
78 d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
79 return sk_sp<GrFragmentProcessor>(
80 new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
83 GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
84 return new GLComposeTwoFragmentProcessor;
87 /////////////////////////////////////////////////////////////////////
89 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
91 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
92 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
94 const char* inputColor = nullptr;
95 if (args.fInputColor) {
96 inputColor = "inputColor";
97 fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
100 // declare outputColor and emit the code for each of the two children
101 SkString srcColor("xfer_src");
102 this->emitChild(0, inputColor, &srcColor, args);
104 SkString dstColor("xfer_dst");
105 this->emitChild(1, inputColor, &dstColor, args);
108 SkXfermode::Mode mode = cs.getMode();
109 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
110 GrGLSLBlend::AppendMode(fragBuilder,
116 // re-multiply the output color by the input color's alpha
117 if (args.fInputColor) {
118 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
122 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
123 sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
125 case SkXfermode::kClear_Mode:
126 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
127 GrConstColorProcessor::kIgnore_InputMode);
128 case SkXfermode::kSrc_Mode:
130 case SkXfermode::kDst_Mode:
133 return sk_sp<GrFragmentProcessor>(
134 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
138 //////////////////////////////////////////////////////////////////////////////
140 class ComposeOneFragmentProcessor : public GrFragmentProcessor {
147 ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode, Child child)
150 this->initClassID<ComposeOneFragmentProcessor>();
151 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(std::move(dst));
152 SkASSERT(0 == dstIndex);
155 const char* name() const override { return "ComposeOne"; }
157 SkString dumpInfo() const override {
160 for (int i = 0; i < this->numChildProcessors(); ++i) {
161 str.append(this->childProcessor(i).dumpInfo());
166 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
167 GR_STATIC_ASSERT((SkXfermode::kLastMode & SK_MaxU16) == SkXfermode::kLastMode);
168 b->add32(fMode | (fChild << 16));
171 SkXfermode::Mode mode() const { return fMode; }
173 Child child() const { return fChild; }
176 bool onIsEqual(const GrFragmentProcessor& that) const override {
177 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
180 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
181 SkXfermode::Coeff skSrcCoeff, skDstCoeff;
182 if (SkXfermode::ModeAsCoeff(fMode, &skSrcCoeff, &skDstCoeff)) {
183 GrBlendCoeff srcCoeff = SkXfermodeCoeffToGrBlendCoeff(skSrcCoeff);
184 GrBlendCoeff dstCoeff = SkXfermodeCoeffToGrBlendCoeff(skDstCoeff);
185 GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlags, false);
186 this->childProcessor(0).computeInvariantOutput(&childOutput);
188 GrColorComponentFlags blendFlags;
189 if (kDst_Child == fChild) {
190 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
191 inout->color(), inout->validFlags(),
192 childOutput.color(), childOutput.validFlags(),
193 &blendColor, &blendFlags);
195 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
196 childOutput.color(), childOutput.validFlags(),
197 inout->color(), inout->validFlags(),
198 &blendColor, &blendFlags);
200 // will the shader code reference the input color?
201 GrInvariantOutput::ReadInput readsInput = GrInvariantOutput::kWillNot_ReadInput;
202 if (kDst_Child == fChild) {
203 if (kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff)) {
204 readsInput = GrInvariantOutput::kWill_ReadInput;
207 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoeff)) {
208 readsInput = GrInvariantOutput::kWill_ReadInput;
211 inout->setToOther(blendFlags, blendColor, readsInput);
213 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
218 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
220 SkXfermode::Mode fMode;
223 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
225 typedef GrFragmentProcessor INHERITED;
228 //////////////////////////////////////////////////////////////////////////////
230 class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
232 void emitCode(EmitArgs& args) override {
233 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
234 SkXfermode::Mode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
235 ComposeOneFragmentProcessor::Child child =
236 args.fFp.cast<ComposeOneFragmentProcessor>().child();
237 SkString childColor("child");
238 this->emitChild(0, nullptr, &childColor, args);
240 const char* inputColor = args.fInputColor;
241 // We don't try to optimize for this case at all
243 fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
248 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
249 const char* childStr = childColor.c_str();
250 if (ComposeOneFragmentProcessor::kDst_Child == child) {
251 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
253 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
258 typedef GrGLSLFragmentProcessor INHERITED;
261 /////////////////////////////////////////////////////////////////////
263 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
265 sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
266 // Create one random frag procs.
267 // For now, we'll prevent either children from being a shader with children to prevent the
268 // possibility of an arbitrarily large tree of procs.
269 sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
270 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(
271 d->fRandom->nextRangeU(0, SkXfermode::kLastMode));
272 ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
273 ComposeOneFragmentProcessor::kDst_Child :
274 ComposeOneFragmentProcessor::kSrc_Child;
275 return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
278 GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
279 return new GLComposeOneFragmentProcessor;
282 //////////////////////////////////////////////////////////////////////////////
284 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
285 sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
287 case SkXfermode::kClear_Mode:
288 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
289 GrConstColorProcessor::kIgnore_InputMode);
290 case SkXfermode::kSrc_Mode:
293 return sk_sp<GrFragmentProcessor>(
294 new ComposeOneFragmentProcessor(std::move(dst), mode,
295 ComposeOneFragmentProcessor::kDst_Child));
299 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
300 sk_sp<GrFragmentProcessor> src, SkXfermode::Mode mode) {
302 case SkXfermode::kClear_Mode:
303 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
304 GrConstColorProcessor::kIgnore_InputMode);
305 case SkXfermode::kDst_Mode:
308 return sk_sp<GrFragmentProcessor>(
309 new ComposeOneFragmentProcessor(src, mode,
310 ComposeOneFragmentProcessor::kSrc_Child));