blob: 923c82fd26850b2278ee983a4dcc3054d77c3367 [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 Salomon94efbf52016-11-29 13:43:05 -050043 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -040044 b->add32((int)fMode);
wangyix809e5af2015-09-09 12:58:32 -070045 }
46
Mike Reed7d954ad2016-10-28 15:42:34 -040047 SkBlendMode getMode() const { return fMode; }
wangyix809e5af2015-09-09 12:58:32 -070048
Brian Salomon587e08f2017-01-27 10:59:27 -050049private:
50 static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
51 const GrFragmentProcessor* dst, SkBlendMode mode) {
Brian Salomona12c1532017-02-13 12:41:44 -050052 OptimizationFlags flags;
53 switch (mode) {
54 case SkBlendMode::kClear:
55 case SkBlendMode::kSrc:
56 case SkBlendMode::kDst:
57 SkFAIL("Should never create clear, src, or dst compose two FP.");
58 flags = kNone_OptimizationFlags;
59 break;
60
61 // Produces opaque if both src and dst are opaque.
62 case SkBlendMode::kSrcIn:
63 case SkBlendMode::kDstIn:
64 case SkBlendMode::kModulate:
65 flags = src->preservesOpaqueInput() && dst->preservesOpaqueInput()
66 ? kPreservesOpaqueInput_OptimizationFlag
67 : kNone_OptimizationFlags;
68 break;
69
70 // Produces zero when both are opaque, indeterminate if one is opaque.
71 case SkBlendMode::kSrcOut:
72 case SkBlendMode::kDstOut:
73 case SkBlendMode::kXor:
74 flags = kNone_OptimizationFlags;
75 break;
76
77 // Is opaque if the dst is opaque.
78 case SkBlendMode::kSrcATop:
79 flags = dst->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
80 : kNone_OptimizationFlags;
81 break;
82
83 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
84 case SkBlendMode::kDstATop:
85 case SkBlendMode::kScreen:
86 flags = src->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
87 : kNone_OptimizationFlags;
88 break;
89
90 // These modes are all opaque if either src or dst is opaque. All the advanced modes
91 // compute alpha as src-over.
92 case SkBlendMode::kSrcOver:
93 case SkBlendMode::kDstOver:
94 case SkBlendMode::kPlus:
95 case SkBlendMode::kOverlay:
96 case SkBlendMode::kDarken:
97 case SkBlendMode::kLighten:
98 case SkBlendMode::kColorDodge:
99 case SkBlendMode::kColorBurn:
100 case SkBlendMode::kHardLight:
101 case SkBlendMode::kSoftLight:
102 case SkBlendMode::kDifference:
103 case SkBlendMode::kExclusion:
104 case SkBlendMode::kMultiply:
105 case SkBlendMode::kHue:
106 case SkBlendMode::kSaturation:
107 case SkBlendMode::kColor:
108 case SkBlendMode::kLuminosity:
109 flags = src->preservesOpaqueInput() || dst->preservesOpaqueInput()
110 ? kPreservesOpaqueInput_OptimizationFlag
111 : kNone_OptimizationFlags;
112 break;
113 }
Brian Salomon246a3c22017-02-10 16:16:21 -0500114 if (does_cpu_blend_impl_match_gpu(mode) && src->hasConstantOutputForConstantInput() &&
115 dst->hasConstantOutputForConstantInput()) {
Brian Salomona12c1532017-02-13 12:41:44 -0500116 flags |= kConstantOutputForConstantInput_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500117 }
Brian Salomona12c1532017-02-13 12:41:44 -0500118 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500119 }
120
wangyix809e5af2015-09-09 12:58:32 -0700121 bool onIsEqual(const GrFragmentProcessor& other) const override {
bsalomonae4738f2015-09-15 15:33:27 -0700122 const ComposeTwoFragmentProcessor& cs = other.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700123 return fMode == cs.fMode;
124 }
125
Brian Salomon587e08f2017-01-27 10:59:27 -0500126 GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
127 float alpha = input.fRGBA[3];
128 input = input.opaque();
129 GrColor4f srcColor = ConstantOutputForConstantInput(this->childProcessor(0), input);
130 GrColor4f dstColor = ConstantOutputForConstantInput(this->childProcessor(1), input);
131 SkPM4f src = GrColor4fToSkPM4f(srcColor);
132 SkPM4f dst = GrColor4fToSkPM4f(dstColor);
133 auto proc = SkXfermode::GetProc4f(fMode);
134 return SkPM4fToGrColor4f(proc(src, dst)).mulByScalar(alpha);
135 }
136
egdaniel57d3b032015-11-13 11:57:27 -0800137 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyix809e5af2015-09-09 12:58:32 -0700138
Mike Reed7d954ad2016-10-28 15:42:34 -0400139 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -0700140
141 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
142
143 typedef GrFragmentProcessor INHERITED;
144};
145
146/////////////////////////////////////////////////////////////////////
147
egdaniel64c47282015-11-13 06:54:19 -0800148class GLComposeTwoFragmentProcessor : public GrGLSLFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -0700149public:
wangyix809e5af2015-09-09 12:58:32 -0700150 void emitCode(EmitArgs&) override;
151
152private:
egdaniel64c47282015-11-13 06:54:19 -0800153 typedef GrGLSLFragmentProcessor INHERITED;
wangyix809e5af2015-09-09 12:58:32 -0700154};
155
156/////////////////////////////////////////////////////////////////////
157
bsalomonae4738f2015-09-15 15:33:27 -0700158GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeTwoFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -0700159
Hal Canary6f6961e2017-01-31 13:50:44 -0500160#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700161sk_sp<GrFragmentProcessor> ComposeTwoFragmentProcessor::TestCreate(GrProcessorTestData* d) {
wangyix809e5af2015-09-09 12:58:32 -0700162 // Create two random frag procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700163 sk_sp<GrFragmentProcessor> fpA(GrProcessorUnitTest::MakeChildFP(d));
164 sk_sp<GrFragmentProcessor> fpB(GrProcessorUnitTest::MakeChildFP(d));
wangyix809e5af2015-09-09 12:58:32 -0700165
Brian Salomona12c1532017-02-13 12:41:44 -0500166 SkBlendMode mode;
167 do {
168 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
169 } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
bungeman06ca8ec2016-06-09 08:01:03 -0700170 return sk_sp<GrFragmentProcessor>(
171 new ComposeTwoFragmentProcessor(std::move(fpA), std::move(fpB), mode));
wangyix809e5af2015-09-09 12:58:32 -0700172}
Hal Canary6f6961e2017-01-31 13:50:44 -0500173#endif
wangyix809e5af2015-09-09 12:58:32 -0700174
egdaniel57d3b032015-11-13 11:57:27 -0800175GrGLSLFragmentProcessor* ComposeTwoFragmentProcessor::onCreateGLSLInstance() const{
robertphillips9cdb9922016-02-03 12:25:40 -0800176 return new GLComposeTwoFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -0700177}
178
179/////////////////////////////////////////////////////////////////////
180
bsalomonae4738f2015-09-15 15:33:27 -0700181void GLComposeTwoFragmentProcessor::emitCode(EmitArgs& args) {
wangyix809e5af2015-09-09 12:58:32 -0700182
cdalton85285412016-02-18 12:37:07 -0800183 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomonae4738f2015-09-15 15:33:27 -0700184 const ComposeTwoFragmentProcessor& cs = args.fFp.cast<ComposeTwoFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700185
bsalomonf1b7a1d2015-09-28 06:26:28 -0700186 const char* inputColor = nullptr;
bsalomonb5b60322015-09-14 12:26:33 -0700187 if (args.fInputColor) {
bsalomonf1b7a1d2015-09-28 06:26:28 -0700188 inputColor = "inputColor";
egdaniel4ca2e602015-11-18 08:01:26 -0800189 fragBuilder->codeAppendf("vec4 inputColor = vec4(%s.rgb, 1.0);", args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700190 }
wangyix809e5af2015-09-09 12:58:32 -0700191
192 // declare outputColor and emit the code for each of the two children
ethannicholas22f939e2016-10-13 13:25:34 -0700193 SkString srcColor("xfer_src");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700194 this->emitChild(0, inputColor, &srcColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700195
ethannicholas22f939e2016-10-13 13:25:34 -0700196 SkString dstColor("xfer_dst");
bsalomonf1b7a1d2015-09-28 06:26:28 -0700197 this->emitChild(1, inputColor, &dstColor, args);
wangyix809e5af2015-09-09 12:58:32 -0700198
199 // emit blend code
Mike Reed7d954ad2016-10-28 15:42:34 -0400200 SkBlendMode mode = cs.getMode();
egdaniel4ca2e602015-11-18 08:01:26 -0800201 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
202 GrGLSLBlend::AppendMode(fragBuilder,
203 srcColor.c_str(),
204 dstColor.c_str(),
205 args.fOutputColor,
206 mode);
wangyix809e5af2015-09-09 12:58:32 -0700207
208 // re-multiply the output color by the input color's alpha
bsalomonf1b7a1d2015-09-28 06:26:28 -0700209 if (args.fInputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800210 fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
bsalomonb5b60322015-09-14 12:26:33 -0700211 }
wangyix809e5af2015-09-09 12:58:32 -0700212}
213
bungeman06ca8ec2016-06-09 08:01:03 -0700214sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
Mike Reed7d954ad2016-10-28 15:42:34 -0400215 sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700216 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400217 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400218 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
bungeman06ca8ec2016-06-09 08:01:03 -0700219 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400220 case SkBlendMode::kSrc:
bungeman06ca8ec2016-06-09 08:01:03 -0700221 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400222 case SkBlendMode::kDst:
bungeman06ca8ec2016-06-09 08:01:03 -0700223 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700224 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700225 return sk_sp<GrFragmentProcessor>(
226 new ComposeTwoFragmentProcessor(std::move(src), std::move(dst), mode));
bsalomonae4738f2015-09-15 15:33:27 -0700227 }
228}
229
230//////////////////////////////////////////////////////////////////////////////
231
232class ComposeOneFragmentProcessor : public GrFragmentProcessor {
233public:
234 enum Child {
235 kDst_Child,
236 kSrc_Child,
237 };
238
Brian Salomona12c1532017-02-13 12:41:44 -0500239 ComposeOneFragmentProcessor(sk_sp<GrFragmentProcessor> fp, SkBlendMode mode, Child child)
240 : INHERITED(OptFlags(fp.get(), mode, child)), fMode(mode), fChild(child) {
bsalomonae4738f2015-09-15 15:33:27 -0700241 this->initClassID<ComposeOneFragmentProcessor>();
Brian Salomona12c1532017-02-13 12:41:44 -0500242 SkDEBUGCODE(int dstIndex =) this->registerChildProcessor(std::move(fp));
bsalomonae4738f2015-09-15 15:33:27 -0700243 SkASSERT(0 == dstIndex);
244 }
245
246 const char* name() const override { return "ComposeOne"; }
247
robertphillips783a4da2015-11-19 14:00:02 -0800248 SkString dumpInfo() const override {
249 SkString str;
250
251 for (int i = 0; i < this->numChildProcessors(); ++i) {
252 str.append(this->childProcessor(i).dumpInfo());
253 }
254 return str;
255 }
256
Brian Salomon94efbf52016-11-29 13:43:05 -0500257 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
Mike Reed7d954ad2016-10-28 15:42:34 -0400258 GR_STATIC_ASSERT(((int)SkBlendMode::kLastMode & SK_MaxU16) == (int)SkBlendMode::kLastMode);
259 b->add32((int)fMode | (fChild << 16));
bsalomonae4738f2015-09-15 15:33:27 -0700260 }
261
Mike Reed7d954ad2016-10-28 15:42:34 -0400262 SkBlendMode mode() const { return fMode; }
bsalomonae4738f2015-09-15 15:33:27 -0700263
264 Child child() const { return fChild; }
265
Brian Salomon587e08f2017-01-27 10:59:27 -0500266private:
Brian Salomona12c1532017-02-13 12:41:44 -0500267 OptimizationFlags OptFlags(const GrFragmentProcessor* fp, SkBlendMode mode, Child child) {
268 OptimizationFlags flags;
269 switch (mode) {
270 case SkBlendMode::kClear:
271 SkFAIL("Should never create clear compose one FP.");
272 flags = kNone_OptimizationFlags;
273 break;
274
275 case SkBlendMode::kSrc:
276 SkASSERT(child == kSrc_Child);
277 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
278 : kNone_OptimizationFlags;
279 break;
280
281 case SkBlendMode::kDst:
282 SkASSERT(child == kDst_Child);
283 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
284 : kNone_OptimizationFlags;
285 break;
286
287 // Produces opaque if both src and dst are opaque. These also will modulate the child's
Brian Salomone0265112017-02-21 14:19:07 -0500288 // output by either the input color or alpha. However, if the child is not compatible
289 // with the coverage as alpha then it may produce a color that is not valid premul.
Brian Salomona12c1532017-02-13 12:41:44 -0500290 case SkBlendMode::kSrcIn:
291 case SkBlendMode::kDstIn:
292 case SkBlendMode::kModulate:
Brian Salomone0265112017-02-21 14:19:07 -0500293 if (fp->compatibleWithCoverageAsAlpha()) {
294 if (fp->preservesOpaqueInput()) {
295 flags = kPreservesOpaqueInput_OptimizationFlag |
296 kCompatibleWithCoverageAsAlpha_OptimizationFlag;
297 } else {
298 flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
299 }
Brian Salomonf3b995b2017-02-15 10:22:23 -0500300 } else {
Brian Salomone0265112017-02-21 14:19:07 -0500301 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
302 : kNone_OptimizationFlags;
Brian Salomonf3b995b2017-02-15 10:22:23 -0500303 }
Brian Salomona12c1532017-02-13 12:41:44 -0500304 break;
305
306 // Produces zero when both are opaque, indeterminate if one is opaque.
307 case SkBlendMode::kSrcOut:
308 case SkBlendMode::kDstOut:
309 case SkBlendMode::kXor:
310 flags = kNone_OptimizationFlags;
311 break;
312
313 // Is opaque if the dst is opaque.
314 case SkBlendMode::kSrcATop:
315 if (child == kDst_Child) {
316 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
317 : kNone_OptimizationFlags;
318 } else {
319 flags = kPreservesOpaqueInput_OptimizationFlag;
320 }
321 break;
322
323 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
324 case SkBlendMode::kDstATop:
325 case SkBlendMode::kScreen:
326 if (child == kSrc_Child) {
327 flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
328 : kNone_OptimizationFlags;
329 } else {
330 flags = kPreservesOpaqueInput_OptimizationFlag;
331 }
332 break;
333
334 // These modes are all opaque if either src or dst is opaque. All the advanced modes
335 // compute alpha as src-over.
336 case SkBlendMode::kSrcOver:
337 case SkBlendMode::kDstOver:
338 case SkBlendMode::kPlus:
339 case SkBlendMode::kOverlay:
340 case SkBlendMode::kDarken:
341 case SkBlendMode::kLighten:
342 case SkBlendMode::kColorDodge:
343 case SkBlendMode::kColorBurn:
344 case SkBlendMode::kHardLight:
345 case SkBlendMode::kSoftLight:
346 case SkBlendMode::kDifference:
347 case SkBlendMode::kExclusion:
348 case SkBlendMode::kMultiply:
349 case SkBlendMode::kHue:
350 case SkBlendMode::kSaturation:
351 case SkBlendMode::kColor:
352 case SkBlendMode::kLuminosity:
353 flags = kPreservesOpaqueInput_OptimizationFlag;
354 break;
Brian Salomon587e08f2017-01-27 10:59:27 -0500355 }
Brian Salomona12c1532017-02-13 12:41:44 -0500356 if (does_cpu_blend_impl_match_gpu(mode) && fp->hasConstantOutputForConstantInput()) {
357 flags |= kConstantOutputForConstantInput_OptimizationFlag;
358 }
359 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500360 }
361
bsalomonae4738f2015-09-15 15:33:27 -0700362 bool onIsEqual(const GrFragmentProcessor& that) const override {
363 return fMode == that.cast<ComposeOneFragmentProcessor>().fMode;
364 }
365
Brian Salomon587e08f2017-01-27 10:59:27 -0500366 GrColor4f constantOutputForConstantInput(GrColor4f inputColor) const override {
367 GrColor4f childColor =
368 ConstantOutputForConstantInput(this->childProcessor(0), GrColor4f::OpaqueWhite());
369 SkPM4f src, dst;
370 if (kSrc_Child == fChild) {
371 src = GrColor4fToSkPM4f(childColor);
372 dst = GrColor4fToSkPM4f(inputColor);
373 } else {
374 src = GrColor4fToSkPM4f(inputColor);
375 dst = GrColor4fToSkPM4f(childColor);
376 }
377 auto proc = SkXfermode::GetProc4f(fMode);
378 return SkPM4fToGrColor4f(proc(src, dst));
379 }
380
bsalomonae4738f2015-09-15 15:33:27 -0700381private:
egdaniel57d3b032015-11-13 11:57:27 -0800382 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
bsalomonae4738f2015-09-15 15:33:27 -0700383
Mike Reed7d954ad2016-10-28 15:42:34 -0400384 SkBlendMode fMode;
385 Child fChild;
bsalomonae4738f2015-09-15 15:33:27 -0700386
387 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
388
389 typedef GrFragmentProcessor INHERITED;
390};
391
392//////////////////////////////////////////////////////////////////////////////
393
egdaniel64c47282015-11-13 06:54:19 -0800394class GLComposeOneFragmentProcessor : public GrGLSLFragmentProcessor {
bsalomonae4738f2015-09-15 15:33:27 -0700395public:
bsalomonae4738f2015-09-15 15:33:27 -0700396 void emitCode(EmitArgs& args) override {
cdalton85285412016-02-18 12:37:07 -0800397 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Mike Reed7d954ad2016-10-28 15:42:34 -0400398 SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
bsalomonae4738f2015-09-15 15:33:27 -0700399 ComposeOneFragmentProcessor::Child child =
400 args.fFp.cast<ComposeOneFragmentProcessor>().child();
bsalomon38ddbad2015-09-24 06:00:00 -0700401 SkString childColor("child");
402 this->emitChild(0, nullptr, &childColor, args);
bsalomonae4738f2015-09-15 15:33:27 -0700403
404 const char* inputColor = args.fInputColor;
405 // We don't try to optimize for this case at all
406 if (!inputColor) {
egdaniel4ca2e602015-11-18 08:01:26 -0800407 fragBuilder->codeAppendf("const vec4 ones = vec4(1);");
bsalomonae4738f2015-09-15 15:33:27 -0700408 inputColor = "ones";
409 }
410
411 // emit blend code
egdaniel4ca2e602015-11-18 08:01:26 -0800412 fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkXfermode::ModeName(mode));
bsalomon38ddbad2015-09-24 06:00:00 -0700413 const char* childStr = childColor.c_str();
bsalomonae4738f2015-09-15 15:33:27 -0700414 if (ComposeOneFragmentProcessor::kDst_Child == child) {
egdaniel4ca2e602015-11-18 08:01:26 -0800415 GrGLSLBlend::AppendMode(fragBuilder, inputColor, childStr, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700416 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800417 GrGLSLBlend::AppendMode(fragBuilder, childStr, inputColor, args.fOutputColor, mode);
bsalomonae4738f2015-09-15 15:33:27 -0700418 }
bsalomonae4738f2015-09-15 15:33:27 -0700419 }
420
421private:
egdaniel64c47282015-11-13 06:54:19 -0800422 typedef GrGLSLFragmentProcessor INHERITED;
bsalomonae4738f2015-09-15 15:33:27 -0700423};
424
425/////////////////////////////////////////////////////////////////////
426
427GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ComposeOneFragmentProcessor);
428
Hal Canary6f6961e2017-01-31 13:50:44 -0500429#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700430sk_sp<GrFragmentProcessor> ComposeOneFragmentProcessor::TestCreate(GrProcessorTestData* d) {
bsalomonae4738f2015-09-15 15:33:27 -0700431 // Create one random frag procs.
432 // For now, we'll prevent either children from being a shader with children to prevent the
433 // possibility of an arbitrarily large tree of procs.
bungeman06ca8ec2016-06-09 08:01:03 -0700434 sk_sp<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
Brian Salomona12c1532017-02-13 12:41:44 -0500435 SkBlendMode mode;
436 ComposeOneFragmentProcessor::Child child;
437 do {
438 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
439 child = d->fRandom->nextBool() ? kDst_Child : kSrc_Child;
440 } while (SkBlendMode::kClear == mode || (SkBlendMode::kDst == mode && child == kSrc_Child) ||
441 (SkBlendMode::kSrc == mode && child == kDst_Child));
bungeman06ca8ec2016-06-09 08:01:03 -0700442 return sk_sp<GrFragmentProcessor>(new ComposeOneFragmentProcessor(std::move(dst), mode, child));
bsalomonae4738f2015-09-15 15:33:27 -0700443}
Hal Canary6f6961e2017-01-31 13:50:44 -0500444#endif
bsalomonae4738f2015-09-15 15:33:27 -0700445
egdaniel57d3b032015-11-13 11:57:27 -0800446GrGLSLFragmentProcessor* ComposeOneFragmentProcessor::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800447 return new GLComposeOneFragmentProcessor;
bsalomonae4738f2015-09-15 15:33:27 -0700448}
449
450//////////////////////////////////////////////////////////////////////////////
451
Brian Salomona12c1532017-02-13 12:41:44 -0500452// It may seems as though when the input FP is the dst and the mode is kDst (or same for src/kSrc)
453// that these factories could simply return the input FP. However, that doesn't have quite
454// the same effect as the returned compose FP will replace the FP's input with solid white and
455// ignore the original input. This could be implemented as:
456// RunInSeries(ConstColor(GrColor_WHITE, kIgnoreInput), inputFP).
457
bungeman06ca8ec2016-06-09 08:01:03 -0700458sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400459 sk_sp<GrFragmentProcessor> dst, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700460 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400461 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400462 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500463 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400464 case SkBlendMode::kSrc:
bsalomonae4738f2015-09-15 15:33:27 -0700465 return nullptr;
466 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700467 return sk_sp<GrFragmentProcessor>(
468 new ComposeOneFragmentProcessor(std::move(dst), mode,
469 ComposeOneFragmentProcessor::kDst_Child));
bsalomonae4738f2015-09-15 15:33:27 -0700470 }
471}
472
bungeman06ca8ec2016-06-09 08:01:03 -0700473sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
Mike Reed7d954ad2016-10-28 15:42:34 -0400474 sk_sp<GrFragmentProcessor> src, SkBlendMode mode) {
bsalomonae4738f2015-09-15 15:33:27 -0700475 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400476 case SkBlendMode::kClear:
Brian Osman618d3042016-10-25 10:51:28 -0400477 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
Brian Salomona12c1532017-02-13 12:41:44 -0500478 GrConstColorProcessor::kIgnore_InputMode);
Mike Reed7d954ad2016-10-28 15:42:34 -0400479 case SkBlendMode::kDst:
bsalomonae4738f2015-09-15 15:33:27 -0700480 return nullptr;
481 default:
bungeman06ca8ec2016-06-09 08:01:03 -0700482 return sk_sp<GrFragmentProcessor>(
Brian Salomona12c1532017-02-13 12:41:44 -0500483 new ComposeOneFragmentProcessor(std::move(src), mode,
bungeman06ca8ec2016-06-09 08:01:03 -0700484 ComposeOneFragmentProcessor::kSrc_Child));
wangyix809e5af2015-09-09 12:58:32 -0700485 }
486}