blob: d3eaee338d295643ca6ae77f8f5cc6c45aadde73 [file] [log] [blame]
wangyix809e5af2015-09-09 12:58:32 -07001/*
2* Copyright 2015 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#include "effects/GrXfermodeFragmentProcessor.h"
9
10#include "GrFragmentProcessor.h"
egdaniel7ea439b2015-12-03 09:20:44 -080011#include "GrInvariantOutput.h"
wangyix809e5af2015-09-09 12:58:32 -070012#include "effects/GrConstColorProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080013#include "glsl/GrGLSLFragmentProcessor.h"
14#include "glsl/GrGLSLBlend.h"
egdaniel2d721d32015-11-11 13:06:05 -080015#include "glsl/GrGLSLFragmentShaderBuilder.h"
bsalomonf276ac52015-10-09 13:36:42 -070016#include "SkGrPriv.h"
wangyix809e5af2015-09-09 12:58:32 -070017
bsalomonae4738f2015-09-15 15:33:27 -070018class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -070019public:
bungeman06ca8ec2016-06-09 08:01:03 -070020 ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
Mike Reed7d954ad2016-10-28 15:42:34 -040021 SkBlendMode mode)
wangyix809e5af2015-09-09 12:58:32 -070022 : fMode(mode) {
bsalomonae4738f2015-09-15 15:33:27 -070023 this->initClassID<ComposeTwoFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -070024 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
25 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
wangyix809e5af2015-09-09 12:58:32 -070026 SkASSERT(0 == shaderAChildIndex);
27 SkASSERT(1 == shaderBChildIndex);
28 }
29
bsalomonae4738f2015-09-15 15:33:27 -070030 const char* name() const override { return "ComposeTwo"; }
wangyix809e5af2015-09-09 12:58:32 -070031
Brian Salomon94efbf52016-11-29 13:43:05 -050032 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -040033 b->add32((int)fMode);
wangyix809e5af2015-09-09 12:58:32 -070034 }
35
Mike Reed7d954ad2016-10-28 15:42:34 -040036 SkBlendMode getMode() const { return fMode; }
wangyix809e5af2015-09-09 12:58:32 -070037
38protected:
39 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -070040 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -070041 return fMode == cs.fMode;
42 }
43
44 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
45 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
46 }
47
48private:
egdaniel57d3b032015-11-13 11:57:27 -080049 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyix809e5af2015-09-09 12:58:32 -070050
Mike Reed7d954ad2016-10-28 15:42:34 -040051 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -070052
53 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
54
55 typedef GrFragmentProcessor INHERITED;
56};
57
58/////////////////////////////////////////////////////////////////////
59
egdaniel64c47282015-11-13 06:54:19 -080060class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -070061public:
wangyix809e5af2015-09-09 12:58:32 -070062 void emitCode(EmitArgs&) override;
63
64private:
egdaniel64c47282015-11-13 06:54:19 -080065 typedef GrGLSLFragmentProcessor INHERITED;
wangyix809e5af2015-09-09 12:58:32 -070066};
67
68/////////////////////////////////////////////////////////////////////
69
bsalomonae4738f2015-09-15 15:33:27 -070070GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -070071
bungeman06ca8ec2016-06-09 08:01:03 -070072sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -070073 // Create two random frag procs.
bungeman06ca8ec2016-06-09 08:01:03 -070074 sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
75 sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
wangyix809e5af2015-09-09 12:58:32 -070076
Mike Reed7d954ad2016-10-28 15:42:34 -040077 SkBlendMode mode = static_cast<SkBlendMode>(
78 d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
bungeman06ca8ec2016-06-09 08:01:03 -070079 return sk_sp<GrFragmentProcessor>(
80 new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
wangyix809e5af2015-09-09 12:58:32 -070081}
82
egdaniel57d3b032015-11-13 11:57:27 -080083GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
robertphillips9cdb9922016-02-03 12:25:40 -080084 return new GLComposeTwoFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -070085}
86
87/////////////////////////////////////////////////////////////////////
88
bsalomonae4738f2015-09-15 15:33:27 -070089void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -070090
cdalton85285412016-02-18 12:37:07 -080091 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonae4738f2015-09-15 15:33:27 -070092 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -070093
bsalomonf1b7a1d2015-09-28 06:26:28 -070094 const char* inputColor = nullptr;
bsalomonb5b60322015-09-14 12:26:33 -070095 if (args.fInputColor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -070096 inputColor = "inputColor";
egdaniel4ca2e602015-11-18 08:01:26 -080097 fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -070098 }
wangyix809e5af2015-09-09 12:58:32 -070099
100 // declare outputColor and emit the code for each of the two children
ethannicholas22f939e2016-10-13 13:25:34 -0700101 SkString srcColor("xfer_src");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700102 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700103
ethannicholas22f939e2016-10-13 13:25:34 -0700104 SkString dstColor("xfer_dst");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700105 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700106
107 // emit blend code
Mike Reed7d954ad2016-10-28 15:42:34 -0400108 SkBlendMode mode = cs.getMode();
egdaniel4ca2e602015-11-18 08:01:26 -0800109 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
110 GrGLSLBlend::AppendMode(fragBuilder,
111 srcColor.c_str(),
112 dstColor.c_str(),
113 args.fOutputColor,
114 mode);
wangyix809e5af2015-09-09 12:58:32 -0700115
116 // re-multiply the output color by the input color's alpha
bsalomonf1b7a1d2015-09-28 06:26:28 -0700117 if (args.fInputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800118 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700119 }
wangyix809e5af2015-09-09 12:58:32 -0700120}
121
bungeman06ca8ec2016-06-09 08:01:03 -0700122sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
Mike Reed7d954ad2016-10-28 15:42:34 -0400123 sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700124 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400125 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400126 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bungeman06ca8ec2016-06-09 08:01:03 -0700127 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400128 case SkBlendMode::kSrc:
bungeman06ca8ec2016-06-09 08:01:03 -0700129 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400130 case SkBlendMode::kDst:
bungeman06ca8ec2016-06-09 08:01:03 -0700131 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700132 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700133 return sk_sp<GrFragmentProcessor>(
134 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
bsalomonae4738f2015-09-15 15:33:27 -0700135 }
136}
137
138//////////////////////////////////////////////////////////////////////////////
139
140class ComposeOneFragmentProcessor : public GrFragmentProcessor {
141public:
142 enum Child {
143 kDst_Child,
144 kSrc_Child,
145 };
146
Mike Reed7d954ad2016-10-28 15:42:34 -0400147 ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> dst, SkBlendMode mode, Child child)
bsalomonae4738f2015-09-15 15:33:27 -0700148 : fMode(mode)
149 , fChild(child) {
150 this->initClassID<ComposeOneFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -0700151 SkDEBUGCODE(int dstIndex = )this->registerChildProcessor(std::move(dst));
bsalomonae4738f2015-09-15 15:33:27 -0700152 SkASSERT(0 == dstIndex);
153 }
154
155 const char* name() const override { return "ComposeOne"; }
156
robertphillips783a4da2015-11-19 14:00:02 -0800157 SkString dumpInfo() const override {
158 SkString str;
159
160 for (int i = 0; i < this->numChildProcessors(); ++i) {
161 str.append(this->childProcessor(i).dumpInfo());
162 }
163 return str;
164 }
165
Brian Salomon94efbf52016-11-29 13:43:05 -0500166 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -0400167 GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
168 b->add32((int)fMode | (fChild << 16));
bsalomonae4738f2015-09-15 15:33:27 -0700169 }
170
Mike Reed7d954ad2016-10-28 15:42:34 -0400171 SkBlendMode mode() const { return fMode; }
bsalomonae4738f2015-09-15 15:33:27 -0700172
173 Child child() const { return fChild; }
174
175protected:
176 bool onIsEqual(const GrFragmentProcessor& that) const override {
177 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
178 }
179
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);
Brian Salomonaab259e2017-01-17 10:44:34 -0500185 GrInvariantOutput childOutput(0xFFFFFFFF, kRGBA_GrColorComponentFlags);
bsalomonae4738f2015-09-15 15:33:27 -0700186 this->childProcessor(0).computeInvariantOutput(&childOutput);
187 GrColor blendColor;
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);
194 } else {
195 GrGetCoeffBlendKnownComponents(srcCoeff, dstCoeff,
196 childOutput.color(), childOutput.validFlags(),
197 inout->color(), inout->validFlags(),
198 &blendColor, &blendFlags);
199 }
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;
205 }
206 } else {
207 if (kZero_GrBlendCoeff != dstCoeff || GrBlendCoeffRefsDst(srcCoeff)) {
208 readsInput = GrInvariantOutput::kWill_ReadInput;
209 }
210 }
211 inout->setToOther(blendFlags, blendColor, readsInput);
212 } else {
213 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
214 }
215 }
216
217private:
egdaniel57d3b032015-11-13 11:57:27 -0800218 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700219
Mike Reed7d954ad2016-10-28 15:42:34 -0400220 SkBlendMode fMode;
221 Child fChild;
bsalomonae4738f2015-09-15 15:33:27 -0700222
223 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
224
225 typedef GrFragmentProcessor INHERITED;
226};
227
228//////////////////////////////////////////////////////////////////////////////
229
egdaniel64c47282015-11-13 06:54:19 -0800230class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
bsalomonae4738f2015-09-15 15:33:27 -0700231public:
bsalomonae4738f2015-09-15 15:33:27 -0700232 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800233 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Mike Reed7d954ad2016-10-28 15:42:34 -0400234 SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
bsalomonae4738f2015-09-15 15:33:27 -0700235 ComposeOneFragmentProcessor::Child child =
236 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700237 SkString childColor("child");
238 this->emitChild(0, nullptr, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700239
240 const char* inputColor = args.fInputColor;
241 // We don't try to optimize for this case at all
242 if (!inputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800243 fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
bsalomonae4738f2015-09-15 15:33:27 -0700244 inputColor = "ones";
245 }
246
247 // emit blend code
egdaniel4ca2e602015-11-18 08:01:26 -0800248 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700249 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700250 if (ComposeOneFragmentProcessor::kDst_Child == child) {
egdaniel4ca2e602015-11-18 08:01:26 -0800251 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700252 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800253 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700254 }
bsalomonae4738f2015-09-15 15:33:27 -0700255 }
256
257private:
egdaniel64c47282015-11-13 06:54:19 -0800258 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonae4738f2015-09-15 15:33:27 -0700259};
260
261/////////////////////////////////////////////////////////////////////
262
263GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
264
bungeman06ca8ec2016-06-09 08:01:03 -0700265sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
bsalomonae4738f2015-09-15 15:33:27 -0700266 // 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.
bungeman06ca8ec2016-06-09 08:01:03 -0700269 sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
Mike Reed7d954ad2016-10-28 15:42:34 -0400270 SkBlendMode mode = static_cast<SkBlendMode>(
271 d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
bsalomonae4738f2015-09-15 15:33:27 -0700272 ComposeOneFragmentProcessor::Child child = d->fRandom->nextBool() ?
273 ComposeOneFragmentProcessor::kDst_Child :
274 ComposeOneFragmentProcessor::kSrc_Child;
bungeman06ca8ec2016-06-09 08:01:03 -0700275 return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700276}
277
egdaniel57d3b032015-11-13 11:57:27 -0800278GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800279 return new GLComposeOneFragmentProcessor;
bsalomonae4738f2015-09-15 15:33:27 -0700280}
281
282//////////////////////////////////////////////////////////////////////////////
283
bungeman06ca8ec2016-06-09 08:01:03 -0700284sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400285 sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700286 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400287 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400288 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bsalomonae4738f2015-09-15 15:33:27 -0700289 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400290 case SkBlendMode::kSrc:
bsalomonae4738f2015-09-15 15:33:27 -0700291 return nullptr;
292 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700293 return sk_sp<GrFragmentProcessor>(
294 new ComposeOneFragmentProcessor(std::move(dst), mode,
295 ComposeOneFragmentProcessor::kDst_Child));
bsalomonae4738f2015-09-15 15:33:27 -0700296 }
297}
298
bungeman06ca8ec2016-06-09 08:01:03 -0700299sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400300 sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700301 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400302 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400303 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bsalomonae4738f2015-09-15 15:33:27 -0700304 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400305 case SkBlendMode::kDst:
bsalomonae4738f2015-09-15 15:33:27 -0700306 return nullptr;
307 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700308 return sk_sp<GrFragmentProcessor>(
309 new ComposeOneFragmentProcessor(src, mode,
310 ComposeOneFragmentProcessor::kSrc_Child));
wangyix809e5af2015-09-09 12:58:32 -0700311 }
312}