blob: 80de68f4c2884a364575efd7b5a637b469183e0c [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:
Robert Phillips1c9686b2017-06-30 08:40:28 -040032 static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> src,
33 sk_sp<GrFragmentProcessor> dst,
34 SkBlendMode mode) {
35 return sk_sp<GrFragmentProcessor>(new ComposeTwoFragmentProcessor(std::move(src),
36 std::move(dst), mode));
wangyix809e5af2015-09-09 12:58:32 -070037 }
38
bsalomonae4738f2015-09-15 15:33:27 -070039 const char* name() const override { return "ComposeTwo"; }
wangyix809e5af2015-09-09 12:58:32 -070040
Brian Osmanbd1f76f2017-03-15 11:33:12 -040041 SkString dumpInfo() const override {
42 SkString str;
43
44 str.appendf("Mode: %s", SkBlendMode_Name(fMode));
45
46 for (int i = 0; i < this->numChildProcessors(); ++i) {
47 str.appendf(" [%s %s]",
48 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
49 }
50 return str;
51 }
52
Brian Salomonfb7c83a2017-07-26 13:57:33 -040053 sk_sp<GrFragmentProcessor> clone() const override;
wangyix809e5af2015-09-09 12:58:32 -070054
Mike Reed7d954ad2016-10-28 15:42:34 -040055 SkBlendMode getMode() const { return fMode; }
wangyix809e5af2015-09-09 12:58:32 -070056
Brian Salomon587e08f2017-01-27 10:59:27 -050057private:
Robert Phillips1c9686b2017-06-30 08:40:28 -040058 ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src,
59 sk_sp<GrFragmentProcessor> dst,
60 SkBlendMode mode)
61 : INHERITED(OptFlags(src.get(), dst.get(), mode))
62 , fMode(mode) {
63 this->initClassID<ComposeTwoFragmentProcessor>();
64 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
65 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
66 SkASSERT(0 == shaderAChildIndex);
67 SkASSERT(1 == shaderBChildIndex);
68 }
69
Brian Salomon587e08f2017-01-27 10:59:27 -050070 static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
71 const GrFragmentProcessor* dst, SkBlendMode mode) {
Brian Salomona12c1532017-02-13 12:41:44 -050072 OptimizationFlags flags;
73 switch (mode) {
74 case SkBlendMode::kClear:
75 case SkBlendMode::kSrc:
76 case SkBlendMode::kDst:
77 SkFAIL("Should never create clear, src, or dst compose two FP.");
78 flags = kNone_OptimizationFlags;
79 break;
80
81 // Produces opaque if both src and dst are opaque.
82 case SkBlendMode::kSrcIn:
83 case SkBlendMode::kDstIn:
84 case SkBlendMode::kModulate:
85 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
86 ? kPreservesOpaqueInput_OptimizationFlag
87 : kNone_OptimizationFlags;
88 break;
89
90 // Produces zero when both are opaque, indeterminate if one is opaque.
91 case SkBlendMode::kSrcOut:
92 case SkBlendMode::kDstOut:
93 case SkBlendMode::kXor:
94 flags = kNone_OptimizationFlags;
95 break;
96
97 // Is opaque if the dst is opaque.
98 case SkBlendMode::kSrcATop:
99 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
100 : kNone_OptimizationFlags;
101 break;
102
103 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
104 case SkBlendMode::kDstATop:
105 case SkBlendMode::kScreen:
106 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
107 : kNone_OptimizationFlags;
108 break;
109
110 // These modes are all opaque if either src or dst is opaque. All the advanced modes
111 // compute alpha as src-over.
112 case SkBlendMode::kSrcOver:
113 case SkBlendMode::kDstOver:
114 case SkBlendMode::kPlus:
115 case SkBlendMode::kOverlay:
116 case SkBlendMode::kDarken:
117 case SkBlendMode::kLighten:
118 case SkBlendMode::kColorDodge:
119 case SkBlendMode::kColorBurn:
120 case SkBlendMode::kHardLight:
121 case SkBlendMode::kSoftLight:
122 case SkBlendMode::kDifference:
123 case SkBlendMode::kExclusion:
124 case SkBlendMode::kMultiply:
125 case SkBlendMode::kHue:
126 case SkBlendMode::kSaturation:
127 case SkBlendMode::kColor:
128 case SkBlendMode::kLuminosity:
129 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
130 ? kPreservesOpaqueInput_OptimizationFlag
131 : kNone_OptimizationFlags;
132 break;
133 }
Brian Salomon246a3c22017-02-10 16:16:21 -0500134 if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
135 dst->hasConstantOutputForConstantInput()) {
Brian Salomona12c1532017-02-13 12:41:44 -0500136 flags |= kConstantOutputForConstantInput_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500137 }
Brian Salomona12c1532017-02-13 12:41:44 -0500138 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500139 }
140
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400141 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
142 b->add32((int)fMode);
143 }
144
wangyix809e5af2015-09-09 12:58:32 -0700145 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -0700146 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700147 return fMode == cs.fMode;
148 }
149
Brian Salomon587e08f2017-01-27 10:59:27 -0500150 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000151 float alpha = input.fRGBA[3];
152 input = input.opaque();
Brian Salomon587e08f2017-01-27 10:59:27 -0500153 GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
154 GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
155 SkPM4f src = GrColor4fToSkPM4f(srcColor);
156 SkPM4f dst = GrColor4fToSkPM4f(dstColor);
Mike Reedf066ac92017-06-09 14:36:59 -0400157 SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000158 return SkPM4fToGrColor4f(res).mulByScalar(alpha);
Brian Salomon587e08f2017-01-27 10:59:27 -0500159 }
160
egdaniel57d3b032015-11-13 11:57:27 -0800161 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyix809e5af2015-09-09 12:58:32 -0700162
Mike Reed7d954ad2016-10-28 15:42:34 -0400163 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -0700164
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400165 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
wangyix809e5af2015-09-09 12:58:32 -0700166
167 typedef GrFragmentProcessor INHERITED;
168};
169
170/////////////////////////////////////////////////////////////////////
171
egdaniel64c47282015-11-13 06:54:19 -0800172class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -0700173public:
wangyix809e5af2015-09-09 12:58:32 -0700174 void emitCode(EmitArgs&) override;
175
176private:
egdaniel64c47282015-11-13 06:54:19 -0800177 typedef GrGLSLFragmentProcessor INHERITED;
wangyix809e5af2015-09-09 12:58:32 -0700178};
179
180/////////////////////////////////////////////////////////////////////
181
bsalomonae4738f2015-09-15 15:33:27 -0700182GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -0700183
Hal Canary6f6961e2017-01-31 13:50:44 -0500184#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700185sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -0700186 // Create two random frag procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700187 sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
188 sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
wangyix809e5af2015-09-09 12:58:32 -0700189
Brian Salomona12c1532017-02-13 12:41:44 -0500190 SkBlendMode mode;
191 do {
192 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
193 } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
bungeman06ca8ec2016-06-09 08:01:03 -0700194 return sk_sp<GrFragmentProcessor>(
195 new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
wangyix809e5af2015-09-09 12:58:32 -0700196}
Hal Canary6f6961e2017-01-31 13:50:44 -0500197#endif
wangyix809e5af2015-09-09 12:58:32 -0700198
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400199sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::clone() const {
200 auto src = this->childProcessor(0).clone();
201 auto dst = this->childProcessor(1).clone();
202 if (!src || !dst) {
203 return nullptr;
204 }
205 return sk_sp<GrFragmentProcessor>(
206 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), fMode));
207}
208
egdaniel57d3b032015-11-13 11:57:27 -0800209GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
robertphillips9cdb9922016-02-03 12:25:40 -0800210 return new GLComposeTwoFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -0700211}
212
213/////////////////////////////////////////////////////////////////////
214
bsalomonae4738f2015-09-15 15:33:27 -0700215void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -0700216
cdalton85285412016-02-18 12:37:07 -0800217 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonae4738f2015-09-15 15:33:27 -0700218 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700219
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000220 const char* inputColor = nullptr;
221 if (args.fInputColor) {
222 inputColor = "inputColor";
223 fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
224 }
225
wangyix809e5af2015-09-09 12:58:32 -0700226 // declare outputColor and emit the code for each of the two children
ethannicholas22f939e2016-10-13 13:25:34 -0700227 SkString srcColor("xfer_src");
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000228 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700229
ethannicholas22f939e2016-10-13 13:25:34 -0700230 SkString dstColor("xfer_dst");
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000231 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700232
233 // emit blend code
Mike Reed7d954ad2016-10-28 15:42:34 -0400234 SkBlendMode mode = cs.getMode();
Mike Reedcde90312017-06-07 23:05:45 -0400235 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
egdaniel4ca2e602015-11-18 08:01:26 -0800236 GrGLSLBlend::AppendMode(fragBuilder,
237 srcColor.c_str(),
238 dstColor.c_str(),
239 args.fOutputColor,
240 mode);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000241
242 // re-multiply the output color by the input color's alpha
243 if (args.fInputColor) {
244 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
245 }
wangyix809e5af2015-09-09 12:58:32 -0700246}
247
bungeman06ca8ec2016-06-09 08:01:03 -0700248sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
Mike Reed7d954ad2016-10-28 15:42:34 -0400249 sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700250 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400251 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400252 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bungeman06ca8ec2016-06-09 08:01:03 -0700253 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400254 case SkBlendMode::kSrc:
bungeman06ca8ec2016-06-09 08:01:03 -0700255 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400256 case SkBlendMode::kDst:
bungeman06ca8ec2016-06-09 08:01:03 -0700257 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700258 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400259 return ComposeTwoFragmentProcessor::Make(std::move(src), std::move(dst), mode);
bsalomonae4738f2015-09-15 15:33:27 -0700260 }
261}
262
263//////////////////////////////////////////////////////////////////////////////
264
265class ComposeOneFragmentProcessor : public GrFragmentProcessor {
266public:
267 enum Child {
268 kDst_Child,
269 kSrc_Child,
270 };
271
Robert Phillips1c9686b2017-06-30 08:40:28 -0400272 static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode,
273 Child child) {
274 if (!fp) {
275 return nullptr;
276 }
277 return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(fp),
278 mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700279 }
280
281 const char* name() const override { return "ComposeOne"; }
282
robertphillips783a4da2015-11-19 14:00:02 -0800283 SkString dumpInfo() const override {
284 SkString str;
285
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400286 str.appendf("Mode: %s, Child: %s",
287 SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
288
robertphillips783a4da2015-11-19 14:00:02 -0800289 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400290 str.appendf(" [%s %s]",
291 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
robertphillips783a4da2015-11-19 14:00:02 -0800292 }
293 return str;
294 }
295
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400296 sk_sp<GrFragmentProcessor> clone() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700297
Mike Reed7d954ad2016-10-28 15:42:34 -0400298 SkBlendMode mode() const { return fMode; }
bsalomonae4738f2015-09-15 15:33:27 -0700299
300 Child child() const { return fChild; }
301
Brian Salomon587e08f2017-01-27 10:59:27 -0500302private:
Brian Salomona12c1532017-02-13 12:41:44 -0500303 OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
304 OptimizationFlags flags;
305 switch (mode) {
306 case SkBlendMode::kClear:
307 SkFAIL("Should never create clear compose one FP.");
308 flags = kNone_OptimizationFlags;
309 break;
310
311 case SkBlendMode::kSrc:
312 SkASSERT(child == kSrc_Child);
313 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
314 : kNone_OptimizationFlags;
315 break;
316
317 case SkBlendMode::kDst:
318 SkASSERT(child == kDst_Child);
319 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
320 : kNone_OptimizationFlags;
321 break;
322
323 // Produces opaque if both src and dst are opaque. These also will modulate the child's
Brian Salomone0265112017-02-21 14:19:07 -0500324 // output by either the input color or alpha. However, if the child is not compatible
325 // with the coverage as alpha then it may produce a color that is not valid premul.
Brian Salomona12c1532017-02-13 12:41:44 -0500326 case SkBlendMode::kSrcIn:
327 case SkBlendMode::kDstIn:
328 case SkBlendMode::kModulate:
Brian Salomone0265112017-02-21 14:19:07 -0500329 if (fp->compatibleWithCoverageAsAlpha()) {
330 if (fp->preservesOpaqueInput()) {
331 flags = kPreservesOpaqueInput_OptimizationFlag |
332 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
333 } else {
334 flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
335 }
Brian Salomonf3b995b2017-02-15 10:22:23 -0500336 } else {
Brian Salomone0265112017-02-21 14:19:07 -0500337 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
338 : kNone_OptimizationFlags;
Brian Salomonf3b995b2017-02-15 10:22:23 -0500339 }
Brian Salomona12c1532017-02-13 12:41:44 -0500340 break;
341
342 // Produces zero when both are opaque, indeterminate if one is opaque.
343 case SkBlendMode::kSrcOut:
344 case SkBlendMode::kDstOut:
345 case SkBlendMode::kXor:
346 flags = kNone_OptimizationFlags;
347 break;
348
349 // Is opaque if the dst is opaque.
350 case SkBlendMode::kSrcATop:
351 if (child == kDst_Child) {
352 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
353 : kNone_OptimizationFlags;
354 } else {
355 flags = kPreservesOpaqueInput_OptimizationFlag;
356 }
357 break;
358
359 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
360 case SkBlendMode::kDstATop:
361 case SkBlendMode::kScreen:
362 if (child == kSrc_Child) {
363 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
364 : kNone_OptimizationFlags;
365 } else {
366 flags = kPreservesOpaqueInput_OptimizationFlag;
367 }
368 break;
369
370 // These modes are all opaque if either src or dst is opaque. All the advanced modes
371 // compute alpha as src-over.
372 case SkBlendMode::kSrcOver:
373 case SkBlendMode::kDstOver:
374 case SkBlendMode::kPlus:
375 case SkBlendMode::kOverlay:
376 case SkBlendMode::kDarken:
377 case SkBlendMode::kLighten:
378 case SkBlendMode::kColorDodge:
379 case SkBlendMode::kColorBurn:
380 case SkBlendMode::kHardLight:
381 case SkBlendMode::kSoftLight:
382 case SkBlendMode::kDifference:
383 case SkBlendMode::kExclusion:
384 case SkBlendMode::kMultiply:
385 case SkBlendMode::kHue:
386 case SkBlendMode::kSaturation:
387 case SkBlendMode::kColor:
388 case SkBlendMode::kLuminosity:
389 flags = kPreservesOpaqueInput_OptimizationFlag;
390 break;
Brian Salomon587e08f2017-01-27 10:59:27 -0500391 }
Brian Salomona12c1532017-02-13 12:41:44 -0500392 if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
393 flags |= kConstantOutputForConstantInput_OptimizationFlag;
394 }
395 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500396 }
397
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400398 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
399 GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
400 b->add32((int)fMode | (fChild << 16));
401 }
402
bsalomonae4738f2015-09-15 15:33:27 -0700403 bool onIsEqual(const GrFragmentProcessor& that) const override {
404 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
405 }
406
Brian Salomon587e08f2017-01-27 10:59:27 -0500407 GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
408 GrColor4f childColor =
409 ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
410 SkPM4f src, dst;
411 if (kSrc_Child == fChild) {
412 src = GrColor4fToSkPM4f(childColor);
413 dst = GrColor4fToSkPM4f(inputColor);
414 } else {
415 src = GrColor4fToSkPM4f(inputColor);
416 dst = GrColor4fToSkPM4f(childColor);
417 }
Mike Reedf066ac92017-06-09 14:36:59 -0400418 SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
419 return SkPM4fToGrColor4f(res);
Brian Salomon587e08f2017-01-27 10:59:27 -0500420 }
421
bsalomonae4738f2015-09-15 15:33:27 -0700422private:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400423 ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode, Child child)
424 : INHERITED(OptFlags(fp.get(), mode, child))
425 , fMode(mode)
426 , fChild(child) {
427 this->initClassID<ComposeOneFragmentProcessor>();
428 SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
429 SkASSERT(0 == dstIndex);
430 }
431
egdaniel57d3b032015-11-13 11:57:27 -0800432 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700433
Mike Reed7d954ad2016-10-28 15:42:34 -0400434 SkBlendMode fMode;
435 Child fChild;
bsalomonae4738f2015-09-15 15:33:27 -0700436
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400437 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
bsalomonae4738f2015-09-15 15:33:27 -0700438
439 typedef GrFragmentProcessor INHERITED;
440};
441
442//////////////////////////////////////////////////////////////////////////////
443
egdaniel64c47282015-11-13 06:54:19 -0800444class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
bsalomonae4738f2015-09-15 15:33:27 -0700445public:
bsalomonae4738f2015-09-15 15:33:27 -0700446 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800447 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Mike Reed7d954ad2016-10-28 15:42:34 -0400448 SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
bsalomonae4738f2015-09-15 15:33:27 -0700449 ComposeOneFragmentProcessor::Child child =
450 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700451 SkString childColor("child");
Ethan Nicholas2983f402017-05-08 09:36:08 -0400452 this->emitChild(0, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700453
454 const char* inputColor = args.fInputColor;
455 // We don't try to optimize for this case at all
456 if (!inputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800457 fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
bsalomonae4738f2015-09-15 15:33:27 -0700458 inputColor = "ones";
459 }
460
461 // emit blend code
Mike Reedcde90312017-06-07 23:05:45 -0400462 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700463 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700464 if (ComposeOneFragmentProcessor::kDst_Child == child) {
egdaniel4ca2e602015-11-18 08:01:26 -0800465 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700466 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800467 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700468 }
bsalomonae4738f2015-09-15 15:33:27 -0700469 }
470
471private:
egdaniel64c47282015-11-13 06:54:19 -0800472 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonae4738f2015-09-15 15:33:27 -0700473};
474
475/////////////////////////////////////////////////////////////////////
476
477GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
478
Hal Canary6f6961e2017-01-31 13:50:44 -0500479#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700480sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
bsalomonae4738f2015-09-15 15:33:27 -0700481 // Create one random frag procs.
482 // For now, we'll prevent either children from being a shader with children to prevent the
483 // possibility of an arbitrarily large tree of procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700484 sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
Brian Salomona12c1532017-02-13 12:41:44 -0500485 SkBlendMode mode;
486 ComposeOneFragmentProcessor::Child child;
487 do {
488 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
489 child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
490 } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
491 (SkBlendMode::kSrc == mode && child == kDst_Child));
bungeman06ca8ec2016-06-09 08:01:03 -0700492 return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700493}
Hal Canary6f6961e2017-01-31 13:50:44 -0500494#endif
bsalomonae4738f2015-09-15 15:33:27 -0700495
egdaniel57d3b032015-11-13 11:57:27 -0800496GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800497 return new GLComposeOneFragmentProcessor;
bsalomonae4738f2015-09-15 15:33:27 -0700498}
499
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400500sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::clone() const {
501 auto child = this->childProcessor(0).clone();
502 if (!child) {
503 return nullptr;
504 }
505 return sk_sp<GrFragmentProcessor>(
506 new ComposeOneFragmentProcessor(std::move(child), fMode, fChild));
507}
508
bsalomonae4738f2015-09-15 15:33:27 -0700509//////////////////////////////////////////////////////////////////////////////
510
Brian Salomona12c1532017-02-13 12:41:44 -0500511// It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
512// that these factories could simply return the input FP. However, that doesn't have quite
513// the same effect as the returned compose FP will replace the FP's input with solid white and
514// ignore the original input. This could be implemented as:
515// RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
516
bungeman06ca8ec2016-06-09 08:01:03 -0700517sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400518 sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700519 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400520 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400521 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500522 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400523 case SkBlendMode::kSrc:
bsalomonae4738f2015-09-15 15:33:27 -0700524 return nullptr;
525 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400526 return ComposeOneFragmentProcessor::Make(std::move(dst), mode,
527 ComposeOneFragmentProcessor::kDst_Child);
bsalomonae4738f2015-09-15 15:33:27 -0700528 }
529}
530
bungeman06ca8ec2016-06-09 08:01:03 -0700531sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400532 sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700533 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400534 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400535 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500536 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400537 case SkBlendMode::kDst:
bsalomonae4738f2015-09-15 15:33:27 -0700538 return nullptr;
539 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400540 return ComposeOneFragmentProcessor::Make(std::move(src), mode,
541 ComposeOneFragmentProcessor::kSrc_Child);
wangyix809e5af2015-09-09 12:58:32 -0700542 }
543}