blob: aa1c1c7c9d03df4ef63efff6865f5f792dc1c6b9 [file] [log] [blame]
wangyix809e5af2015-09-09 12:58:32 -07001/*
Brian Salomona12c1532017-02-13 12:41:44 -05002 * 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 */
wangyix809e5af2015-09-09 12:58:32 -07007
Robert Phillips54cbcd72017-04-20 17:20:24 -04008#include "GrXfermodeFragmentProcessor.h"
wangyix809e5af2015-09-09 12:58:32 -07009
Robert Phillips54cbcd72017-04-20 17:20:24 -040010#include "GrConstColorProcessor.h"
wangyix809e5af2015-09-09 12:58:32 -070011#include "GrFragmentProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080012#include "glsl/GrGLSLFragmentProcessor.h"
13#include "glsl/GrGLSLBlend.h"
egdaniel2d721d32015-11-11 13:06:05 -080014#include "glsl/GrGLSLFragmentShaderBuilder.h"
Brian Osman3b655982017-03-07 16:58:08 -050015#include "SkGr.h"
Mike Reed6b3542a2017-06-06 10:41:18 -040016#include "SkXfermodePriv.h"
wangyix809e5af2015-09-09 12:58:32 -070017
Brian Salomon246a3c22017-02-10 16:16:21 -050018// Some of the cpu implementations of blend modes differ too much from the GPU enough that
19// we can't use the cpu implementation to implement constantOutputForConstantInput.
20static inline bool does_cpu_blend_impl_match_gpu(SkBlendMode mode) {
21 // The non-seperable modes differ too much. So does SoftLight. ColorBurn differs too much on our
22 // test iOS device (but we just disable it across the aboard since it may happen on untested
23 // GPUs).
24 return mode <= SkBlendMode::kLastSeparableMode && mode != SkBlendMode::kSoftLight &&
25 mode != SkBlendMode::kColorBurn;
26}
27
28//////////////////////////////////////////////////////////////////////////////
29
bsalomonae4738f2015-09-15 15:33:27 -070030class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -070031public:
bungeman06ca8ec2016-06-09 08:01:03 -070032 ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
Mike Reed7d954ad2016-10-28 15:42:34 -040033 SkBlendMode mode)
Brian Salomon587e08f2017-01-27 10:59:27 -050034 : INHERITED(OptFlags(src.get(), dst.get(), mode)), fMode(mode) {
bsalomonae4738f2015-09-15 15:33:27 -070035 this->initClassID<ComposeTwoFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -070036 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
37 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
wangyix809e5af2015-09-09 12:58:32 -070038 SkASSERT(0 == shaderAChildIndex);
39 SkASSERT(1 == shaderBChildIndex);
40 }
41
bsalomonae4738f2015-09-15 15:33:27 -070042 const char* name() const override { return "ComposeTwo"; }
wangyix809e5af2015-09-09 12:58:32 -070043
Brian Osmanbd1f76f2017-03-15 11:33:12 -040044 SkString dumpInfo() const override {
45 SkString str;
46
47 str.appendf("Mode: %s", SkBlendMode_Name(fMode));
48
49 for (int i = 0; i < this->numChildProcessors(); ++i) {
50 str.appendf(" [%s %s]",
51 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
52 }
53 return str;
54 }
55
Brian Salomon94efbf52016-11-29 13:43:05 -050056 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -040057 b->add32((int)fMode);
wangyix809e5af2015-09-09 12:58:32 -070058 }
59
Mike Reed7d954ad2016-10-28 15:42:34 -040060 SkBlendMode getMode() const { return fMode; }
wangyix809e5af2015-09-09 12:58:32 -070061
Brian Salomon587e08f2017-01-27 10:59:27 -050062private:
63 static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
64 const GrFragmentProcessor* dst, SkBlendMode mode) {
Brian Salomona12c1532017-02-13 12:41:44 -050065 OptimizationFlags flags;
66 switch (mode) {
67 case SkBlendMode::kClear:
68 case SkBlendMode::kSrc:
69 case SkBlendMode::kDst:
70 SkFAIL("Should never create clear, src, or dst compose two FP.");
71 flags = kNone_OptimizationFlags;
72 break;
73
74 // Produces opaque if both src and dst are opaque.
75 case SkBlendMode::kSrcIn:
76 case SkBlendMode::kDstIn:
77 case SkBlendMode::kModulate:
78 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
79 ? kPreservesOpaqueInput_OptimizationFlag
80 : kNone_OptimizationFlags;
81 break;
82
83 // Produces zero when both are opaque, indeterminate if one is opaque.
84 case SkBlendMode::kSrcOut:
85 case SkBlendMode::kDstOut:
86 case SkBlendMode::kXor:
87 flags = kNone_OptimizationFlags;
88 break;
89
90 // Is opaque if the dst is opaque.
91 case SkBlendMode::kSrcATop:
92 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
93 : kNone_OptimizationFlags;
94 break;
95
96 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
97 case SkBlendMode::kDstATop:
98 case SkBlendMode::kScreen:
99 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
100 : kNone_OptimizationFlags;
101 break;
102
103 // These modes are all opaque if either src or dst is opaque. All the advanced modes
104 // compute alpha as src-over.
105 case SkBlendMode::kSrcOver:
106 case SkBlendMode::kDstOver:
107 case SkBlendMode::kPlus:
108 case SkBlendMode::kOverlay:
109 case SkBlendMode::kDarken:
110 case SkBlendMode::kLighten:
111 case SkBlendMode::kColorDodge:
112 case SkBlendMode::kColorBurn:
113 case SkBlendMode::kHardLight:
114 case SkBlendMode::kSoftLight:
115 case SkBlendMode::kDifference:
116 case SkBlendMode::kExclusion:
117 case SkBlendMode::kMultiply:
118 case SkBlendMode::kHue:
119 case SkBlendMode::kSaturation:
120 case SkBlendMode::kColor:
121 case SkBlendMode::kLuminosity:
122 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
123 ? kPreservesOpaqueInput_OptimizationFlag
124 : kNone_OptimizationFlags;
125 break;
126 }
Brian Salomon246a3c22017-02-10 16:16:21 -0500127 if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
128 dst->hasConstantOutputForConstantInput()) {
Brian Salomona12c1532017-02-13 12:41:44 -0500129 flags |= kConstantOutputForConstantInput_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500130 }
Brian Salomona12c1532017-02-13 12:41:44 -0500131 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500132 }
133
wangyix809e5af2015-09-09 12:58:32 -0700134 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -0700135 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700136 return fMode == cs.fMode;
137 }
138
Brian Salomon587e08f2017-01-27 10:59:27 -0500139 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
140 float alpha = input.fRGBA[3];
141 input = input.opaque();
142 GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
143 GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
144 SkPM4f src = GrColor4fToSkPM4f(srcColor);
145 SkPM4f dst = GrColor4fToSkPM4f(dstColor);
146 auto proc = SkXfermode::GetProc4f(fMode);
147 return SkPM4fToGrColor4f(proc(src, dst)).mulByScalar(alpha);
148 }
149
egdaniel57d3b032015-11-13 11:57:27 -0800150 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyix809e5af2015-09-09 12:58:32 -0700151
Mike Reed7d954ad2016-10-28 15:42:34 -0400152 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -0700153
154 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
155
156 typedef GrFragmentProcessor INHERITED;
157};
158
159/////////////////////////////////////////////////////////////////////
160
egdaniel64c47282015-11-13 06:54:19 -0800161class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -0700162public:
wangyix809e5af2015-09-09 12:58:32 -0700163 void emitCode(EmitArgs&) override;
164
165private:
egdaniel64c47282015-11-13 06:54:19 -0800166 typedef GrGLSLFragmentProcessor INHERITED;
wangyix809e5af2015-09-09 12:58:32 -0700167};
168
169/////////////////////////////////////////////////////////////////////
170
bsalomonae4738f2015-09-15 15:33:27 -0700171GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -0700172
Hal Canary6f6961e2017-01-31 13:50:44 -0500173#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700174sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -0700175 // Create two random frag procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700176 sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
177 sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
wangyix809e5af2015-09-09 12:58:32 -0700178
Brian Salomona12c1532017-02-13 12:41:44 -0500179 SkBlendMode mode;
180 do {
181 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
182 } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
bungeman06ca8ec2016-06-09 08:01:03 -0700183 return sk_sp<GrFragmentProcessor>(
184 new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
wangyix809e5af2015-09-09 12:58:32 -0700185}
Hal Canary6f6961e2017-01-31 13:50:44 -0500186#endif
wangyix809e5af2015-09-09 12:58:32 -0700187
egdaniel57d3b032015-11-13 11:57:27 -0800188GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
robertphillips9cdb9922016-02-03 12:25:40 -0800189 return new GLComposeTwoFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -0700190}
191
192/////////////////////////////////////////////////////////////////////
193
bsalomonae4738f2015-09-15 15:33:27 -0700194void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -0700195
cdalton85285412016-02-18 12:37:07 -0800196 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonae4738f2015-09-15 15:33:27 -0700197 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700198
bsalomonf1b7a1d2015-09-28 06:26:28 -0700199 const char* inputColor = nullptr;
bsalomonb5b60322015-09-14 12:26:33 -0700200 if (args.fInputColor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700201 inputColor = "inputColor";
egdaniel4ca2e602015-11-18 08:01:26 -0800202 fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700203 }
wangyix809e5af2015-09-09 12:58:32 -0700204
205 // declare outputColor and emit the code for each of the two children
ethannicholas22f939e2016-10-13 13:25:34 -0700206 SkString srcColor("xfer_src");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700207 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700208
ethannicholas22f939e2016-10-13 13:25:34 -0700209 SkString dstColor("xfer_dst");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700210 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700211
212 // emit blend code
Mike Reed7d954ad2016-10-28 15:42:34 -0400213 SkBlendMode mode = cs.getMode();
egdaniel4ca2e602015-11-18 08:01:26 -0800214 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
215 GrGLSLBlend::AppendMode(fragBuilder,
216 srcColor.c_str(),
217 dstColor.c_str(),
218 args.fOutputColor,
219 mode);
wangyix809e5af2015-09-09 12:58:32 -0700220
221 // re-multiply the output color by the input color's alpha
bsalomonf1b7a1d2015-09-28 06:26:28 -0700222 if (args.fInputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800223 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700224 }
wangyix809e5af2015-09-09 12:58:32 -0700225}
226
bungeman06ca8ec2016-06-09 08:01:03 -0700227sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
Mike Reed7d954ad2016-10-28 15:42:34 -0400228 sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700229 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400230 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400231 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bungeman06ca8ec2016-06-09 08:01:03 -0700232 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400233 case SkBlendMode::kSrc:
bungeman06ca8ec2016-06-09 08:01:03 -0700234 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400235 case SkBlendMode::kDst:
bungeman06ca8ec2016-06-09 08:01:03 -0700236 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700237 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700238 return sk_sp<GrFragmentProcessor>(
239 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
bsalomonae4738f2015-09-15 15:33:27 -0700240 }
241}
242
243//////////////////////////////////////////////////////////////////////////////
244
245class ComposeOneFragmentProcessor : public GrFragmentProcessor {
246public:
247 enum Child {
248 kDst_Child,
249 kSrc_Child,
250 };
251
Brian Salomona12c1532017-02-13 12:41:44 -0500252 ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode, Child child)
253 : INHERITED(OptFlags(fp.get(), mode, child)), fMode(mode), fChild(child) {
bsalomonae4738f2015-09-15 15:33:27 -0700254 this->initClassID<ComposeOneFragmentProcessor>();
Brian Salomona12c1532017-02-13 12:41:44 -0500255 SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
bsalomonae4738f2015-09-15 15:33:27 -0700256 SkASSERT(0 == dstIndex);
257 }
258
259 const char* name() const override { return "ComposeOne"; }
260
robertphillips783a4da2015-11-19 14:00:02 -0800261 SkString dumpInfo() const override {
262 SkString str;
263
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400264 str.appendf("Mode: %s, Child: %s",
265 SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
266
robertphillips783a4da2015-11-19 14:00:02 -0800267 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400268 str.appendf(" [%s %s]",
269 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
robertphillips783a4da2015-11-19 14:00:02 -0800270 }
271 return str;
272 }
273
Brian Salomon94efbf52016-11-29 13:43:05 -0500274 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -0400275 GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
276 b->add32((int)fMode | (fChild << 16));
bsalomonae4738f2015-09-15 15:33:27 -0700277 }
278
Mike Reed7d954ad2016-10-28 15:42:34 -0400279 SkBlendMode mode() const { return fMode; }
bsalomonae4738f2015-09-15 15:33:27 -0700280
281 Child child() const { return fChild; }
282
Brian Salomon587e08f2017-01-27 10:59:27 -0500283private:
Brian Salomona12c1532017-02-13 12:41:44 -0500284 OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
285 OptimizationFlags flags;
286 switch (mode) {
287 case SkBlendMode::kClear:
288 SkFAIL("Should never create clear compose one FP.");
289 flags = kNone_OptimizationFlags;
290 break;
291
292 case SkBlendMode::kSrc:
293 SkASSERT(child == kSrc_Child);
294 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
295 : kNone_OptimizationFlags;
296 break;
297
298 case SkBlendMode::kDst:
299 SkASSERT(child == kDst_Child);
300 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
301 : kNone_OptimizationFlags;
302 break;
303
304 // Produces opaque if both src and dst are opaque. These also will modulate the child's
Brian Salomone0265112017-02-21 14:19:07 -0500305 // output by either the input color or alpha. However, if the child is not compatible
306 // with the coverage as alpha then it may produce a color that is not valid premul.
Brian Salomona12c1532017-02-13 12:41:44 -0500307 case SkBlendMode::kSrcIn:
308 case SkBlendMode::kDstIn:
309 case SkBlendMode::kModulate:
Brian Salomone0265112017-02-21 14:19:07 -0500310 if (fp->compatibleWithCoverageAsAlpha()) {
311 if (fp->preservesOpaqueInput()) {
312 flags = kPreservesOpaqueInput_OptimizationFlag |
313 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
314 } else {
315 flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
316 }
Brian Salomonf3b995b2017-02-15 10:22:23 -0500317 } else {
Brian Salomone0265112017-02-21 14:19:07 -0500318 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
319 : kNone_OptimizationFlags;
Brian Salomonf3b995b2017-02-15 10:22:23 -0500320 }
Brian Salomona12c1532017-02-13 12:41:44 -0500321 break;
322
323 // Produces zero when both are opaque, indeterminate if one is opaque.
324 case SkBlendMode::kSrcOut:
325 case SkBlendMode::kDstOut:
326 case SkBlendMode::kXor:
327 flags = kNone_OptimizationFlags;
328 break;
329
330 // Is opaque if the dst is opaque.
331 case SkBlendMode::kSrcATop:
332 if (child == kDst_Child) {
333 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
334 : kNone_OptimizationFlags;
335 } else {
336 flags = kPreservesOpaqueInput_OptimizationFlag;
337 }
338 break;
339
340 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
341 case SkBlendMode::kDstATop:
342 case SkBlendMode::kScreen:
343 if (child == kSrc_Child) {
344 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
345 : kNone_OptimizationFlags;
346 } else {
347 flags = kPreservesOpaqueInput_OptimizationFlag;
348 }
349 break;
350
351 // These modes are all opaque if either src or dst is opaque. All the advanced modes
352 // compute alpha as src-over.
353 case SkBlendMode::kSrcOver:
354 case SkBlendMode::kDstOver:
355 case SkBlendMode::kPlus:
356 case SkBlendMode::kOverlay:
357 case SkBlendMode::kDarken:
358 case SkBlendMode::kLighten:
359 case SkBlendMode::kColorDodge:
360 case SkBlendMode::kColorBurn:
361 case SkBlendMode::kHardLight:
362 case SkBlendMode::kSoftLight:
363 case SkBlendMode::kDifference:
364 case SkBlendMode::kExclusion:
365 case SkBlendMode::kMultiply:
366 case SkBlendMode::kHue:
367 case SkBlendMode::kSaturation:
368 case SkBlendMode::kColor:
369 case SkBlendMode::kLuminosity:
370 flags = kPreservesOpaqueInput_OptimizationFlag;
371 break;
Brian Salomon587e08f2017-01-27 10:59:27 -0500372 }
Brian Salomona12c1532017-02-13 12:41:44 -0500373 if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
374 flags |= kConstantOutputForConstantInput_OptimizationFlag;
375 }
376 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500377 }
378
bsalomonae4738f2015-09-15 15:33:27 -0700379 bool onIsEqual(const GrFragmentProcessor& that) const override {
380 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
381 }
382
Brian Salomon587e08f2017-01-27 10:59:27 -0500383 GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
384 GrColor4f childColor =
385 ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
386 SkPM4f src, dst;
387 if (kSrc_Child == fChild) {
388 src = GrColor4fToSkPM4f(childColor);
389 dst = GrColor4fToSkPM4f(inputColor);
390 } else {
391 src = GrColor4fToSkPM4f(inputColor);
392 dst = GrColor4fToSkPM4f(childColor);
393 }
394 auto proc = SkXfermode::GetProc4f(fMode);
395 return SkPM4fToGrColor4f(proc(src, dst));
396 }
397
bsalomonae4738f2015-09-15 15:33:27 -0700398private:
egdaniel57d3b032015-11-13 11:57:27 -0800399 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700400
Mike Reed7d954ad2016-10-28 15:42:34 -0400401 SkBlendMode fMode;
402 Child fChild;
bsalomonae4738f2015-09-15 15:33:27 -0700403
404 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
405
406 typedef GrFragmentProcessor INHERITED;
407};
408
409//////////////////////////////////////////////////////////////////////////////
410
egdaniel64c47282015-11-13 06:54:19 -0800411class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
bsalomonae4738f2015-09-15 15:33:27 -0700412public:
bsalomonae4738f2015-09-15 15:33:27 -0700413 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800414 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Mike Reed7d954ad2016-10-28 15:42:34 -0400415 SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
bsalomonae4738f2015-09-15 15:33:27 -0700416 ComposeOneFragmentProcessor::Child child =
417 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700418 SkString childColor("child");
Ethan Nicholas2983f402017-05-08 09:36:08 -0400419 this->emitChild(0, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700420
421 const char* inputColor = args.fInputColor;
422 // We don't try to optimize for this case at all
423 if (!inputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800424 fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
bsalomonae4738f2015-09-15 15:33:27 -0700425 inputColor = "ones";
426 }
427
428 // emit blend code
egdaniel4ca2e602015-11-18 08:01:26 -0800429 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700430 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700431 if (ComposeOneFragmentProcessor::kDst_Child == child) {
egdaniel4ca2e602015-11-18 08:01:26 -0800432 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700433 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800434 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700435 }
bsalomonae4738f2015-09-15 15:33:27 -0700436 }
437
438private:
egdaniel64c47282015-11-13 06:54:19 -0800439 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonae4738f2015-09-15 15:33:27 -0700440};
441
442/////////////////////////////////////////////////////////////////////
443
444GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
445
Hal Canary6f6961e2017-01-31 13:50:44 -0500446#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700447sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
bsalomonae4738f2015-09-15 15:33:27 -0700448 // Create one random frag procs.
449 // For now, we'll prevent either children from being a shader with children to prevent the
450 // possibility of an arbitrarily large tree of procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700451 sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
Brian Salomona12c1532017-02-13 12:41:44 -0500452 SkBlendMode mode;
453 ComposeOneFragmentProcessor::Child child;
454 do {
455 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
456 child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
457 } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
458 (SkBlendMode::kSrc == mode && child == kDst_Child));
bungeman06ca8ec2016-06-09 08:01:03 -0700459 return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700460}
Hal Canary6f6961e2017-01-31 13:50:44 -0500461#endif
bsalomonae4738f2015-09-15 15:33:27 -0700462
egdaniel57d3b032015-11-13 11:57:27 -0800463GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800464 return new GLComposeOneFragmentProcessor;
bsalomonae4738f2015-09-15 15:33:27 -0700465}
466
467//////////////////////////////////////////////////////////////////////////////
468
Brian Salomona12c1532017-02-13 12:41:44 -0500469// It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
470// that these factories could simply return the input FP. However, that doesn't have quite
471// the same effect as the returned compose FP will replace the FP's input with solid white and
472// ignore the original input. This could be implemented as:
473// RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
474
bungeman06ca8ec2016-06-09 08:01:03 -0700475sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400476 sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700477 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400478 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400479 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500480 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400481 case SkBlendMode::kSrc:
bsalomonae4738f2015-09-15 15:33:27 -0700482 return nullptr;
483 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700484 return sk_sp<GrFragmentProcessor>(
485 new ComposeOneFragmentProcessor(std::move(dst), mode,
486 ComposeOneFragmentProcessor::kDst_Child));
bsalomonae4738f2015-09-15 15:33:27 -0700487 }
488}
489
bungeman06ca8ec2016-06-09 08:01:03 -0700490sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400491 sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700492 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400493 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400494 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500495 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400496 case SkBlendMode::kDst:
bsalomonae4738f2015-09-15 15:33:27 -0700497 return nullptr;
498 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700499 return sk_sp<GrFragmentProcessor>(
Brian Salomona12c1532017-02-13 12:41:44 -0500500 new ComposeOneFragmentProcessor(std::move(src), mode,
bungeman06ca8ec2016-06-09 08:01:03 -0700501 ComposeOneFragmentProcessor::kSrc_Child));
wangyix809e5af2015-09-09 12:58:32 -0700502 }
503}