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.
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:
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 
39     const char* name() const override { return "ComposeTwo"; }
40 
41     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 
53     std::unique_ptr<GrFragmentProcessor> clone() const override;
54 
55     SkBlendMode getMode() const { return fMode; }
56 
57 private:
58     ComposeTwoFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
59                                 std::unique_ptr<GrFragmentProcessor> dst,
60                                 SkBlendMode mode)
61             : INHERITED(kComposeTwoFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode))
62             , fMode(mode) {
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 
69     static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
70                                       const GrFragmentProcessor* dst, SkBlendMode mode) {
71         OptimizationFlags flags;
72         switch (mode) {
73             case SkBlendMode::kClear:
74             case SkBlendMode::kSrc:
75             case SkBlendMode::kDst:
76                 SK_ABORT("Should never create clear, src, or dst compose two FP.");
77                 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         }
133         if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
134             dst->hasConstantOutputForConstantInput()) {
135             flags |= kConstantOutputForConstantInput_OptimizationFlag;
136         }
137         return flags;
138     }
139 
140     void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
141         b->add32((int)fMode);
142     }
143 
144     bool onIsEqual(const GrFragmentProcessor& other) const override {
145         const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
146         return fMode == cs.fMode;
147     }
148 
149     GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
150         float alpha = input.fRGBA[3];
151         input = input.opaque();
152         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);
156         SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
157         return SkPM4fToGrColor4f(res).mulByScalar(alpha);
158     }
159 
160     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
161 
162     SkBlendMode fMode;
163 
164     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
165 
166     typedef GrFragmentProcessor INHERITED;
167 };
168 
169 /////////////////////////////////////////////////////////////////////
170 
171 class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
172 public:
173     void emitCode(EmitArgs&) override;
174 
175 private:
176     typedef GrGLSLFragmentProcessor INHERITED;
177 };
178 
179 /////////////////////////////////////////////////////////////////////
180 
181 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
182 
183 #if GR_TEST_UTILS
184 std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(
185         GrProcessorTestData* d) {
186     // Create two random frag procs.
187     std::unique_ptr<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
188     std::unique_ptr<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
189 
190     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);
194     return std::unique_ptr<GrFragmentProcessor>(
195             new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
196 }
197 #endif
198 
199 std::unique_ptr<GrFragmentProcessor> ComposeTwoFragmentProcessor::clone() const {
200     auto src = this->childProcessor(0).clone();
201     auto dst = this->childProcessor(1).clone();
202     return std::unique_ptr<GrFragmentProcessor>(
203             new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), fMode));
204 }
205 
206 GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
207     return new GLComposeTwoFragmentProcessor;
208 }
209 
210 /////////////////////////////////////////////////////////////////////
211 
212 void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
213 
214     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
215     const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
216 
217     const char* inputColor = nullptr;
218     if (args.fInputColor) {
219         inputColor = "inputColor";
220         fragBuilder->codeAppendf("half4 inputColor = half4(%s.rgb, 1.0);", args.fInputColor);
221     }
222 
223     // declare outputColor and emit the code for each of the two children
224     SkString srcColor("xfer_src");
225     this->emitChild(0, inputColor, &srcColor, args);
226 
227     SkString dstColor("xfer_dst");
228     this->emitChild(1, inputColor, &dstColor, args);
229 
230     // emit blend code
231     SkBlendMode mode = cs.getMode();
232     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
233     GrGLSLBlend::AppendMode(fragBuilder,
234                             srcColor.c_str(),
235                             dstColor.c_str(),
236                             args.fOutputColor,
237                             mode);
238 
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     }
243 }
244 
245 std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
246         std::unique_ptr<GrFragmentProcessor> src,
247         std::unique_ptr<GrFragmentProcessor> dst,
248         SkBlendMode mode) {
249     switch (mode) {
250         case SkBlendMode::kClear:
251             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
252                                                GrConstColorProcessor::InputMode::kIgnore);
253         case SkBlendMode::kSrc:
254             return src;
255         case SkBlendMode::kDst:
256             return dst;
257         default:
258             return ComposeTwoFragmentProcessor::Make(std::move(src), std::move(dst), mode);
259     }
260 }
261 
262 //////////////////////////////////////////////////////////////////////////////
263 
264 class ComposeOneFragmentProcessor : public GrFragmentProcessor {
265 public:
266     enum Child {
267         kDst_Child,
268         kSrc_Child,
269     };
270 
271     static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
272                                                      SkBlendMode mode, Child child) {
273         if (!fp) {
274             return nullptr;
275         }
276         return std::unique_ptr<GrFragmentProcessor>(
277                 new ComposeOneFragmentProcessor(std::move(fp), mode, child));
278     }
279 
280     const char* name() const override { return "ComposeOne"; }
281 
282     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 
295     std::unique_ptr<GrFragmentProcessor> clone() const override;
296 
297     SkBlendMode mode() const { return fMode; }
298 
299     Child child() const { return fChild; }
300 
301 private:
302     OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
303         OptimizationFlags flags;
304         switch (mode) {
305             case SkBlendMode::kClear:
306                 SK_ABORT("Should never create clear compose one FP.");
307                 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
323             // 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.
325             case SkBlendMode::kSrcIn:
326             case SkBlendMode::kDstIn:
327             case SkBlendMode::kModulate:
328                 if (fp->compatibleWithCoverageAsAlpha()) {
329                     if (fp->preservesOpaqueInput()) {
330                         flags = kPreservesOpaqueInput_OptimizationFlag |
331                                 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
332                     } else {
333                         flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
334                     }
335                 } else {
336                     flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
337                                                        : kNone_OptimizationFlags;
338                 }
339                 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;
390         }
391         if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
392             flags |= kConstantOutputForConstantInput_OptimizationFlag;
393         }
394         return flags;
395     }
396 
397     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 
402     bool onIsEqual(const GrFragmentProcessor& that) const override {
403         return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
404     }
405 
406     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         }
417         SkPM4f res = SkBlendMode_Apply(fMode, src, dst);
418         return SkPM4fToGrColor4f(res);
419     }
420 
421 private:
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:
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         const char* inputColor = args.fInputColor;
454         // We don't try to optimize for this case at all
455         if (!inputColor) {
456             fragBuilder->codeAppendf("const half4 ones = half4(1);");
457             inputColor = "ones";
458         }
459 
460         // emit blend code
461         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
462         const char* childStr = childColor.c_str();
463         if (ComposeOneFragmentProcessor::kDst_Child == child) {
464             GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
465         } else {
466             GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
467         }
468     }
469 
470 private:
471     typedef GrGLSLFragmentProcessor INHERITED;
472 };
473 
474 /////////////////////////////////////////////////////////////////////
475 
476 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
477 
478 #if GR_TEST_UTILS
479 std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(
480         GrProcessorTestData* d) {
481     // Create one random frag procs.
482     // For now, we'll prevent either children from being a shader with children to prevent the
483     // possibility of an arbitrarily large tree of procs.
484     std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
485     SkBlendMode mode;
486     ComposeOneFragmentProcessor::Child child;
487     do {
488         mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
489         child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
490     } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
491              (SkBlendMode::kSrc == mode && child == kDst_Child));
492     return std::unique_ptr<GrFragmentProcessor>(
493             new ComposeOneFragmentProcessor(std::move(dst), mode, child));
494 }
495 #endif
496 
497 GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
498     return new GLComposeOneFragmentProcessor;
499 }
500 
501 std::unique_ptr<GrFragmentProcessor> ComposeOneFragmentProcessor::clone() const {
502     return std::unique_ptr<GrFragmentProcessor>(
503             new ComposeOneFragmentProcessor(this->childProcessor(0).clone(), fMode, fChild));
504 }
505 
506 //////////////////////////////////////////////////////////////////////////////
507 
508 // It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
509 // that these factories could simply return the input FP. However, that doesn't have quite
510 // the same effect as the returned compose FP will replace the FP's input with solid white and
511 // ignore the original input. This could be implemented as:
512 // RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
513 
514 std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
515         std::unique_ptr<GrFragmentProcessor> dst, SkBlendMode mode) {
516     switch (mode) {
517         case SkBlendMode::kClear:
518             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
519                                                GrConstColorProcessor::InputMode::kIgnore);
520         case SkBlendMode::kSrc:
521             return nullptr;
522         default:
523             return ComposeOneFragmentProcessor::Make(std::move(dst), mode,
524                                                      ComposeOneFragmentProcessor::kDst_Child);
525     }
526 }
527 
528 std::unique_ptr<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
529         std::unique_ptr<GrFragmentProcessor> src, SkBlendMode mode) {
530     switch (mode) {
531         case SkBlendMode::kClear:
532             return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
533                                                GrConstColorProcessor::InputMode::kIgnore);
534         case SkBlendMode::kDst:
535             return nullptr;
536         default:
537             return ComposeOneFragmentProcessor::Make(std::move(src), mode,
538                                                      ComposeOneFragmentProcessor::kSrc_Child);
539     }
540 }
541