blob: 3b9b44cd577ea9e00fca23f6661dc922efdfce77 [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:
Brian Salomonaff329b2017-08-11 09:40:37 -040032 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> src,
33 std::unique_ptr<GrFragmentProcessor> dst,
34 SkBlendMode mode) {
35 return std::unique_ptr<GrFragmentProcessor>(
36 new ComposeTwoFragmentProcessor(std::move(src), 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 Salomonaff329b2017-08-11 09:40:37 -040053 std::unique_ptr<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:
Brian Salomonaff329b2017-08-11 09:40:37 -040058 ComposeTwoFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
59 std::unique_ptr<GrFragmentProcessor> dst,
Robert Phillips1c9686b2017-06-30 08:40:28 -040060 SkBlendMode mode)
Brian Salomonaff329b2017-08-11 09:40:37 -040061 : INHERITED(OptFlags(src.get(), dst.get(), mode)), fMode(mode) {
Robert Phillips1c9686b2017-06-30 08:40:28 -040062 this->initClassID<ComposeTwoFragmentProcessor>();
63 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
64 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
65 SkASSERT(0 == shaderAChildIndex);
66 SkASSERT(1 == shaderBChildIndex);
67 }
68
Brian Salomon587e08f2017-01-27 10:59:27 -050069 static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
70 const GrFragmentProcessor* dst, SkBlendMode mode) {
Brian Salomona12c1532017-02-13 12:41:44 -050071 OptimizationFlags flags;
72 switch (mode) {
73 case SkBlendMode::kClear:
74 case SkBlendMode::kSrc:
75 case SkBlendMode::kDst:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -040076 SK_ABORT("Should never create clear, src, or dst compose two FP.");
Brian Salomona12c1532017-02-13 12:41:44 -050077 flags = kNone_OptimizationFlags;
78 break;
79
80 // Produces opaque if both src and dst are opaque.
81 case SkBlendMode::kSrcIn:
82 case SkBlendMode::kDstIn:
83 case SkBlendMode::kModulate:
84 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
85 ? kPreservesOpaqueInput_OptimizationFlag
86 : kNone_OptimizationFlags;
87 break;
88
89 // Produces zero when both are opaque, indeterminate if one is opaque.
90 case SkBlendMode::kSrcOut:
91 case SkBlendMode::kDstOut:
92 case SkBlendMode::kXor:
93 flags = kNone_OptimizationFlags;
94 break;
95
96 // Is opaque if the dst is opaque.
97 case SkBlendMode::kSrcATop:
98 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
99 : kNone_OptimizationFlags;
100 break;
101
102 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
103 case SkBlendMode::kDstATop:
104 case SkBlendMode::kScreen:
105 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
106 : kNone_OptimizationFlags;
107 break;
108
109 // These modes are all opaque if either src or dst is opaque. All the advanced modes
110 // compute alpha as src-over.
111 case SkBlendMode::kSrcOver:
112 case SkBlendMode::kDstOver:
113 case SkBlendMode::kPlus:
114 case SkBlendMode::kOverlay:
115 case SkBlendMode::kDarken:
116 case SkBlendMode::kLighten:
117 case SkBlendMode::kColorDodge:
118 case SkBlendMode::kColorBurn:
119 case SkBlendMode::kHardLight:
120 case SkBlendMode::kSoftLight:
121 case SkBlendMode::kDifference:
122 case SkBlendMode::kExclusion:
123 case SkBlendMode::kMultiply:
124 case SkBlendMode::kHue:
125 case SkBlendMode::kSaturation:
126 case SkBlendMode::kColor:
127 case SkBlendMode::kLuminosity:
128 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
129 ? kPreservesOpaqueInput_OptimizationFlag
130 : kNone_OptimizationFlags;
131 break;
132 }
Brian Salomon246a3c22017-02-10 16:16:21 -0500133 if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
134 dst->hasConstantOutputForConstantInput()) {
Brian Salomona12c1532017-02-13 12:41:44 -0500135 flags |= kConstantOutputForConstantInput_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500136 }
Brian Salomona12c1532017-02-13 12:41:44 -0500137 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500138 }
139
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400140 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
141 b->add32((int)fMode);
142 }
143
wangyix809e5af2015-09-09 12:58:32 -0700144 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -0700145 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700146 return fMode == cs.fMode;
147 }
148
Brian Salomon587e08f2017-01-27 10:59:27 -0500149 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000150 float alpha = input.fRGBA[3];
151 input = input.opaque();
Brian Salomon587e08f2017-01-27 10:59:27 -0500152 GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
153 GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
154 SkPM4f src = GrColor4fToSkPM4f(srcColor);
155 SkPM4f dst = GrColor4fToSkPM4f(dstColor);
Mike Reedf066ac92017-06-09 14:36:59 -0400156 SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000157 return SkPM4fToGrColor4f(res).mulByScalar(alpha);
Brian Salomon587e08f2017-01-27 10:59:27 -0500158 }
159
egdaniel57d3b032015-11-13 11:57:27 -0800160 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyix809e5af2015-09-09 12:58:32 -0700161
Mike Reed7d954ad2016-10-28 15:42:34 -0400162 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -0700163
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400164 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
wangyix809e5af2015-09-09 12:58:32 -0700165
166 typedef GrFragmentProcessor INHERITED;
167};
168
169/////////////////////////////////////////////////////////////////////
170
egdaniel64c47282015-11-13 06:54:19 -0800171class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -0700172public:
wangyix809e5af2015-09-09 12:58:32 -0700173 void emitCode(EmitArgs&) override;
174
175private:
egdaniel64c47282015-11-13 06:54:19 -0800176 typedef GrGLSLFragmentProcessor INHERITED;
wangyix809e5af2015-09-09 12:58:32 -0700177};
178
179/////////////////////////////////////////////////////////////////////
180
bsalomonae4738f2015-09-15 15:33:27 -0700181GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -0700182
Hal Canary6f6961e2017-01-31 13:50:44 -0500183#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400184std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(
185 GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -0700186 // Create two random frag procs.
Brian Salomonaff329b2017-08-11 09:40:37 -0400187 std::unique_ptr<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
188 std::unique_ptr<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);
Brian Salomonaff329b2017-08-11 09:40:37 -0400194 return std::unique_ptr<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 Salomonaff329b2017-08-11 09:40:37 -0400199std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::clone() const {
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400200 auto src = this->childProcessor(0).clone();
201 auto dst = this->childProcessor(1).clone();
Brian Salomonaff329b2017-08-11 09:40:37 -0400202 return std::unique_ptr<GrFragmentProcessor>(
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400203 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), fMode));
204}
205
egdaniel57d3b032015-11-13 11:57:27 -0800206GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
robertphillips9cdb9922016-02-03 12:25:40 -0800207 return new GLComposeTwoFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -0700208}
209
210/////////////////////////////////////////////////////////////////////
211
bsalomonae4738f2015-09-15 15:33:27 -0700212void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -0700213
cdalton85285412016-02-18 12:37:07 -0800214 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonae4738f2015-09-15 15:33:27 -0700215 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700216
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000217 const char* inputColor = nullptr;
218 if (args.fInputColor) {
219 inputColor = "inputColor";
Brian Salomon1d816b92017-08-17 11:07:59 -0400220 fragBuilder->codeAppendf("float4 inputColor = float4(%s.rgb, 1.0);", args.fInputColor);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000221 }
222
wangyix809e5af2015-09-09 12:58:32 -0700223 // declare outputColor and emit the code for each of the two children
ethannicholas22f939e2016-10-13 13:25:34 -0700224 SkString srcColor("xfer_src");
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000225 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700226
ethannicholas22f939e2016-10-13 13:25:34 -0700227 SkString dstColor("xfer_dst");
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000228 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700229
230 // emit blend code
Mike Reed7d954ad2016-10-28 15:42:34 -0400231 SkBlendMode mode = cs.getMode();
Mike Reedcde90312017-06-07 23:05:45 -0400232 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
egdaniel4ca2e602015-11-18 08:01:26 -0800233 GrGLSLBlend::AppendMode(fragBuilder,
234 srcColor.c_str(),
235 dstColor.c_str(),
236 args.fOutputColor,
237 mode);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000238
239 // re-multiply the output color by the input color's alpha
240 if (args.fInputColor) {
241 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
242 }
wangyix809e5af2015-09-09 12:58:32 -0700243}
244
Brian Salomonaff329b2017-08-11 09:40:37 -0400245std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
246 std::unique_ptr<GrFragmentProcessor> src,
247 std::unique_ptr<GrFragmentProcessor> dst,
248 SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700249 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400250 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400251 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bungeman06ca8ec2016-06-09 08:01:03 -0700252 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400253 case SkBlendMode::kSrc:
bungeman06ca8ec2016-06-09 08:01:03 -0700254 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400255 case SkBlendMode::kDst:
bungeman06ca8ec2016-06-09 08:01:03 -0700256 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700257 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400258 return ComposeTwoFragmentProcessor::Make(std::move(src), std::move(dst), mode);
bsalomonae4738f2015-09-15 15:33:27 -0700259 }
260}
261
262//////////////////////////////////////////////////////////////////////////////
263
264class ComposeOneFragmentProcessor : public GrFragmentProcessor {
265public:
266 enum Child {
267 kDst_Child,
268 kSrc_Child,
269 };
270
Brian Salomonaff329b2017-08-11 09:40:37 -0400271 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
272 SkBlendMode mode, Child child) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400273 if (!fp) {
274 return nullptr;
275 }
Brian Salomonaff329b2017-08-11 09:40:37 -0400276 return std::unique_ptr<GrFragmentProcessor>(
277 new ComposeOneFragmentProcessor(std::move(fp), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700278 }
279
280 const char* name() const override { return "ComposeOne"; }
281
robertphillips783a4da2015-11-19 14:00:02 -0800282 SkString dumpInfo() const override {
283 SkString str;
284
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400285 str.appendf("Mode: %s, Child: %s",
286 SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
287
robertphillips783a4da2015-11-19 14:00:02 -0800288 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400289 str.appendf(" [%s %s]",
290 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
robertphillips783a4da2015-11-19 14:00:02 -0800291 }
292 return str;
293 }
294
Brian Salomonaff329b2017-08-11 09:40:37 -0400295 std::unique_ptr<GrFragmentProcessor> clone() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700296
Mike Reed7d954ad2016-10-28 15:42:34 -0400297 SkBlendMode mode() const { return fMode; }
bsalomonae4738f2015-09-15 15:33:27 -0700298
299 Child child() const { return fChild; }
300
Brian Salomon587e08f2017-01-27 10:59:27 -0500301private:
Brian Salomona12c1532017-02-13 12:41:44 -0500302 OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
303 OptimizationFlags flags;
304 switch (mode) {
305 case SkBlendMode::kClear:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400306 SK_ABORT("Should never create clear compose one FP.");
Brian Salomona12c1532017-02-13 12:41:44 -0500307 flags = kNone_OptimizationFlags;
308 break;
309
310 case SkBlendMode::kSrc:
311 SkASSERT(child == kSrc_Child);
312 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
313 : kNone_OptimizationFlags;
314 break;
315
316 case SkBlendMode::kDst:
317 SkASSERT(child == kDst_Child);
318 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
319 : kNone_OptimizationFlags;
320 break;
321
322 // Produces opaque if both src and dst are opaque. These also will modulate the child's
Brian Salomone0265112017-02-21 14:19:07 -0500323 // output by either the input color or alpha. However, if the child is not compatible
324 // with the coverage as alpha then it may produce a color that is not valid premul.
Brian Salomona12c1532017-02-13 12:41:44 -0500325 case SkBlendMode::kSrcIn:
326 case SkBlendMode::kDstIn:
327 case SkBlendMode::kModulate:
Brian Salomone0265112017-02-21 14:19:07 -0500328 if (fp->compatibleWithCoverageAsAlpha()) {
329 if (fp->preservesOpaqueInput()) {
330 flags = kPreservesOpaqueInput_OptimizationFlag |
331 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
332 } else {
333 flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
334 }
Brian Salomonf3b995b2017-02-15 10:22:23 -0500335 } else {
Brian Salomone0265112017-02-21 14:19:07 -0500336 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
337 : kNone_OptimizationFlags;
Brian Salomonf3b995b2017-02-15 10:22:23 -0500338 }
Brian Salomona12c1532017-02-13 12:41:44 -0500339 break;
340
341 // Produces zero when both are opaque, indeterminate if one is opaque.
342 case SkBlendMode::kSrcOut:
343 case SkBlendMode::kDstOut:
344 case SkBlendMode::kXor:
345 flags = kNone_OptimizationFlags;
346 break;
347
348 // Is opaque if the dst is opaque.
349 case SkBlendMode::kSrcATop:
350 if (child == kDst_Child) {
351 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
352 : kNone_OptimizationFlags;
353 } else {
354 flags = kPreservesOpaqueInput_OptimizationFlag;
355 }
356 break;
357
358 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
359 case SkBlendMode::kDstATop:
360 case SkBlendMode::kScreen:
361 if (child == kSrc_Child) {
362 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
363 : kNone_OptimizationFlags;
364 } else {
365 flags = kPreservesOpaqueInput_OptimizationFlag;
366 }
367 break;
368
369 // These modes are all opaque if either src or dst is opaque. All the advanced modes
370 // compute alpha as src-over.
371 case SkBlendMode::kSrcOver:
372 case SkBlendMode::kDstOver:
373 case SkBlendMode::kPlus:
374 case SkBlendMode::kOverlay:
375 case SkBlendMode::kDarken:
376 case SkBlendMode::kLighten:
377 case SkBlendMode::kColorDodge:
378 case SkBlendMode::kColorBurn:
379 case SkBlendMode::kHardLight:
380 case SkBlendMode::kSoftLight:
381 case SkBlendMode::kDifference:
382 case SkBlendMode::kExclusion:
383 case SkBlendMode::kMultiply:
384 case SkBlendMode::kHue:
385 case SkBlendMode::kSaturation:
386 case SkBlendMode::kColor:
387 case SkBlendMode::kLuminosity:
388 flags = kPreservesOpaqueInput_OptimizationFlag;
389 break;
Brian Salomon587e08f2017-01-27 10:59:27 -0500390 }
Brian Salomona12c1532017-02-13 12:41:44 -0500391 if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
392 flags |= kConstantOutputForConstantInput_OptimizationFlag;
393 }
394 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500395 }
396
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400397 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
398 GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
399 b->add32((int)fMode | (fChild << 16));
400 }
401
bsalomonae4738f2015-09-15 15:33:27 -0700402 bool onIsEqual(const GrFragmentProcessor& that) const override {
403 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
404 }
405
Brian Salomon587e08f2017-01-27 10:59:27 -0500406 GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
407 GrColor4f childColor =
408 ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
409 SkPM4f src, dst;
410 if (kSrc_Child == fChild) {
411 src = GrColor4fToSkPM4f(childColor);
412 dst = GrColor4fToSkPM4f(inputColor);
413 } else {
414 src = GrColor4fToSkPM4f(inputColor);
415 dst = GrColor4fToSkPM4f(childColor);
416 }
Mike Reedf066ac92017-06-09 14:36:59 -0400417 SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
418 return SkPM4fToGrColor4f(res);
Brian Salomon587e08f2017-01-27 10:59:27 -0500419 }
420
bsalomonae4738f2015-09-15 15:33:27 -0700421private:
Brian Salomonaff329b2017-08-11 09:40:37 -0400422 ComposeOneFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, SkBlendMode mode,
423 Child child)
424 : INHERITED(OptFlags(fp.get(), mode, child)), fMode(mode), fChild(child) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400425 this->initClassID<ComposeOneFragmentProcessor>();
426 SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
427 SkASSERT(0 == dstIndex);
428 }
429
egdaniel57d3b032015-11-13 11:57:27 -0800430 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700431
Mike Reed7d954ad2016-10-28 15:42:34 -0400432 SkBlendMode fMode;
433 Child fChild;
bsalomonae4738f2015-09-15 15:33:27 -0700434
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400435 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
bsalomonae4738f2015-09-15 15:33:27 -0700436
437 typedef GrFragmentProcessor INHERITED;
438};
439
440//////////////////////////////////////////////////////////////////////////////
441
egdaniel64c47282015-11-13 06:54:19 -0800442class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
bsalomonae4738f2015-09-15 15:33:27 -0700443public:
bsalomonae4738f2015-09-15 15:33:27 -0700444 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800445 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Mike Reed7d954ad2016-10-28 15:42:34 -0400446 SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
bsalomonae4738f2015-09-15 15:33:27 -0700447 ComposeOneFragmentProcessor::Child child =
448 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700449 SkString childColor("child");
Ethan Nicholas2983f402017-05-08 09:36:08 -0400450 this->emitChild(0, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700451
452 const char* inputColor = args.fInputColor;
453 // We don't try to optimize for this case at all
454 if (!inputColor) {
Brian Salomon1d816b92017-08-17 11:07:59 -0400455 fragBuilder->codeAppendf("const float4 ones = float4(1);");
bsalomonae4738f2015-09-15 15:33:27 -0700456 inputColor = "ones";
457 }
458
459 // emit blend code
Mike Reedcde90312017-06-07 23:05:45 -0400460 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700461 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700462 if (ComposeOneFragmentProcessor::kDst_Child == child) {
egdaniel4ca2e602015-11-18 08:01:26 -0800463 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700464 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800465 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700466 }
bsalomonae4738f2015-09-15 15:33:27 -0700467 }
468
469private:
egdaniel64c47282015-11-13 06:54:19 -0800470 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonae4738f2015-09-15 15:33:27 -0700471};
472
473/////////////////////////////////////////////////////////////////////
474
475GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
476
Hal Canary6f6961e2017-01-31 13:50:44 -0500477#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400478std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(
479 GrProcessorTestData* d) {
bsalomonae4738f2015-09-15 15:33:27 -0700480 // Create one random frag procs.
481 // For now, we'll prevent either children from being a shader with children to prevent the
482 // possibility of an arbitrarily large tree of procs.
Brian Salomonaff329b2017-08-11 09:40:37 -0400483 std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
Brian Salomona12c1532017-02-13 12:41:44 -0500484 SkBlendMode mode;
485 ComposeOneFragmentProcessor::Child child;
486 do {
487 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
488 child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
489 } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
490 (SkBlendMode::kSrc == mode && child == kDst_Child));
Brian Salomonaff329b2017-08-11 09:40:37 -0400491 return std::unique_ptr<GrFragmentProcessor>(
492 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 Salomonaff329b2017-08-11 09:40:37 -0400500std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::clone() const {
501 return std::unique_ptr<GrFragmentProcessor>(
Brian Salomon96271cd2017-07-31 16:27:23 -0400502 new ComposeOneFragmentProcessor(this->childProcessor(0).clone(), fMode, fChild));
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400503}
504
bsalomonae4738f2015-09-15 15:33:27 -0700505//////////////////////////////////////////////////////////////////////////////
506
Brian Salomona12c1532017-02-13 12:41:44 -0500507// It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
508// that these factories could simply return the input FP. However, that doesn't have quite
509// the same effect as the returned compose FP will replace the FP's input with solid white and
510// ignore the original input. This could be implemented as:
511// RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
512
Brian Salomonaff329b2017-08-11 09:40:37 -0400513std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
514 std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700515 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400516 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400517 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500518 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400519 case SkBlendMode::kSrc:
bsalomonae4738f2015-09-15 15:33:27 -0700520 return nullptr;
521 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400522 return ComposeOneFragmentProcessor::Make(std::move(dst), mode,
523 ComposeOneFragmentProcessor::kDst_Child);
bsalomonae4738f2015-09-15 15:33:27 -0700524 }
525}
526
Brian Salomonaff329b2017-08-11 09:40:37 -0400527std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
528 std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700529 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400530 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400531 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500532 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400533 case SkBlendMode::kDst:
bsalomonae4738f2015-09-15 15:33:27 -0700534 return nullptr;
535 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400536 return ComposeOneFragmentProcessor::Make(std::move(src), mode,
537 ComposeOneFragmentProcessor::kSrc_Child);
wangyix809e5af2015-09-09 12:58:32 -0700538 }
539}