blob: 9671919decb7bac79f857f474722117c4b5589cd [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
8#include "effects/GrXfermodeFragmentProcessor.h"
9
10#include "GrFragmentProcessor.h"
11#include "effects/GrConstColorProcessor.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"
wangyix809e5af2015-09-09 12:58:32 -070016
Brian Salomon246a3c22017-02-10 16:16:21 -050017// Some of the cpu implementations of blend modes differ too much from the GPU enough that
18// we can't use the cpu implementation to implement constantOutputForConstantInput.
19static inline bool does_cpu_blend_impl_match_gpu(SkBlendMode mode) {
20 // The non-seperable modes differ too much. So does SoftLight. ColorBurn differs too much on our
21 // test iOS device (but we just disable it across the aboard since it may happen on untested
22 // GPUs).
23 return mode <= SkBlendMode::kLastSeparableMode && mode != SkBlendMode::kSoftLight &&
24 mode != SkBlendMode::kColorBurn;
25}
26
27//////////////////////////////////////////////////////////////////////////////
28
bsalomonae4738f2015-09-15 15:33:27 -070029class ComposeTwoFragmentProcessor : public GrFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -070030public:
bungeman06ca8ec2016-06-09 08:01:03 -070031 ComposeTwoFragmentProcessor(sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst,
Mike Reed7d954ad2016-10-28 15:42:34 -040032 SkBlendMode mode)
Brian Salomon587e08f2017-01-27 10:59:27 -050033 : INHERITED(OptFlags(src.get(), dst.get(), mode)), fMode(mode) {
bsalomonae4738f2015-09-15 15:33:27 -070034 this->initClassID<ComposeTwoFragmentProcessor>();
bungeman06ca8ec2016-06-09 08:01:03 -070035 SkDEBUGCODE(int shaderAChildIndex = )this->registerChildProcessor(std::move(src));
36 SkDEBUGCODE(int shaderBChildIndex = )this->registerChildProcessor(std::move(dst));
wangyix809e5af2015-09-09 12:58:32 -070037 SkASSERT(0 == shaderAChildIndex);
38 SkASSERT(1 == shaderBChildIndex);
39 }
40
bsalomonae4738f2015-09-15 15:33:27 -070041 const char* name() const override { return "ComposeTwo"; }
wangyix809e5af2015-09-09 12:58:32 -070042
Brian Osmanbd1f76f2017-03-15 11:33:12 -040043 SkString dumpInfo() const override {
44 SkString str;
45
46 str.appendf("Mode: %s", SkBlendMode_Name(fMode));
47
48 for (int i = 0; i < this->numChildProcessors(); ++i) {
49 str.appendf(" [%s %s]",
50 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
51 }
52 return str;
53 }
54
Brian Salomon94efbf52016-11-29 13:43:05 -050055 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -040056 b->add32((int)fMode);
wangyix809e5af2015-09-09 12:58:32 -070057 }
58
Mike Reed7d954ad2016-10-28 15:42:34 -040059 SkBlendMode getMode() const { return fMode; }
wangyix809e5af2015-09-09 12:58:32 -070060
Brian Salomon587e08f2017-01-27 10:59:27 -050061private:
62 static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
63 const GrFragmentProcessor* dst, SkBlendMode mode) {
Brian Salomona12c1532017-02-13 12:41:44 -050064 OptimizationFlags flags;
65 switch (mode) {
66 case SkBlendMode::kClear:
67 case SkBlendMode::kSrc:
68 case SkBlendMode::kDst:
69 SkFAIL("Should never create clear, src, or dst compose two FP.");
70 flags = kNone_OptimizationFlags;
71 break;
72
73 // Produces opaque if both src and dst are opaque.
74 case SkBlendMode::kSrcIn:
75 case SkBlendMode::kDstIn:
76 case SkBlendMode::kModulate:
77 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
78 ? kPreservesOpaqueInput_OptimizationFlag
79 : kNone_OptimizationFlags;
80 break;
81
82 // Produces zero when both are opaque, indeterminate if one is opaque.
83 case SkBlendMode::kSrcOut:
84 case SkBlendMode::kDstOut:
85 case SkBlendMode::kXor:
86 flags = kNone_OptimizationFlags;
87 break;
88
89 // Is opaque if the dst is opaque.
90 case SkBlendMode::kSrcATop:
91 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
92 : kNone_OptimizationFlags;
93 break;
94
95 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
96 case SkBlendMode::kDstATop:
97 case SkBlendMode::kScreen:
98 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
99 : kNone_OptimizationFlags;
100 break;
101
102 // These modes are all opaque if either src or dst is opaque. All the advanced modes
103 // compute alpha as src-over.
104 case SkBlendMode::kSrcOver:
105 case SkBlendMode::kDstOver:
106 case SkBlendMode::kPlus:
107 case SkBlendMode::kOverlay:
108 case SkBlendMode::kDarken:
109 case SkBlendMode::kLighten:
110 case SkBlendMode::kColorDodge:
111 case SkBlendMode::kColorBurn:
112 case SkBlendMode::kHardLight:
113 case SkBlendMode::kSoftLight:
114 case SkBlendMode::kDifference:
115 case SkBlendMode::kExclusion:
116 case SkBlendMode::kMultiply:
117 case SkBlendMode::kHue:
118 case SkBlendMode::kSaturation:
119 case SkBlendMode::kColor:
120 case SkBlendMode::kLuminosity:
121 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
122 ? kPreservesOpaqueInput_OptimizationFlag
123 : kNone_OptimizationFlags;
124 break;
125 }
Brian Salomon246a3c22017-02-10 16:16:21 -0500126 if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
127 dst->hasConstantOutputForConstantInput()) {
Brian Salomona12c1532017-02-13 12:41:44 -0500128 flags |= kConstantOutputForConstantInput_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500129 }
Brian Salomona12c1532017-02-13 12:41:44 -0500130 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500131 }
132
wangyix809e5af2015-09-09 12:58:32 -0700133 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -0700134 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700135 return fMode == cs.fMode;
136 }
137
Brian Salomon587e08f2017-01-27 10:59:27 -0500138 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
139 float alpha = input.fRGBA[3];
140 input = input.opaque();
141 GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
142 GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
143 SkPM4f src = GrColor4fToSkPM4f(srcColor);
144 SkPM4f dst = GrColor4fToSkPM4f(dstColor);
145 auto proc = SkXfermode::GetProc4f(fMode);
146 return SkPM4fToGrColor4f(proc(src, dst)).mulByScalar(alpha);
147 }
148
egdaniel57d3b032015-11-13 11:57:27 -0800149 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyix809e5af2015-09-09 12:58:32 -0700150
Mike Reed7d954ad2016-10-28 15:42:34 -0400151 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -0700152
153 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
154
155 typedef GrFragmentProcessor INHERITED;
156};
157
158/////////////////////////////////////////////////////////////////////
159
egdaniel64c47282015-11-13 06:54:19 -0800160class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -0700161public:
wangyix809e5af2015-09-09 12:58:32 -0700162 void emitCode(EmitArgs&) override;
163
164private:
egdaniel64c47282015-11-13 06:54:19 -0800165 typedef GrGLSLFragmentProcessor INHERITED;
wangyix809e5af2015-09-09 12:58:32 -0700166};
167
168/////////////////////////////////////////////////////////////////////
169
bsalomonae4738f2015-09-15 15:33:27 -0700170GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -0700171
Hal Canary6f6961e2017-01-31 13:50:44 -0500172#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700173sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -0700174 // Create two random frag procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700175 sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
176 sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
wangyix809e5af2015-09-09 12:58:32 -0700177
Brian Salomona12c1532017-02-13 12:41:44 -0500178 SkBlendMode mode;
179 do {
180 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
181 } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
bungeman06ca8ec2016-06-09 08:01:03 -0700182 return sk_sp<GrFragmentProcessor>(
183 new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
wangyix809e5af2015-09-09 12:58:32 -0700184}
Hal Canary6f6961e2017-01-31 13:50:44 -0500185#endif
wangyix809e5af2015-09-09 12:58:32 -0700186
egdaniel57d3b032015-11-13 11:57:27 -0800187GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
robertphillips9cdb9922016-02-03 12:25:40 -0800188 return new GLComposeTwoFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -0700189}
190
191/////////////////////////////////////////////////////////////////////
192
bsalomonae4738f2015-09-15 15:33:27 -0700193void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -0700194
cdalton85285412016-02-18 12:37:07 -0800195 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonae4738f2015-09-15 15:33:27 -0700196 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700197
bsalomonf1b7a1d2015-09-28 06:26:28 -0700198 const char* inputColor = nullptr;
bsalomonb5b60322015-09-14 12:26:33 -0700199 if (args.fInputColor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700200 inputColor = "inputColor";
egdaniel4ca2e602015-11-18 08:01:26 -0800201 fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700202 }
wangyix809e5af2015-09-09 12:58:32 -0700203
204 // declare outputColor and emit the code for each of the two children
ethannicholas22f939e2016-10-13 13:25:34 -0700205 SkString srcColor("xfer_src");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700206 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700207
ethannicholas22f939e2016-10-13 13:25:34 -0700208 SkString dstColor("xfer_dst");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700209 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700210
211 // emit blend code
Mike Reed7d954ad2016-10-28 15:42:34 -0400212 SkBlendMode mode = cs.getMode();
egdaniel4ca2e602015-11-18 08:01:26 -0800213 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
214 GrGLSLBlend::AppendMode(fragBuilder,
215 srcColor.c_str(),
216 dstColor.c_str(),
217 args.fOutputColor,
218 mode);
wangyix809e5af2015-09-09 12:58:32 -0700219
220 // re-multiply the output color by the input color's alpha
bsalomonf1b7a1d2015-09-28 06:26:28 -0700221 if (args.fInputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800222 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700223 }
wangyix809e5af2015-09-09 12:58:32 -0700224}
225
bungeman06ca8ec2016-06-09 08:01:03 -0700226sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
Mike Reed7d954ad2016-10-28 15:42:34 -0400227 sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700228 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400229 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400230 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bungeman06ca8ec2016-06-09 08:01:03 -0700231 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400232 case SkBlendMode::kSrc:
bungeman06ca8ec2016-06-09 08:01:03 -0700233 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400234 case SkBlendMode::kDst:
bungeman06ca8ec2016-06-09 08:01:03 -0700235 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700236 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700237 return sk_sp<GrFragmentProcessor>(
238 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
bsalomonae4738f2015-09-15 15:33:27 -0700239 }
240}
241
242//////////////////////////////////////////////////////////////////////////////
243
244class ComposeOneFragmentProcessor : public GrFragmentProcessor {
245public:
246 enum Child {
247 kDst_Child,
248 kSrc_Child,
249 };
250
Brian Salomona12c1532017-02-13 12:41:44 -0500251 ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode, Child child)
252 : INHERITED(OptFlags(fp.get(), mode, child)), fMode(mode), fChild(child) {
bsalomonae4738f2015-09-15 15:33:27 -0700253 this->initClassID<ComposeOneFragmentProcessor>();
Brian Salomona12c1532017-02-13 12:41:44 -0500254 SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
bsalomonae4738f2015-09-15 15:33:27 -0700255 SkASSERT(0 == dstIndex);
256 }
257
258 const char* name() const override { return "ComposeOne"; }
259
robertphillips783a4da2015-11-19 14:00:02 -0800260 SkString dumpInfo() const override {
261 SkString str;
262
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400263 str.appendf("Mode: %s, Child: %s",
264 SkBlendMode_Name(fMode), kDst_Child == fChild ? "Dst" : "Src");
265
robertphillips783a4da2015-11-19 14:00:02 -0800266 for (int i = 0; i < this->numChildProcessors(); ++i) {
Brian Osmanbd1f76f2017-03-15 11:33:12 -0400267 str.appendf(" [%s %s]",
268 this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
robertphillips783a4da2015-11-19 14:00:02 -0800269 }
270 return str;
271 }
272
Brian Salomon94efbf52016-11-29 13:43:05 -0500273 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -0400274 GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
275 b->add32((int)fMode | (fChild << 16));
bsalomonae4738f2015-09-15 15:33:27 -0700276 }
277
Mike Reed7d954ad2016-10-28 15:42:34 -0400278 SkBlendMode mode() const { return fMode; }
bsalomonae4738f2015-09-15 15:33:27 -0700279
280 Child child() const { return fChild; }
281
Brian Salomon587e08f2017-01-27 10:59:27 -0500282private:
Brian Salomona12c1532017-02-13 12:41:44 -0500283 OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
284 OptimizationFlags flags;
285 switch (mode) {
286 case SkBlendMode::kClear:
287 SkFAIL("Should never create clear compose one FP.");
288 flags = kNone_OptimizationFlags;
289 break;
290
291 case SkBlendMode::kSrc:
292 SkASSERT(child == kSrc_Child);
293 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
294 : kNone_OptimizationFlags;
295 break;
296
297 case SkBlendMode::kDst:
298 SkASSERT(child == kDst_Child);
299 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
300 : kNone_OptimizationFlags;
301 break;
302
303 // Produces opaque if both src and dst are opaque. These also will modulate the child's
Brian Salomone0265112017-02-21 14:19:07 -0500304 // output by either the input color or alpha. However, if the child is not compatible
305 // with the coverage as alpha then it may produce a color that is not valid premul.
Brian Salomona12c1532017-02-13 12:41:44 -0500306 case SkBlendMode::kSrcIn:
307 case SkBlendMode::kDstIn:
308 case SkBlendMode::kModulate:
Brian Salomone0265112017-02-21 14:19:07 -0500309 if (fp->compatibleWithCoverageAsAlpha()) {
310 if (fp->preservesOpaqueInput()) {
311 flags = kPreservesOpaqueInput_OptimizationFlag |
312 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
313 } else {
314 flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
315 }
Brian Salomonf3b995b2017-02-15 10:22:23 -0500316 } else {
Brian Salomone0265112017-02-21 14:19:07 -0500317 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
318 : kNone_OptimizationFlags;
Brian Salomonf3b995b2017-02-15 10:22:23 -0500319 }
Brian Salomona12c1532017-02-13 12:41:44 -0500320 break;
321
322 // Produces zero when both are opaque, indeterminate if one is opaque.
323 case SkBlendMode::kSrcOut:
324 case SkBlendMode::kDstOut:
325 case SkBlendMode::kXor:
326 flags = kNone_OptimizationFlags;
327 break;
328
329 // Is opaque if the dst is opaque.
330 case SkBlendMode::kSrcATop:
331 if (child == kDst_Child) {
332 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
333 : kNone_OptimizationFlags;
334 } else {
335 flags = kPreservesOpaqueInput_OptimizationFlag;
336 }
337 break;
338
339 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
340 case SkBlendMode::kDstATop:
341 case SkBlendMode::kScreen:
342 if (child == kSrc_Child) {
343 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
344 : kNone_OptimizationFlags;
345 } else {
346 flags = kPreservesOpaqueInput_OptimizationFlag;
347 }
348 break;
349
350 // These modes are all opaque if either src or dst is opaque. All the advanced modes
351 // compute alpha as src-over.
352 case SkBlendMode::kSrcOver:
353 case SkBlendMode::kDstOver:
354 case SkBlendMode::kPlus:
355 case SkBlendMode::kOverlay:
356 case SkBlendMode::kDarken:
357 case SkBlendMode::kLighten:
358 case SkBlendMode::kColorDodge:
359 case SkBlendMode::kColorBurn:
360 case SkBlendMode::kHardLight:
361 case SkBlendMode::kSoftLight:
362 case SkBlendMode::kDifference:
363 case SkBlendMode::kExclusion:
364 case SkBlendMode::kMultiply:
365 case SkBlendMode::kHue:
366 case SkBlendMode::kSaturation:
367 case SkBlendMode::kColor:
368 case SkBlendMode::kLuminosity:
369 flags = kPreservesOpaqueInput_OptimizationFlag;
370 break;
Brian Salomon587e08f2017-01-27 10:59:27 -0500371 }
Brian Salomona12c1532017-02-13 12:41:44 -0500372 if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
373 flags |= kConstantOutputForConstantInput_OptimizationFlag;
374 }
375 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500376 }
377
bsalomonae4738f2015-09-15 15:33:27 -0700378 bool onIsEqual(const GrFragmentProcessor& that) const override {
379 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
380 }
381
Brian Salomon587e08f2017-01-27 10:59:27 -0500382 GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
383 GrColor4f childColor =
384 ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
385 SkPM4f src, dst;
386 if (kSrc_Child == fChild) {
387 src = GrColor4fToSkPM4f(childColor);
388 dst = GrColor4fToSkPM4f(inputColor);
389 } else {
390 src = GrColor4fToSkPM4f(inputColor);
391 dst = GrColor4fToSkPM4f(childColor);
392 }
393 auto proc = SkXfermode::GetProc4f(fMode);
394 return SkPM4fToGrColor4f(proc(src, dst));
395 }
396
bsalomonae4738f2015-09-15 15:33:27 -0700397private:
egdaniel57d3b032015-11-13 11:57:27 -0800398 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700399
Mike Reed7d954ad2016-10-28 15:42:34 -0400400 SkBlendMode fMode;
401 Child fChild;
bsalomonae4738f2015-09-15 15:33:27 -0700402
403 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
404
405 typedef GrFragmentProcessor INHERITED;
406};
407
408//////////////////////////////////////////////////////////////////////////////
409
egdaniel64c47282015-11-13 06:54:19 -0800410class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
bsalomonae4738f2015-09-15 15:33:27 -0700411public:
bsalomonae4738f2015-09-15 15:33:27 -0700412 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800413 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Mike Reed7d954ad2016-10-28 15:42:34 -0400414 SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
bsalomonae4738f2015-09-15 15:33:27 -0700415 ComposeOneFragmentProcessor::Child child =
416 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700417 SkString childColor("child");
418 this->emitChild(0, nullptr, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700419
420 const char* inputColor = args.fInputColor;
421 // We don't try to optimize for this case at all
422 if (!inputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800423 fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
bsalomonae4738f2015-09-15 15:33:27 -0700424 inputColor = "ones";
425 }
426
427 // emit blend code
egdaniel4ca2e602015-11-18 08:01:26 -0800428 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700429 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700430 if (ComposeOneFragmentProcessor::kDst_Child == child) {
egdaniel4ca2e602015-11-18 08:01:26 -0800431 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700432 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800433 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700434 }
bsalomonae4738f2015-09-15 15:33:27 -0700435 }
436
437private:
egdaniel64c47282015-11-13 06:54:19 -0800438 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonae4738f2015-09-15 15:33:27 -0700439};
440
441/////////////////////////////////////////////////////////////////////
442
443GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
444
Hal Canary6f6961e2017-01-31 13:50:44 -0500445#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700446sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
bsalomonae4738f2015-09-15 15:33:27 -0700447 // Create one random frag procs.
448 // For now, we'll prevent either children from being a shader with children to prevent the
449 // possibility of an arbitrarily large tree of procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700450 sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
Brian Salomona12c1532017-02-13 12:41:44 -0500451 SkBlendMode mode;
452 ComposeOneFragmentProcessor::Child child;
453 do {
454 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
455 child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
456 } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
457 (SkBlendMode::kSrc == mode && child == kDst_Child));
bungeman06ca8ec2016-06-09 08:01:03 -0700458 return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700459}
Hal Canary6f6961e2017-01-31 13:50:44 -0500460#endif
bsalomonae4738f2015-09-15 15:33:27 -0700461
egdaniel57d3b032015-11-13 11:57:27 -0800462GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800463 return new GLComposeOneFragmentProcessor;
bsalomonae4738f2015-09-15 15:33:27 -0700464}
465
466//////////////////////////////////////////////////////////////////////////////
467
Brian Salomona12c1532017-02-13 12:41:44 -0500468// It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
469// that these factories could simply return the input FP. However, that doesn't have quite
470// the same effect as the returned compose FP will replace the FP's input with solid white and
471// ignore the original input. This could be implemented as:
472// RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
473
bungeman06ca8ec2016-06-09 08:01:03 -0700474sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400475 sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700476 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400477 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400478 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500479 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400480 case SkBlendMode::kSrc:
bsalomonae4738f2015-09-15 15:33:27 -0700481 return nullptr;
482 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700483 return sk_sp<GrFragmentProcessor>(
484 new ComposeOneFragmentProcessor(std::move(dst), mode,
485 ComposeOneFragmentProcessor::kDst_Child));
bsalomonae4738f2015-09-15 15:33:27 -0700486 }
487}
488
bungeman06ca8ec2016-06-09 08:01:03 -0700489sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400490 sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700491 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400492 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400493 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500494 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400495 case SkBlendMode::kDst:
bsalomonae4738f2015-09-15 15:33:27 -0700496 return nullptr;
497 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700498 return sk_sp<GrFragmentProcessor>(
Brian Salomona12c1532017-02-13 12:41:44 -0500499 new ComposeOneFragmentProcessor(std::move(src), mode,
bungeman06ca8ec2016-06-09 08:01:03 -0700500 ComposeOneFragmentProcessor::kSrc_Child));
wangyix809e5af2015-09-09 12:58:32 -0700501 }
502}