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(std::unique_ptr<GrFragmentProcessor> src,std::unique_ptr<GrFragmentProcessor> dst,SkBlendMode mode)32     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));
37     }
38 
name() const39     const char* name() const override { return "ComposeTwo"; }
40 
41 #ifdef SK_DEBUG
dumpInfo() const42     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     }
53 #endif
54 
55     std::unique_ptr<GrFragmentProcessor> clone() const override;
56 
getMode() const57     SkBlendMode getMode() const { return fMode; }
58 
59 private:
ComposeTwoFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,std::unique_ptr<GrFragmentProcessor> dst,SkBlendMode mode)60     ComposeTwoFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
61                                 std::unique_ptr<GrFragmentProcessor> dst,
62                                 SkBlendMode mode)
63             : INHERITED(kComposeTwoFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode))
64             , fMode(mode) {
65         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 
OptFlags(const GrFragmentProcessor * src,const GrFragmentProcessor * dst,SkBlendMode mode)71     static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
72                                       const GrFragmentProcessor* dst, SkBlendMode mode) {
73         OptimizationFlags flags;
74         switch (mode) {
75             case SkBlendMode::kClear:
76             case SkBlendMode::kSrc:
77             case SkBlendMode::kDst:
78                 SK_ABORT("Should never create clear, src, or dst compose two FP.");
79                 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         }
135         if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
136             dst->hasConstantOutputForConstantInput()) {
137             flags |= kConstantOutputForConstantInput_OptimizationFlag;
138         }
139         return flags;
140     }
141 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const142     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
143         b->add32((int)fMode);
144     }
145 
onIsEqual(const GrFragmentProcessor & other) const146     bool onIsEqual(const GrFragmentProcessor& other) const override {
147         const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
148         return fMode == cs.fMode;
149     }
150 
constantOutputForConstantInput(const SkPMColor4f & input) const151     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);
155         SkPMColor4f res = SkBlendMode_Apply(fMode, src, dst);
156         return res * input.fA;
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 std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(
184         GrProcessorTestData* d) {
185     // Create two random frag procs.
186     std::unique_ptr<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
187     std::unique_ptr<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
188 
189     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);
193     return std::unique_ptr<GrFragmentProcessor>(
194             new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
195 }
196 #endif
197 
clone() const198 std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::clone() const {
199     auto src = this->childProcessor(0).clone();
200     auto dst = this->childProcessor(1).clone();
201     return std::unique_ptr<GrFragmentProcessor>(
202             new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), fMode));
203 }
204 
onCreateGLSLInstance() const205 GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
206     return new GLComposeTwoFragmentProcessor;
207 }
208 
209 /////////////////////////////////////////////////////////////////////
210 
emitCode(EmitArgs & args)211 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
212 
213     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
214     const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
215 
216     const char* inputColor = nullptr;
217     if (args.fInputColor) {
218         inputColor = "inputColor";
219         fragBuilder->codeAppendf("half4 inputColor = half4(%s.rgb, 1.0);", args.fInputColor);
220     }
221 
222     // declare outputColor and emit the code for each of the two children
223     SkString srcColor("xfer_src");
224     this->emitChild(0, inputColor, &srcColor, args);
225 
226     SkString dstColor("xfer_dst");
227     this->emitChild(1, inputColor, &dstColor, args);
228 
229     // emit blend code
230     SkBlendMode mode = cs.getMode();
231     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
232     GrGLSLBlend::AppendMode(fragBuilder,
233                             srcColor.c_str(),
234                             dstColor.c_str(),
235                             args.fOutputColor,
236                             mode);
237 
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     }
242 }
243 
MakeFromTwoProcessors(std::unique_ptr<GrFragmentProcessor> src,std::unique_ptr<GrFragmentProcessor> dst,SkBlendMode mode)244 std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
245         std::unique_ptr<GrFragmentProcessor> src,
246         std::unique_ptr<GrFragmentProcessor> dst,
247         SkBlendMode mode) {
248     switch (mode) {
249         case SkBlendMode::kClear:
250             return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
251                                                GrConstColorProcessor::InputMode::kIgnore);
252         case SkBlendMode::kSrc:
253             return src;
254         case SkBlendMode::kDst:
255             return dst;
256         default:
257             return ComposeTwoFragmentProcessor::Make(std::move(src), std::move(dst), mode);
258     }
259 }
260 
261 //////////////////////////////////////////////////////////////////////////////
262 
263 class ComposeOneFragmentProcessor : public GrFragmentProcessor {
264 public:
265     enum Child {
266         kDst_Child,
267         kSrc_Child,
268     };
269 
Make(std::unique_ptr<GrFragmentProcessor> fp,SkBlendMode mode,Child child)270     static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
271                                                      SkBlendMode mode, Child child) {
272         if (!fp) {
273             return nullptr;
274         }
275         return std::unique_ptr<GrFragmentProcessor>(
276                 new ComposeOneFragmentProcessor(std::move(fp), mode, child));
277     }
278 
name() const279     const char* name() const override { return "ComposeOne"; }
280 
281 #ifdef SK_DEBUG
dumpInfo() const282     SkString dumpInfo() const override {
283         SkString str;
284 
285         str.appendf("Mode: %s, Child: %s",
286                     SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
287 
288         for (int i = 0; i < this->numChildProcessors(); ++i) {
289             str.appendf(" [%s %s]",
290                         this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
291         }
292         return str;
293     }
294 #endif
295 
296     std::unique_ptr<GrFragmentProcessor> clone() const override;
297 
mode() const298     SkBlendMode mode() const { return fMode; }
299 
child() const300     Child child() const { return fChild; }
301 
302 private:
OptFlags(const GrFragmentProcessor * fp,SkBlendMode mode,Child child)303     OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
304         OptimizationFlags flags;
305         switch (mode) {
306             case SkBlendMode::kClear:
307                 SK_ABORT("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
324             // 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.
326             case SkBlendMode::kSrcIn:
327             case SkBlendMode::kDstIn:
328             case SkBlendMode::kModulate:
329                 if (fp->compatibleWithCoverageAsAlpha()) {
330                     if (fp->preservesOpaqueInput()) {
331                         flags = kPreservesOpaqueInput_OptimizationFlag |
332                                 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
333                     } else {
334                         flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
335                     }
336                 } else {
337                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
338                                                        : kNone_OptimizationFlags;
339                 }
340                 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;
391         }
392         if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
393             flags |= kConstantOutputForConstantInput_OptimizationFlag;
394         }
395         return flags;
396     }
397 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const398     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
399         GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & UINT16_MAX) == (int)SkBlendMode::kLastMode);
400         b->add32((int)fMode | (fChild << 16));
401     }
402 
onIsEqual(const GrFragmentProcessor & that) const403     bool onIsEqual(const GrFragmentProcessor& that) const override {
404         return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
405     }
406 
constantOutputForConstantInput(const SkPMColor4f & inputColor) const407     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inputColor) const override {
408         SkPMColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
409                                                                 SK_PMColor4fWHITE);
410         SkPMColor4f src, dst;
411         if (kSrc_Child == fChild) {
412             src = childColor;
413             dst = inputColor;
414         } else {
415             src = inputColor;
416             dst = childColor;
417         }
418         return SkBlendMode_Apply(fMode, src, dst);
419     }
420 
421 private:
ComposeOneFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp,SkBlendMode mode,Child child)422     ComposeOneFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp, SkBlendMode mode,
423                                 Child child)
424             : INHERITED(kComposeOneFragmentProcessor_ClassID, OptFlags(fp.get(), mode, child))
425             , fMode(mode)
426             , fChild(child) {
427         SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
428         SkASSERT(0 == dstIndex);
429     }
430 
431     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
432 
433     SkBlendMode fMode;
434     Child       fChild;
435 
436     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
437 
438     typedef GrFragmentProcessor INHERITED;
439 };
440 
441 //////////////////////////////////////////////////////////////////////////////
442 
443 class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
444 public:
emitCode(EmitArgs & args)445     void emitCode(EmitArgs& args) override {
446         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
447         SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
448         ComposeOneFragmentProcessor::Child child =
449             args.fFp.cast<ComposeOneFragmentProcessor>().child();
450         SkString childColor("child");
451         this->emitChild(0, &childColor, args);
452 
453         // emit blend code
454         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
455         const char* childStr = childColor.c_str();
456         if (ComposeOneFragmentProcessor::kDst_Child == child) {
457             GrGLSLBlend::AppendMode(fragBuilder, args.fInputColor, childStr, args.fOutputColor, mode);
458         } else {
459             GrGLSLBlend::AppendMode(fragBuilder, childStr, args.fInputColor, args.fOutputColor, mode);
460         }
461     }
462 
463 private:
464     typedef GrGLSLFragmentProcessor INHERITED;
465 };
466 
467 /////////////////////////////////////////////////////////////////////
468 
469 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
470 
471 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)472 std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(
473         GrProcessorTestData* d) {
474     // 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.
477     std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
478     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));
485     return std::unique_ptr<GrFragmentProcessor>(
486             new ComposeOneFragmentProcessor(std::move(dst), mode, child));
487 }
488 #endif
489 
onCreateGLSLInstance() const490 GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
491     return new GLComposeOneFragmentProcessor;
492 }
493 
clone() const494 std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::clone() const {
495     return std::unique_ptr<GrFragmentProcessor>(
496             new ComposeOneFragmentProcessor(this->childProcessor(0).clone(), fMode, fChild));
497 }
498 
499 //////////////////////////////////////////////////////////////////////////////
500 
501 // 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:
505 // RunInSeries(ConstColor(WHITE, kIgnoreInput), inputFP).
506 
MakeFromDstProcessor(std::unique_ptr<GrFragmentProcessor> dst,SkBlendMode mode)507 std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
508         std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
509     switch (mode) {
510         case SkBlendMode::kClear:
511             return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
512                                                GrConstColorProcessor::InputMode::kIgnore);
513         case SkBlendMode::kSrc:
514             return nullptr;
515         default:
516             return ComposeOneFragmentProcessor::Make(std::move(dst), mode,
517                                                      ComposeOneFragmentProcessor::kDst_Child);
518     }
519 }
520 
MakeFromSrcProcessor(std::unique_ptr<GrFragmentProcessor> src,SkBlendMode mode)521 std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
522         std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) {
523     switch (mode) {
524         case SkBlendMode::kClear:
525             return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
526                                                GrConstColorProcessor::InputMode::kIgnore);
527         case SkBlendMode::kDst:
528             return nullptr;
529         default:
530             return ComposeOneFragmentProcessor::Make(std::move(src), mode,
531                                                      ComposeOneFragmentProcessor::kSrc_Child);
532     }
533 }
534