blob: 8604bba7c0aa80d383b1d5107859d20120aa106c [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
John Stilesf743d4e2020-07-23 11:35:08 -04008#include "src/gpu/effects/GrBlendFragmentProcessor.h"
wangyix809e5af2015-09-09 12:58:32 -07009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/GrFragmentProcessor.h"
11#include "src/gpu/SkGr.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/glsl/GrGLSLBlend.h"
13#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
14#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
wangyix809e5af2015-09-09 12:58:32 -070015
John Stiles04c61222021-07-29 19:36:49 -040016// Some of the CPU implementations of blend modes differ from the GPU enough that
17// we can't use the CPU implementation to implement constantOutputForConstantInput.
Brian Salomon246a3c22017-02-10 16:16:21 -050018static inline bool does_cpu_blend_impl_match_gpu(SkBlendMode mode) {
John Stiles04c61222021-07-29 19:36:49 -040019 // The non-separable modes differ too much. So does SoftLight. ColorBurn differs too much on our
20 // test iOS device, but we just disable it across the board since it might differ on untested
21 // GPUs.
Brian Salomon246a3c22017-02-10 16:16:21 -050022 return mode <= SkBlendMode::kLastSeparableMode && mode != SkBlendMode::kSoftLight &&
23 mode != SkBlendMode::kColorBurn;
24}
25
26//////////////////////////////////////////////////////////////////////////////
27
John Stilesf743d4e2020-07-23 11:35:08 -040028class BlendFragmentProcessor : public GrFragmentProcessor {
wangyix809e5af2015-09-09 12:58:32 -070029public:
Brian Salomonaff329b2017-08-11 09:40:37 -040030 static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> src,
31 std::unique_ptr<GrFragmentProcessor> dst,
Brian Salomon4b6e2f02021-07-08 14:04:21 -040032 SkBlendMode mode) {
Brian Salomonaff329b2017-08-11 09:40:37 -040033 return std::unique_ptr<GrFragmentProcessor>(
Brian Salomon4b6e2f02021-07-08 14:04:21 -040034 new BlendFragmentProcessor(std::move(src), std::move(dst), mode));
wangyix809e5af2015-09-09 12:58:32 -070035 }
36
John Stilesf743d4e2020-07-23 11:35:08 -040037 const char* name() const override { return "Blend"; }
wangyix809e5af2015-09-09 12:58:32 -070038
Brian Salomonaff329b2017-08-11 09:40:37 -040039 std::unique_ptr<GrFragmentProcessor> clone() const override;
wangyix809e5af2015-09-09 12:58:32 -070040
Mike Reed7d954ad2016-10-28 15:42:34 -040041 SkBlendMode getMode() const { return fMode; }
wangyix809e5af2015-09-09 12:58:32 -070042
Brian Salomon587e08f2017-01-27 10:59:27 -050043private:
John Stilesf743d4e2020-07-23 11:35:08 -040044 BlendFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
Brian Salomon4b6e2f02021-07-08 14:04:21 -040045 std::unique_ptr<GrFragmentProcessor> dst,
46 SkBlendMode mode)
John Stilesf743d4e2020-07-23 11:35:08 -040047 : INHERITED(kBlendFragmentProcessor_ClassID, OptFlags(src.get(), dst.get(), mode))
Brian Salomon4b6e2f02021-07-08 14:04:21 -040048 , fMode(mode) {
John Stiles04c61222021-07-29 19:36:49 -040049 this->setIsBlendFunction();
Brian Osman12c5d292020-07-13 16:11:35 -040050 this->registerChild(std::move(src));
51 this->registerChild(std::move(dst));
John Stiles5c57e882020-06-30 14:05:03 -040052 }
53
John Stilesf743d4e2020-07-23 11:35:08 -040054 BlendFragmentProcessor(const BlendFragmentProcessor& that)
John Stiles307f8f52021-08-09 15:36:59 -040055 : INHERITED(that)
56 , fMode(that.fMode) {}
Robert Phillips1c9686b2017-06-30 08:40:28 -040057
John Stilesaf366522020-08-13 09:57:34 -040058#if GR_TEST_UTILS
59 SkString onDumpInfo() const override {
60 return SkStringPrintf("(fMode=%s)", SkBlendMode_Name(fMode));
61 }
62#endif
63
Brian Salomon587e08f2017-01-27 10:59:27 -050064 static OptimizationFlags OptFlags(const GrFragmentProcessor* src,
65 const GrFragmentProcessor* dst, SkBlendMode mode) {
Brian Salomona12c1532017-02-13 12:41:44 -050066 OptimizationFlags flags;
67 switch (mode) {
68 case SkBlendMode::kClear:
69 case SkBlendMode::kSrc:
70 case SkBlendMode::kDst:
John Stiles04c61222021-07-29 19:36:49 -040071 SkDEBUGFAIL("Shouldn't have created a Blend FP as 'clear', 'src', or 'dst'.");
Brian Salomona12c1532017-02-13 12:41:44 -050072 flags = kNone_OptimizationFlags;
73 break;
74
John Stiles5c57e882020-06-30 14:05:03 -040075 // Produces opaque if both src and dst are opaque. These also will modulate the child's
76 // output by either the input color or alpha. However, if the child is not compatible
77 // with the coverage as alpha then it may produce a color that is not valid premul.
Brian Salomona12c1532017-02-13 12:41:44 -050078 case SkBlendMode::kSrcIn:
79 case SkBlendMode::kDstIn:
80 case SkBlendMode::kModulate:
John Stiles5c57e882020-06-30 14:05:03 -040081 if (src && dst) {
82 flags = ProcessorOptimizationFlags(src) & ProcessorOptimizationFlags(dst) &
83 kPreservesOpaqueInput_OptimizationFlag;
84 } else if (src) {
85 flags = ProcessorOptimizationFlags(src) &
86 ~kConstantOutputForConstantInput_OptimizationFlag;
87 } else if (dst) {
88 flags = ProcessorOptimizationFlags(dst) &
89 ~kConstantOutputForConstantInput_OptimizationFlag;
90 } else {
91 flags = kNone_OptimizationFlags;
92 }
Brian Salomona12c1532017-02-13 12:41:44 -050093 break;
94
95 // Produces zero when both are opaque, indeterminate if one is opaque.
96 case SkBlendMode::kSrcOut:
97 case SkBlendMode::kDstOut:
98 case SkBlendMode::kXor:
99 flags = kNone_OptimizationFlags;
100 break;
101
102 // Is opaque if the dst is opaque.
103 case SkBlendMode::kSrcATop:
Brian Osman8f391372021-04-29 15:27:34 -0400104 flags = ProcessorOptimizationFlags(dst) & kPreservesOpaqueInput_OptimizationFlag;
Brian Salomona12c1532017-02-13 12:41:44 -0500105 break;
106
107 // DstATop is the converse of kSrcATop. Screen is also opaque if the src is a opaque.
108 case SkBlendMode::kDstATop:
109 case SkBlendMode::kScreen:
Brian Osman8f391372021-04-29 15:27:34 -0400110 flags = ProcessorOptimizationFlags(src) & kPreservesOpaqueInput_OptimizationFlag;
Brian Salomona12c1532017-02-13 12:41:44 -0500111 break;
112
113 // These modes are all opaque if either src or dst is opaque. All the advanced modes
114 // compute alpha as src-over.
115 case SkBlendMode::kSrcOver:
116 case SkBlendMode::kDstOver:
117 case SkBlendMode::kPlus:
118 case SkBlendMode::kOverlay:
119 case SkBlendMode::kDarken:
120 case SkBlendMode::kLighten:
121 case SkBlendMode::kColorDodge:
122 case SkBlendMode::kColorBurn:
123 case SkBlendMode::kHardLight:
124 case SkBlendMode::kSoftLight:
125 case SkBlendMode::kDifference:
126 case SkBlendMode::kExclusion:
127 case SkBlendMode::kMultiply:
128 case SkBlendMode::kHue:
129 case SkBlendMode::kSaturation:
130 case SkBlendMode::kColor:
131 case SkBlendMode::kLuminosity:
Brian Osman8f391372021-04-29 15:27:34 -0400132 flags = (ProcessorOptimizationFlags(src) | ProcessorOptimizationFlags(dst)) &
133 kPreservesOpaqueInput_OptimizationFlag;
Brian Salomona12c1532017-02-13 12:41:44 -0500134 break;
135 }
John Stiles5c57e882020-06-30 14:05:03 -0400136 if (does_cpu_blend_impl_match_gpu(mode) &&
John Stiles04c61222021-07-29 19:36:49 -0400137 (!src || src->hasConstantOutputForConstantInput()) &&
138 (!dst || dst->hasConstantOutputForConstantInput())) {
Brian Salomona12c1532017-02-13 12:41:44 -0500139 flags |= kConstantOutputForConstantInput_OptimizationFlag;
Brian Salomon587e08f2017-01-27 10:59:27 -0500140 }
Brian Salomona12c1532017-02-13 12:41:44 -0500141 return flags;
Brian Salomon587e08f2017-01-27 10:59:27 -0500142 }
143
Brian Salomon13b28732021-08-06 15:33:58 -0400144 void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400145 b->add32((int)fMode);
146 }
147
wangyix809e5af2015-09-09 12:58:32 -0700148 bool onIsEqual(const GrFragmentProcessor& other) const override {
John Stilesf743d4e2020-07-23 11:35:08 -0400149 const BlendFragmentProcessor& cs = other.cast<BlendFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700150 return fMode == cs.fMode;
151 }
152
Brian Osman1d5b5982018-10-01 13:41:39 -0400153 SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
Brian Osman12c5d292020-07-13 16:11:35 -0400154 const auto* src = this->childProcessor(0);
155 const auto* dst = this->childProcessor(1);
John Stiles5c57e882020-06-30 14:05:03 -0400156
Brian Salomon4b6e2f02021-07-08 14:04:21 -0400157 SkPMColor4f srcColor = ConstantOutputForConstantInput(src, input);
158 SkPMColor4f dstColor = ConstantOutputForConstantInput(dst, input);
John Stiles09dbeff2020-06-30 14:07:57 -0400159
Brian Salomon4b6e2f02021-07-08 14:04:21 -0400160 return SkBlendMode_Apply(fMode, srcColor, dstColor);
Brian Salomon587e08f2017-01-27 10:59:27 -0500161 }
162
Brian Salomon3176e862021-08-09 11:23:04 -0400163 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override;
wangyix809e5af2015-09-09 12:58:32 -0700164
Mike Reed7d954ad2016-10-28 15:42:34 -0400165 SkBlendMode fMode;
wangyix809e5af2015-09-09 12:58:32 -0700166
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400167 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
wangyix809e5af2015-09-09 12:58:32 -0700168
John Stiles7571f9e2020-09-02 22:42:33 -0400169 using INHERITED = GrFragmentProcessor;
wangyix809e5af2015-09-09 12:58:32 -0700170};
171
172/////////////////////////////////////////////////////////////////////
173
Brian Salomon3176e862021-08-09 11:23:04 -0400174class GLBlendFragmentProcessor : public GrFragmentProcessor::ProgramImpl {
wangyix809e5af2015-09-09 12:58:32 -0700175public:
wangyix809e5af2015-09-09 12:58:32 -0700176 void emitCode(EmitArgs&) override;
177
178private:
Brian Salomon3176e862021-08-09 11:23:04 -0400179 using INHERITED = ProgramImpl;
wangyix809e5af2015-09-09 12:58:32 -0700180};
181
182/////////////////////////////////////////////////////////////////////
183
John Stilesf743d4e2020-07-23 11:35:08 -0400184GR_DEFINE_FRAGMENT_PROCESSOR_TEST(BlendFragmentProcessor);
wangyix809e5af2015-09-09 12:58:32 -0700185
Hal Canary6f6961e2017-01-31 13:50:44 -0500186#if GR_TEST_UTILS
John Stilesf743d4e2020-07-23 11:35:08 -0400187std::unique_ptr<GrFragmentProcessor> BlendFragmentProcessor::TestCreate(GrProcessorTestData* d) {
John Stiles87d0a2f2020-08-10 13:12:41 -0400188 // Create one or two random fragment processors.
189 std::unique_ptr<GrFragmentProcessor> src(GrProcessorUnitTest::MakeOptionalChildFP(d));
190 std::unique_ptr<GrFragmentProcessor> dst(GrProcessorUnitTest::MakeChildFP(d));
191 if (d->fRandom->nextBool()) {
192 std::swap(src, dst);
193 }
wangyix809e5af2015-09-09 12:58:32 -0700194
Brian Salomona12c1532017-02-13 12:41:44 -0500195 SkBlendMode mode;
196 do {
197 mode = static_cast<SkBlendMode>(d->fRandom->nextRangeU(0, (int)SkBlendMode::kLastMode));
198 } while (SkBlendMode::kClear == mode || SkBlendMode::kSrc == mode || SkBlendMode::kDst == mode);
Brian Salomonaff329b2017-08-11 09:40:37 -0400199 return std::unique_ptr<GrFragmentProcessor>(
Brian Salomon4b6e2f02021-07-08 14:04:21 -0400200 new BlendFragmentProcessor(std::move(src), std::move(dst), mode));
wangyix809e5af2015-09-09 12:58:32 -0700201}
Hal Canary6f6961e2017-01-31 13:50:44 -0500202#endif
wangyix809e5af2015-09-09 12:58:32 -0700203
John Stilesf743d4e2020-07-23 11:35:08 -0400204std::unique_ptr<GrFragmentProcessor> BlendFragmentProcessor::clone() const {
205 return std::unique_ptr<GrFragmentProcessor>(new BlendFragmentProcessor(*this));
Brian Salomonfb7c83a2017-07-26 13:57:33 -0400206}
207
Brian Salomon3176e862021-08-09 11:23:04 -0400208std::unique_ptr<GrFragmentProcessor::ProgramImpl> BlendFragmentProcessor::onMakeProgramImpl() const {
Brian Salomon18ab2032021-02-23 10:07:05 -0500209 return std::make_unique<GLBlendFragmentProcessor>();
wangyix809e5af2015-09-09 12:58:32 -0700210}
211
212/////////////////////////////////////////////////////////////////////
213
John Stilesf743d4e2020-07-23 11:35:08 -0400214void GLBlendFragmentProcessor::emitCode(EmitArgs& args) {
cdalton85285412016-02-18 12:37:07 -0800215 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
John Stilesf743d4e2020-07-23 11:35:08 -0400216 const BlendFragmentProcessor& cs = args.fFp.cast<BlendFragmentProcessor>();
John Stiles5c57e882020-06-30 14:05:03 -0400217 SkBlendMode mode = cs.getMode();
wangyix809e5af2015-09-09 12:58:32 -0700218
Brian Salomon4b6e2f02021-07-08 14:04:21 -0400219 fragBuilder->codeAppendf("// Blend mode: %s\n", SkBlendMode_Name(mode));
John Stiles5c57e882020-06-30 14:05:03 -0400220
Brian Salomon4b6e2f02021-07-08 14:04:21 -0400221 // Invoke src/dst with our input color (or substitute input color if no child FP)
John Stiles04c61222021-07-29 19:36:49 -0400222 SkString srcColor = this->invokeChild(0, args);
223 SkString dstColor = this->invokeChild(1, args);
Ethan Nicholas62ae6642017-07-10 17:43:15 +0000224
John Stiles5c57e882020-06-30 14:05:03 -0400225 // Blend src and dst colors together.
John Stiles04c61222021-07-29 19:36:49 -0400226 fragBuilder->codeAppendf("return %s(%s, %s);", GrGLSLBlend::BlendFuncName(mode),
John Stiles49643002020-10-19 18:52:40 -0400227 srcColor.c_str(), dstColor.c_str());
wangyix809e5af2015-09-09 12:58:32 -0700228}
229
John Stiles5c57e882020-06-30 14:05:03 -0400230//////////////////////////////////////////////////////////////////////////////
231
John Stilesf743d4e2020-07-23 11:35:08 -0400232std::unique_ptr<GrFragmentProcessor> GrBlendFragmentProcessor::Make(
Brian Salomonaff329b2017-08-11 09:40:37 -0400233 std::unique_ptr<GrFragmentProcessor> src,
234 std::unique_ptr<GrFragmentProcessor> dst,
Brian Salomon4b6e2f02021-07-08 14:04:21 -0400235 SkBlendMode mode) {
wangyix809e5af2015-09-09 12:58:32 -0700236 switch (mode) {
Mike Reed7d954ad2016-10-28 15:42:34 -0400237 case SkBlendMode::kClear:
Brian Salomon354147a2021-04-14 11:15:05 -0400238 return GrFragmentProcessor::MakeColor(SK_PMColor4fTRANSPARENT);
Mike Reed7d954ad2016-10-28 15:42:34 -0400239 case SkBlendMode::kSrc:
Brian Salomon8573dab2021-07-08 13:58:47 -0400240 return src;
Mike Reed7d954ad2016-10-28 15:42:34 -0400241 case SkBlendMode::kDst:
Brian Salomon8573dab2021-07-08 13:58:47 -0400242 return dst;
wangyix809e5af2015-09-09 12:58:32 -0700243 default:
Brian Salomon4b6e2f02021-07-08 14:04:21 -0400244 return BlendFragmentProcessor::Make(std::move(src), std::move(dst), mode);
wangyix809e5af2015-09-09 12:58:32 -0700245 }
246}