• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "GrXfermodeFragmentProcessor.h"
9 
10 #include "GrConstColorProcessor.h"
11 #include "GrFragmentProcessor.h"
12 #include "glsl/GrGLSLFragmentProcessor.h"
13 #include "glsl/GrGLSLBlend.h"
14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "SkGr.h"
16 #include "SkXfermodePriv.h"
17 
18 // 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.
does_cpu_blend_impl_match_gpu(SkBlendMode mode)20 static 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 
30 class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
31 public:
Make(sk_sp<GrFragmentProcessor> src,sk_sp<GrFragmentProcessor> dst,SkBlendMode mode)32     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));
37     }
38 
name() const39     const char* name() const override { return "ComposeTwo"; }
40 
dumpInfo() const41     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 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const53     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
54         b->add32((int)fMode);
55     }
56 
getMode() const57     SkBlendMode getMode() const { return fMode; }
58 
59 private:
ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src,sk_sp<GrFragmentProcessor> dst,SkBlendMode mode)60     ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src,
61                                 sk_sp<GrFragmentProcessor> dst,
62                                 SkBlendMode mode)
63             : INHERITED(OptFlags(src.get(), dst.get(), mode))
64             , fMode(mode) {
65         this->initClassID<ComposeTwoFragmentProcessor>();
66         SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
67         SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
68         SkASSERT(0 == shaderAChildIndex);
69         SkASSERT(1 == shaderBChildIndex);
70     }
71 
OptFlags(const GrFragmentProcessor * src,const GrFragmentProcessor * dst,SkBlendMode mode)72     static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
73                                       const GrFragmentProcessor* dst, SkBlendMode mode) {
74         OptimizationFlags flags;
75         switch (mode) {
76             case SkBlendMode::kClear:
77             case SkBlendMode::kSrc:
78             case SkBlendMode::kDst:
79                 SkFAIL("Should never create clear, src, or dst compose two FP.");
80                 flags = kNone_OptimizationFlags;
81                 break;
82 
83             // Produces opaque if both src and dst are opaque.
84             case SkBlendMode::kSrcIn:
85             case SkBlendMode::kDstIn:
86             case SkBlendMode::kModulate:
87                 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
88                                 ? kPreservesOpaqueInput_OptimizationFlag
89                                 : kNone_OptimizationFlags;
90                 break;
91 
92             // Produces zero when both are opaque, indeterminate if one is opaque.
93             case SkBlendMode::kSrcOut:
94             case SkBlendMode::kDstOut:
95             case SkBlendMode::kXor:
96                 flags = kNone_OptimizationFlags;
97                 break;
98 
99             // Is opaque if the dst is opaque.
100             case SkBlendMode::kSrcATop:
101                 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
102                                                     : kNone_OptimizationFlags;
103                 break;
104 
105             // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
106             case SkBlendMode::kDstATop:
107             case SkBlendMode::kScreen:
108                 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
109                                                     : kNone_OptimizationFlags;
110                 break;
111 
112             // These modes are all opaque if either src or dst is opaque. All the advanced modes
113             // compute alpha as src-over.
114             case SkBlendMode::kSrcOver:
115             case SkBlendMode::kDstOver:
116             case SkBlendMode::kPlus:
117             case SkBlendMode::kOverlay:
118             case SkBlendMode::kDarken:
119             case SkBlendMode::kLighten:
120             case SkBlendMode::kColorDodge:
121             case SkBlendMode::kColorBurn:
122             case SkBlendMode::kHardLight:
123             case SkBlendMode::kSoftLight:
124             case SkBlendMode::kDifference:
125             case SkBlendMode::kExclusion:
126             case SkBlendMode::kMultiply:
127             case SkBlendMode::kHue:
128             case SkBlendMode::kSaturation:
129             case SkBlendMode::kColor:
130             case SkBlendMode::kLuminosity:
131                 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
132                                 ? kPreservesOpaqueInput_OptimizationFlag
133                                 : kNone_OptimizationFlags;
134                 break;
135         }
136         if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
137             dst->hasConstantOutputForConstantInput()) {
138             flags |= kConstantOutputForConstantInput_OptimizationFlag;
139         }
140         return flags;
141     }
142 
onIsEqual(const GrFragmentProcessor & other) const143     bool onIsEqual(const GrFragmentProcessor& other) const override {
144         const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
145         return fMode == cs.fMode;
146     }
147 
constantOutputForConstantInput(GrColor4f input) const148     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
149         float alpha = input.fRGBA[3];
150         input = input.opaque();
151         GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
152         GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
153         SkPM4f src = GrColor4fToSkPM4f(srcColor);
154         SkPM4f dst = GrColor4fToSkPM4f(dstColor);
155         SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
156         return SkPM4fToGrColor4f(res).mulByScalar(alpha);
157     }
158 
159     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
160 
161     SkBlendMode fMode;
162 
163     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
164 
165     typedef GrFragmentProcessor INHERITED;
166 };
167 
168 /////////////////////////////////////////////////////////////////////
169 
170 class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
171 public:
172     void emitCode(EmitArgs&) override;
173 
174 private:
175     typedef GrGLSLFragmentProcessor INHERITED;
176 };
177 
178 /////////////////////////////////////////////////////////////////////
179 
180 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
181 
182 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)183 sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
184     // Create two random frag procs.
185     sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
186     sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
187 
188     SkBlendMode mode;
189     do {
190         mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
191     } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
192     return sk_sp<GrFragmentProcessor>(
193         new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
194 }
195 #endif
196 
onCreateGLSLInstance() const197 GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
198     return new GLComposeTwoFragmentProcessor;
199 }
200 
201 /////////////////////////////////////////////////////////////////////
202 
emitCode(EmitArgs & args)203 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
204 
205     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
206     const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
207 
208     const char* inputColor = nullptr;
209     if (args.fInputColor) {
210         inputColor = "inputColor";
211         fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
212     }
213 
214     // declare outputColor and emit the code for each of the two children
215     SkString srcColor("xfer_src");
216     this->emitChild(0, inputColor, &srcColor, args);
217 
218     SkString dstColor("xfer_dst");
219     this->emitChild(1, inputColor, &dstColor, args);
220 
221     // emit blend code
222     SkBlendMode mode = cs.getMode();
223     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
224     GrGLSLBlend::AppendMode(fragBuilder,
225                             srcColor.c_str(),
226                             dstColor.c_str(),
227                             args.fOutputColor,
228                             mode);
229 
230     // re-multiply the output color by the input color's alpha
231     if (args.fInputColor) {
232         fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
233     }
234 }
235 
MakeFromTwoProcessors(sk_sp<GrFragmentProcessor> src,sk_sp<GrFragmentProcessor> dst,SkBlendMode mode)236 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
237          sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
238     switch (mode) {
239         case SkBlendMode::kClear:
240             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
241                                                GrConstColorProcessor::kIgnore_InputMode);
242         case SkBlendMode::kSrc:
243             return src;
244         case SkBlendMode::kDst:
245             return dst;
246         default:
247             return ComposeTwoFragmentProcessor::Make(std::move(src), std::move(dst), mode);
248     }
249 }
250 
251 //////////////////////////////////////////////////////////////////////////////
252 
253 class ComposeOneFragmentProcessor : public GrFragmentProcessor {
254 public:
255     enum Child {
256         kDst_Child,
257         kSrc_Child,
258     };
259 
Make(sk_sp<GrFragmentProcessor> fp,SkBlendMode mode,Child child)260     static sk_sp<GrFragmentProcessor> Make(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode,
261                                            Child child) {
262         if (!fp) {
263             return nullptr;
264         }
265         return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(fp),
266                                                                           mode, child));
267     }
268 
name() const269     const char* name() const override { return "ComposeOne"; }
270 
dumpInfo() const271     SkString dumpInfo() const override {
272         SkString str;
273 
274         str.appendf("Mode: %s, Child: %s",
275                     SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
276 
277         for (int i = 0; i < this->numChildProcessors(); ++i) {
278             str.appendf(" [%s %s]",
279                         this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
280         }
281         return str;
282     }
283 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const284     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
285         GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
286         b->add32((int)fMode | (fChild << 16));
287     }
288 
mode() const289     SkBlendMode mode() const { return fMode; }
290 
child() const291     Child child() const { return fChild; }
292 
293 private:
OptFlags(const GrFragmentProcessor * fp,SkBlendMode mode,Child child)294     OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
295         OptimizationFlags flags;
296         switch (mode) {
297             case SkBlendMode::kClear:
298                 SkFAIL("Should never create clear compose one FP.");
299                 flags = kNone_OptimizationFlags;
300                 break;
301 
302             case SkBlendMode::kSrc:
303                 SkASSERT(child == kSrc_Child);
304                 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
305                                                    : kNone_OptimizationFlags;
306                 break;
307 
308             case SkBlendMode::kDst:
309                 SkASSERT(child == kDst_Child);
310                 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
311                                                    : kNone_OptimizationFlags;
312                 break;
313 
314             // Produces opaque if both src and dst are opaque. These also will modulate the child's
315             // output by either the input color or alpha. However, if the child is not compatible
316             // with the coverage as alpha then it may produce a color that is not valid premul.
317             case SkBlendMode::kSrcIn:
318             case SkBlendMode::kDstIn:
319             case SkBlendMode::kModulate:
320                 if (fp->compatibleWithCoverageAsAlpha()) {
321                     if (fp->preservesOpaqueInput()) {
322                         flags = kPreservesOpaqueInput_OptimizationFlag |
323                                 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
324                     } else {
325                         flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
326                     }
327                 } else {
328                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
329                                                        : kNone_OptimizationFlags;
330                 }
331                 break;
332 
333             // Produces zero when both are opaque, indeterminate if one is opaque.
334             case SkBlendMode::kSrcOut:
335             case SkBlendMode::kDstOut:
336             case SkBlendMode::kXor:
337                 flags = kNone_OptimizationFlags;
338                 break;
339 
340             // Is opaque if the dst is opaque.
341             case SkBlendMode::kSrcATop:
342                 if (child == kDst_Child) {
343                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
344                                                        : kNone_OptimizationFlags;
345                 } else {
346                     flags = kPreservesOpaqueInput_OptimizationFlag;
347                 }
348                 break;
349 
350             // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
351             case SkBlendMode::kDstATop:
352             case SkBlendMode::kScreen:
353                 if (child == kSrc_Child) {
354                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
355                                                        : kNone_OptimizationFlags;
356                 } else {
357                     flags = kPreservesOpaqueInput_OptimizationFlag;
358                 }
359                 break;
360 
361             // These modes are all opaque if either src or dst is opaque. All the advanced modes
362             // compute alpha as src-over.
363             case SkBlendMode::kSrcOver:
364             case SkBlendMode::kDstOver:
365             case SkBlendMode::kPlus:
366             case SkBlendMode::kOverlay:
367             case SkBlendMode::kDarken:
368             case SkBlendMode::kLighten:
369             case SkBlendMode::kColorDodge:
370             case SkBlendMode::kColorBurn:
371             case SkBlendMode::kHardLight:
372             case SkBlendMode::kSoftLight:
373             case SkBlendMode::kDifference:
374             case SkBlendMode::kExclusion:
375             case SkBlendMode::kMultiply:
376             case SkBlendMode::kHue:
377             case SkBlendMode::kSaturation:
378             case SkBlendMode::kColor:
379             case SkBlendMode::kLuminosity:
380                 flags = kPreservesOpaqueInput_OptimizationFlag;
381                 break;
382         }
383         if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
384             flags |= kConstantOutputForConstantInput_OptimizationFlag;
385         }
386         return flags;
387     }
388 
onIsEqual(const GrFragmentProcessor & that) const389     bool onIsEqual(const GrFragmentProcessor& that) const override {
390         return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
391     }
392 
constantOutputForConstantInput(GrColor4f inputColor) const393     GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
394         GrColor4f childColor =
395                 ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
396         SkPM4f src, dst;
397         if (kSrc_Child == fChild) {
398             src = GrColor4fToSkPM4f(childColor);
399             dst = GrColor4fToSkPM4f(inputColor);
400         } else {
401             src = GrColor4fToSkPM4f(inputColor);
402             dst = GrColor4fToSkPM4f(childColor);
403         }
404         SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
405         return SkPM4fToGrColor4f(res);
406     }
407 
408 private:
ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> fp,SkBlendMode mode,Child child)409     ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode, Child child)
410             : INHERITED(OptFlags(fp.get(), mode, child))
411             , fMode(mode)
412             , fChild(child) {
413         this->initClassID<ComposeOneFragmentProcessor>();
414         SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
415         SkASSERT(0 == dstIndex);
416     }
417 
418     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
419 
420     SkBlendMode fMode;
421     Child       fChild;
422 
423     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
424 
425     typedef GrFragmentProcessor INHERITED;
426 };
427 
428 //////////////////////////////////////////////////////////////////////////////
429 
430 class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
431 public:
emitCode(EmitArgs & args)432     void emitCode(EmitArgs& args) override {
433         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
434         SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
435         ComposeOneFragmentProcessor::Child child =
436             args.fFp.cast<ComposeOneFragmentProcessor>().child();
437         SkString childColor("child");
438         this->emitChild(0, &childColor, args);
439 
440         const char* inputColor = args.fInputColor;
441         // We don't try to optimize for this case at all
442         if (!inputColor) {
443             fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
444             inputColor = "ones";
445         }
446 
447         // emit blend code
448         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
449         const char* childStr = childColor.c_str();
450         if (ComposeOneFragmentProcessor::kDst_Child == child) {
451             GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
452         } else {
453             GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
454         }
455     }
456 
457 private:
458     typedef GrGLSLFragmentProcessor INHERITED;
459 };
460 
461 /////////////////////////////////////////////////////////////////////
462 
463 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
464 
465 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)466 sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
467     // Create one random frag procs.
468     // For now, we'll prevent either children from being a shader with children to prevent the
469     // possibility of an arbitrarily large tree of procs.
470     sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
471     SkBlendMode mode;
472     ComposeOneFragmentProcessor::Child child;
473     do {
474         mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
475         child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
476     } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
477              (SkBlendMode::kSrc == mode && child == kDst_Child));
478     return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
479 }
480 #endif
481 
onCreateGLSLInstance() const482 GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
483     return new GLComposeOneFragmentProcessor;
484 }
485 
486 //////////////////////////////////////////////////////////////////////////////
487 
488 // It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
489 // that these factories could simply return the input FP. However, that doesn't have quite
490 // the same effect as the returned compose FP will replace the FP's input with solid white and
491 // ignore the original input. This could be implemented as:
492 // RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
493 
MakeFromDstProcessor(sk_sp<GrFragmentProcessor> dst,SkBlendMode mode)494 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
495     sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
496     switch (mode) {
497         case SkBlendMode::kClear:
498             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
499                                                GrConstColorProcessor::kIgnore_InputMode);
500         case SkBlendMode::kSrc:
501             return nullptr;
502         default:
503             return ComposeOneFragmentProcessor::Make(std::move(dst), mode,
504                                                      ComposeOneFragmentProcessor::kDst_Child);
505     }
506 }
507 
MakeFromSrcProcessor(sk_sp<GrFragmentProcessor> src,SkBlendMode mode)508 sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
509     sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
510     switch (mode) {
511         case SkBlendMode::kClear:
512             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
513                                                GrConstColorProcessor::kIgnore_InputMode);
514         case SkBlendMode::kDst:
515             return nullptr;
516         default:
517             return ComposeOneFragmentProcessor::Make(std::move(src), mode,
518                                                      ComposeOneFragmentProcessor::kSrc_Child);
519     }
520 }
521