blob: e207e15adf92e63a0b642179ec3d6b8aa6200703 [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 Osman9a390ac2018-11-12 09:47:48 -050041#ifdef SK_DEBUG
Brian Osmanbd1f76f2017-03-15 11:33:12 -040042 SkString dumpInfo() const override {
43 SkString str;
44
45 str.appendf("Mode: %s", SkBlendMode_Name(fMode));
46
47 for (int i = 0; i < this->numChildProcessors(); ++i) {
48 str.appendf(" [%s %s]",
49 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
50 }
51 return str;
52 }
Brian Osman9a390ac2018-11-12 09:47:48 -050053#endif
Brian Osmanbd1f76f2017-03-15 11:33:12 -040054
Brian Salomonaff329b2017-08-11 09:40:37 -040055 std::unique_ptr<GrFragmentProcessor> clone() const override;
wangyix809e5af2015-09-09 12:58:32 -070056
Mike Reed7d954ad2016-10-28 15:42:34 -040057 SkBlendMode getMode() const { return fMode; }
wangyix809e5af2015-09-09 12:58:32 -070058
Brian Salomon587e08f2017-01-27 10:59:27 -050059private:
Brian Salomonaff329b2017-08-11 09:40:37 -040060 ComposeTwoFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
61 std::unique_ptr<GrFragmentProcessor> dst,
Robert Phillips1c9686b2017-06-30 08:40:28 -040062 SkBlendMode mode)
Ethan Nicholasabff9562017-10-09 10:54:08 -040063 : INHERITED(kComposeTwoFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode))
64 , fMode(mode) {
Robert Phillips1c9686b2017-06-30 08:40:28 -040065 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
66 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
67 SkASSERT(0 == shaderAChildIndex);
68 SkASSERT(1 == shaderBChildIndex);
69 }
70
Brian Salomon587e08f2017-01-27 10:59:27 -050071 static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
72 const GrFragmentProcessor* dst, SkBlendMode mode) {
Brian Salomona12c1532017-02-13 12:41:44 -050073 OptimizationFlags flags;
74 switch (mode) {
75 case SkBlendMode::kClear:
76 case SkBlendMode::kSrc:
77 case SkBlendMode::kDst:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -040078 SK_ABORT("Should never create clear, src, or dst compose two FP.");
Brian Salomona12c1532017-02-13 12:41:44 -050079 flags = kNone_OptimizationFlags;
80 break;
81
82 // Produces opaque if both src and dst are opaque.
83 case SkBlendMode::kSrcIn:
84 case SkBlendMode::kDstIn:
85 case SkBlendMode::kModulate:
86 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
87 ? kPreservesOpaqueInput_OptimizationFlag
88 : kNone_OptimizationFlags;
89 break;
90
91 // Produces zero when both are opaque, indeterminate if one is opaque.
92 case SkBlendMode::kSrcOut:
93 case SkBlendMode::kDstOut:
94 case SkBlendMode::kXor:
95 flags = kNone_OptimizationFlags;
96 break;
97
98 // Is opaque if the dst is opaque.
99 case SkBlendMode::kSrcATop:
100 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
101 : kNone_OptimizationFlags;
102 break;
103
104 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
105 case SkBlendMode::kDstATop:
106 case SkBlendMode::kScreen:
107 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
108 : kNone_OptimizationFlags;
109 break;
110
111 // These modes are all opaque if either src or dst is opaque. All the advanced modes
112 // compute alpha as src-over.
113 case SkBlendMode::kSrcOver:
114 case SkBlendMode::kDstOver:
115 case SkBlendMode::kPlus:
116 case SkBlendMode::kOverlay:
117 case SkBlendMode::kDarken:
118 case SkBlendMode::kLighten:
119 case SkBlendMode::kColorDodge:
120 case SkBlendMode::kColorBurn:
121 case SkBlendMode::kHardLight:
122 case SkBlendMode::kSoftLight:
123 case SkBlendMode::kDifference:
124 case SkBlendMode::kExclusion:
125 case SkBlendMode::kMultiply:
126 case SkBlendMode::kHue:
127 case SkBlendMode::kSaturation:
128 case SkBlendMode::kColor:
129 case SkBlendMode::kLuminosity:
130 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
131 ? kPreservesOpaqueInput_OptimizationFlag
132 : kNone_OptimizationFlags;
133 break;
134 }
Brian Salomon246a3c22017-02-10 16:16:21 -0500135 if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
136 dst->hasConstantOutputForConstantInput()) {
Brian Salomona12c1532017-02-13 12:41:44 -0500137 flags |= kConstantOutputForConstantInput_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500138 }
Brian Salomona12c1532017-02-13 12:41:44 -0500139 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500140 }
141
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400142 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
143 b->add32((int)fMode);
144 }
145
wangyix809e5af2015-09-09 12:58:32 -0700146 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -0700147 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700148 return fMode == cs.fMode;
149 }
150
Brian Osman1d5b5982018-10-01 13:41:39 -0400151 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
152 SkPMColor4f opaqueInput = { input.fR, input.fG, input.fB, 1 };
153 SkPMColor4f src = ConstantOutputForConstantInput(this->childProcessor(0), opaqueInput);
154 SkPMColor4f dst = ConstantOutputForConstantInput(this->childProcessor(1), opaqueInput);
Brian Osmand25b7c12018-09-21 16:01:59 -0400155 SkPMColor4f res = SkBlendMode_Apply(fMode, src, dst);
Brian Osman1d5b5982018-10-01 13:41:39 -0400156 return res * input.fA;
Brian Salomon587e08f2017-01-27 10:59:27 -0500157 }
158
egdaniel57d3b032015-11-13 11:57:27 -0800159 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyix809e5af2015-09-09 12:58:32 -0700160
Mike Reed7d954ad2016-10-28 15:42:34 -0400161 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -0700162
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400163 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
wangyix809e5af2015-09-09 12:58:32 -0700164
165 typedef GrFragmentProcessor INHERITED;
166};
167
168/////////////////////////////////////////////////////////////////////
169
egdaniel64c47282015-11-13 06:54:19 -0800170class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -0700171public:
wangyix809e5af2015-09-09 12:58:32 -0700172 void emitCode(EmitArgs&) override;
173
174private:
egdaniel64c47282015-11-13 06:54:19 -0800175 typedef GrGLSLFragmentProcessor INHERITED;
wangyix809e5af2015-09-09 12:58:32 -0700176};
177
178/////////////////////////////////////////////////////////////////////
179
bsalomonae4738f2015-09-15 15:33:27 -0700180GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -0700181
Hal Canary6f6961e2017-01-31 13:50:44 -0500182#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400183std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(
184 GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -0700185 // Create two random frag procs.
Brian Salomonaff329b2017-08-11 09:40:37 -0400186 std::unique_ptr<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
187 std::unique_ptr<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
wangyix809e5af2015-09-09 12:58:32 -0700188
Brian Salomona12c1532017-02-13 12:41:44 -0500189 SkBlendMode mode;
190 do {
191 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
192 } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
Brian Salomonaff329b2017-08-11 09:40:37 -0400193 return std::unique_ptr<GrFragmentProcessor>(
194 new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
wangyix809e5af2015-09-09 12:58:32 -0700195}
Hal Canary6f6961e2017-01-31 13:50:44 -0500196#endif
wangyix809e5af2015-09-09 12:58:32 -0700197
Brian Salomonaff329b2017-08-11 09:40:37 -0400198std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::clone() const {
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400199 auto src = this->childProcessor(0).clone();
200 auto dst = this->childProcessor(1).clone();
Brian Salomonaff329b2017-08-11 09:40:37 -0400201 return std::unique_ptr<GrFragmentProcessor>(
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400202 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), fMode));
203}
204
egdaniel57d3b032015-11-13 11:57:27 -0800205GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
robertphillips9cdb9922016-02-03 12:25:40 -0800206 return new GLComposeTwoFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -0700207}
208
209/////////////////////////////////////////////////////////////////////
210
bsalomonae4738f2015-09-15 15:33:27 -0700211void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -0700212
cdalton85285412016-02-18 12:37:07 -0800213 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonae4738f2015-09-15 15:33:27 -0700214 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700215
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000216 const char* inputColor = nullptr;
217 if (args.fInputColor) {
218 inputColor = "inputColor";
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400219 fragBuilder->codeAppendf("half4 inputColor = half4(%s.rgb, 1.0);", args.fInputColor);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000220 }
221
wangyix809e5af2015-09-09 12:58:32 -0700222 // declare outputColor and emit the code for each of the two children
ethannicholas22f939e2016-10-13 13:25:34 -0700223 SkString srcColor("xfer_src");
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000224 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700225
ethannicholas22f939e2016-10-13 13:25:34 -0700226 SkString dstColor("xfer_dst");
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000227 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700228
229 // emit blend code
Mike Reed7d954ad2016-10-28 15:42:34 -0400230 SkBlendMode mode = cs.getMode();
Mike Reedcde90312017-06-07 23:05:45 -0400231 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
egdaniel4ca2e602015-11-18 08:01:26 -0800232 GrGLSLBlend::AppendMode(fragBuilder,
233 srcColor.c_str(),
234 dstColor.c_str(),
235 args.fOutputColor,
236 mode);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000237
238 // re-multiply the output color by the input color's alpha
239 if (args.fInputColor) {
240 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
241 }
wangyix809e5af2015-09-09 12:58:32 -0700242}
243
Brian Salomonaff329b2017-08-11 09:40:37 -0400244std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
245 std::unique_ptr<GrFragmentProcessor> src,
246 std::unique_ptr<GrFragmentProcessor> dst,
247 SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700248 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400249 case SkBlendMode::kClear:
Brian Osmanf28e55d2018-10-03 16:35:54 -0400250 return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500251 GrConstColorProcessor::InputMode::kIgnore);
Mike Reed7d954ad2016-10-28 15:42:34 -0400252 case SkBlendMode::kSrc:
bungeman06ca8ec2016-06-09 08:01:03 -0700253 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400254 case SkBlendMode::kDst:
bungeman06ca8ec2016-06-09 08:01:03 -0700255 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700256 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400257 return ComposeTwoFragmentProcessor::Make(std::move(src), std::move(dst), mode);
bsalomonae4738f2015-09-15 15:33:27 -0700258 }
259}
260
261//////////////////////////////////////////////////////////////////////////////
262
263class ComposeOneFragmentProcessor : public GrFragmentProcessor {
264public:
265 enum Child {
266 kDst_Child,
267 kSrc_Child,
268 };
269
Brian Salomonaff329b2017-08-11 09:40:37 -0400270 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
271 SkBlendMode mode, Child child) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400272 if (!fp) {
273 return nullptr;
274 }
Brian Salomonaff329b2017-08-11 09:40:37 -0400275 return std::unique_ptr<GrFragmentProcessor>(
276 new ComposeOneFragmentProcessor(std::move(fp), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700277 }
278
279 const char* name() const override { return "ComposeOne"; }
280
Brian Osman9a390ac2018-11-12 09:47:48 -0500281#ifdef SK_DEBUG
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 }
Brian Osman9a390ac2018-11-12 09:47:48 -0500294#endif
robertphillips783a4da2015-11-19 14:00:02 -0800295
Brian Salomonaff329b2017-08-11 09:40:37 -0400296 std::unique_ptr<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:
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400307 SK_ABORT("Should never create clear compose one FP.");
Brian Salomona12c1532017-02-13 12:41:44 -0500308 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 {
Ben Wagnerb0897652018-06-15 15:37:57 +0000399 GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & UINT16_MAX) == (int)SkBlendMode::kLastMode);
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400400 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 Osman1d5b5982018-10-01 13:41:39 -0400407 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inputColor) const override {
408 SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
Brian Osmanf28e55d2018-10-03 16:35:54 -0400409 SK_PMColor4fWHITE);
Brian Osmand25b7c12018-09-21 16:01:59 -0400410 SkPMColor4f src, dst;
Brian Salomon587e08f2017-01-27 10:59:27 -0500411 if (kSrc_Child == fChild) {
Brian Osman1d5b5982018-10-01 13:41:39 -0400412 src = childColor;
413 dst = inputColor;
Brian Salomon587e08f2017-01-27 10:59:27 -0500414 } else {
Brian Osman1d5b5982018-10-01 13:41:39 -0400415 src = inputColor;
416 dst = childColor;
Brian Salomon587e08f2017-01-27 10:59:27 -0500417 }
Brian Osman1d5b5982018-10-01 13:41:39 -0400418 return SkBlendMode_Apply(fMode, src, dst);
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)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400424 : INHERITED(kComposeOneFragmentProcessor_ClassID, OptFlags(fp.get(), mode, child))
425 , fMode(mode)
426 , fChild(child) {
Robert Phillips1c9686b2017-06-30 08:40:28 -0400427 SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
428 SkASSERT(0 == dstIndex);
429 }
430
egdaniel57d3b032015-11-13 11:57:27 -0800431 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700432
Mike Reed7d954ad2016-10-28 15:42:34 -0400433 SkBlendMode fMode;
434 Child fChild;
bsalomonae4738f2015-09-15 15:33:27 -0700435
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400436 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
bsalomonae4738f2015-09-15 15:33:27 -0700437
438 typedef GrFragmentProcessor INHERITED;
439};
440
441//////////////////////////////////////////////////////////////////////////////
442
egdaniel64c47282015-11-13 06:54:19 -0800443class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
bsalomonae4738f2015-09-15 15:33:27 -0700444public:
bsalomonae4738f2015-09-15 15:33:27 -0700445 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800446 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Mike Reed7d954ad2016-10-28 15:42:34 -0400447 SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
bsalomonae4738f2015-09-15 15:33:27 -0700448 ComposeOneFragmentProcessor::Child child =
449 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700450 SkString childColor("child");
Ethan Nicholas2983f402017-05-08 09:36:08 -0400451 this->emitChild(0, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700452
bsalomonae4738f2015-09-15 15:33:27 -0700453 // emit blend code
Mike Reedcde90312017-06-07 23:05:45 -0400454 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700455 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700456 if (ComposeOneFragmentProcessor::kDst_Child == child) {
Michael Ludwig231de032018-08-30 14:33:01 -0400457 GrGLSLBlend::AppendMode(fragBuilder, args.fInputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700458 } else {
Michael Ludwig231de032018-08-30 14:33:01 -0400459 GrGLSLBlend::AppendMode(fragBuilder, childStr, args.fInputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700460 }
bsalomonae4738f2015-09-15 15:33:27 -0700461 }
462
463private:
egdaniel64c47282015-11-13 06:54:19 -0800464 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonae4738f2015-09-15 15:33:27 -0700465};
466
467/////////////////////////////////////////////////////////////////////
468
469GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
470
Hal Canary6f6961e2017-01-31 13:50:44 -0500471#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400472std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(
473 GrProcessorTestData* d) {
bsalomonae4738f2015-09-15 15:33:27 -0700474 // Create one random frag procs.
475 // For now, we'll prevent either children from being a shader with children to prevent the
476 // possibility of an arbitrarily large tree of procs.
Brian Salomonaff329b2017-08-11 09:40:37 -0400477 std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
Brian Salomona12c1532017-02-13 12:41:44 -0500478 SkBlendMode mode;
479 ComposeOneFragmentProcessor::Child child;
480 do {
481 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
482 child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
483 } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
484 (SkBlendMode::kSrc == mode && child == kDst_Child));
Brian Salomonaff329b2017-08-11 09:40:37 -0400485 return std::unique_ptr<GrFragmentProcessor>(
486 new ComposeOneFragmentProcessor(std::move(dst), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700487}
Hal Canary6f6961e2017-01-31 13:50:44 -0500488#endif
bsalomonae4738f2015-09-15 15:33:27 -0700489
egdaniel57d3b032015-11-13 11:57:27 -0800490GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800491 return new GLComposeOneFragmentProcessor;
bsalomonae4738f2015-09-15 15:33:27 -0700492}
493
Brian Salomonaff329b2017-08-11 09:40:37 -0400494std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::clone() const {
495 return std::unique_ptr<GrFragmentProcessor>(
Brian Salomon96271cd2017-07-31 16:27:23 -0400496 new ComposeOneFragmentProcessor(this->childProcessor(0).clone(), fMode, fChild));
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400497}
498
bsalomonae4738f2015-09-15 15:33:27 -0700499//////////////////////////////////////////////////////////////////////////////
500
Brian Salomona12c1532017-02-13 12:41:44 -0500501// It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
502// that these factories could simply return the input FP. However, that doesn't have quite
503// the same effect as the returned compose FP will replace the FP's input with solid white and
504// ignore the original input. This could be implemented as:
Brian Osmanc6444d22019-01-09 16:30:12 -0500505// RunInSeries(ConstColor(WHITE, kIgnoreInput), inputFP).
Brian Salomona12c1532017-02-13 12:41:44 -0500506
Brian Salomonaff329b2017-08-11 09:40:37 -0400507std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
508 std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700509 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400510 case SkBlendMode::kClear:
Brian Osmanf28e55d2018-10-03 16:35:54 -0400511 return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500512 GrConstColorProcessor::InputMode::kIgnore);
Mike Reed7d954ad2016-10-28 15:42:34 -0400513 case SkBlendMode::kSrc:
bsalomonae4738f2015-09-15 15:33:27 -0700514 return nullptr;
515 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400516 return ComposeOneFragmentProcessor::Make(std::move(dst), mode,
517 ComposeOneFragmentProcessor::kDst_Child);
bsalomonae4738f2015-09-15 15:33:27 -0700518 }
519}
520
Brian Salomonaff329b2017-08-11 09:40:37 -0400521std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
522 std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700523 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400524 case SkBlendMode::kClear:
Brian Osmanf28e55d2018-10-03 16:35:54 -0400525 return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500526 GrConstColorProcessor::InputMode::kIgnore);
Mike Reed7d954ad2016-10-28 15:42:34 -0400527 case SkBlendMode::kDst:
bsalomonae4738f2015-09-15 15:33:27 -0700528 return nullptr;
529 default:
Robert Phillips1c9686b2017-06-30 08:40:28 -0400530 return ComposeOneFragmentProcessor::Make(std::move(src), mode,
531 ComposeOneFragmentProcessor::kSrc_Child);
wangyix809e5af2015-09-09 12:58:32 -0700532 }
533}