Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / ganesh / effects / GrCustomXfermode.cpp
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 "src/gpu/ganesh/effects/GrCustomXfermode.h"
9
10 #include "src/gpu/KeyBuilder.h"
11 #include "src/gpu/ganesh/GrCaps.h"
12 #include "src/gpu/ganesh/GrFragmentProcessor.h"
13 #include "src/gpu/ganesh/GrPipeline.h"
14 #include "src/gpu/ganesh/GrProcessor.h"
15 #include "src/gpu/ganesh/GrShaderCaps.h"
16 #include "src/gpu/ganesh/GrXferProcessor.h"
17 #include "src/gpu/ganesh/glsl/GrGLSLBlend.h"
18 #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
19 #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
20 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
21
22 bool GrCustomXfermode::IsSupportedMode(SkBlendMode mode) {
23     return (int)mode  > (int)SkBlendMode::kLastCoeffMode &&
24            (int)mode <= (int)SkBlendMode::kLastMode;
25 }
26
27 ///////////////////////////////////////////////////////////////////////////////
28 // Static helpers
29 ///////////////////////////////////////////////////////////////////////////////
30
31 static constexpr skgpu::BlendEquation hw_blend_equation(SkBlendMode mode) {
32     constexpr int kEqOffset = ((int)skgpu::BlendEquation::kOverlay - (int)SkBlendMode::kOverlay);
33     static_assert((int)skgpu::BlendEquation::kOverlay == (int)SkBlendMode::kOverlay + kEqOffset);
34     static_assert((int)skgpu::BlendEquation::kDarken == (int)SkBlendMode::kDarken + kEqOffset);
35     static_assert((int)skgpu::BlendEquation::kLighten == (int)SkBlendMode::kLighten + kEqOffset);
36     static_assert((int)skgpu::BlendEquation::kColorDodge == (int)SkBlendMode::kColorDodge + kEqOffset);
37     static_assert((int)skgpu::BlendEquation::kColorBurn == (int)SkBlendMode::kColorBurn + kEqOffset);
38     static_assert((int)skgpu::BlendEquation::kHardLight == (int)SkBlendMode::kHardLight + kEqOffset);
39     static_assert((int)skgpu::BlendEquation::kSoftLight == (int)SkBlendMode::kSoftLight + kEqOffset);
40     static_assert((int)skgpu::BlendEquation::kDifference == (int)SkBlendMode::kDifference + kEqOffset);
41     static_assert((int)skgpu::BlendEquation::kExclusion == (int)SkBlendMode::kExclusion + kEqOffset);
42     static_assert((int)skgpu::BlendEquation::kMultiply == (int)SkBlendMode::kMultiply + kEqOffset);
43     static_assert((int)skgpu::BlendEquation::kHSLHue == (int)SkBlendMode::kHue + kEqOffset);
44     static_assert((int)skgpu::BlendEquation::kHSLSaturation == (int)SkBlendMode::kSaturation + kEqOffset);
45     static_assert((int)skgpu::BlendEquation::kHSLColor == (int)SkBlendMode::kColor + kEqOffset);
46     static_assert((int)skgpu::BlendEquation::kHSLLuminosity == (int)SkBlendMode::kLuminosity + kEqOffset);
47
48     // There's an illegal BlendEquation that corresponds to no SkBlendMode, hence the extra +1.
49     static_assert(skgpu::kBlendEquationCnt == (int)SkBlendMode::kLastMode + 1 + 1 + kEqOffset);
50
51     return static_cast<skgpu::BlendEquation>((int)mode + kEqOffset);
52 #undef EQ_OFFSET
53 }
54
55 static bool can_use_hw_blend_equation(skgpu::BlendEquation equation,
56                                       GrProcessorAnalysisCoverage coverage, const GrCaps& caps) {
57     if (!caps.advancedBlendEquationSupport()) {
58         return false;
59     }
60     if (GrProcessorAnalysisCoverage::kLCD == coverage) {
61         return false; // LCD coverage must be applied after the blend equation.
62     }
63     if (caps.isAdvancedBlendEquationDisabled(equation)) {
64         return false;
65     }
66     return true;
67 }
68
69 ///////////////////////////////////////////////////////////////////////////////
70 // Xfer Processor
71 ///////////////////////////////////////////////////////////////////////////////
72
73 class CustomXP : public GrXferProcessor {
74 public:
75     CustomXP(SkBlendMode mode, skgpu::BlendEquation hwBlendEquation)
76         : INHERITED(kCustomXP_ClassID)
77         , fMode(mode)
78         , fHWBlendEquation(hwBlendEquation) {}
79
80     CustomXP(SkBlendMode mode, GrProcessorAnalysisCoverage coverage)
81             : INHERITED(kCustomXP_ClassID, /*willReadDstColor=*/true, coverage)
82             , fMode(mode)
83             , fHWBlendEquation(skgpu::BlendEquation::kIllegal) {
84     }
85
86     const char* name() const override { return "Custom Xfermode"; }
87
88     std::unique_ptr<ProgramImpl> makeProgramImpl() const override;
89
90     GrXferBarrierType xferBarrierType(const GrCaps&) const override;
91
92 private:
93     bool hasHWBlendEquation() const { return skgpu::BlendEquation::kIllegal != fHWBlendEquation; }
94
95     void onAddToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override;
96
97     void onGetBlendInfo(BlendInfo*) const override;
98
99     bool onIsEqual(const GrXferProcessor& xpBase) const override;
100
101     const SkBlendMode          fMode;
102     const skgpu::BlendEquation fHWBlendEquation;
103
104     using INHERITED = GrXferProcessor;
105 };
106
107 void CustomXP::onAddToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const {
108     if (this->hasHWBlendEquation()) {
109         SkASSERT(caps.advBlendEqInteraction() > 0);  // 0 will mean !xp.hasHWBlendEquation().
110         b->addBool(true, "has hardware blend equation");
111         b->add32(caps.advBlendEqInteraction());
112     } else {
113         b->addBool(false, "has hardware blend equation");
114         b->add32(GrGLSLBlend::BlendKey(fMode));
115     }
116 }
117
118 std::unique_ptr<GrXferProcessor::ProgramImpl> CustomXP::makeProgramImpl() const {
119     SkASSERT(this->willReadDstColor() != this->hasHWBlendEquation());
120
121     class Impl : public ProgramImpl {
122     private:
123         void emitOutputsForBlendState(const EmitArgs& args) override {
124             const CustomXP& xp = args.fXP.cast<CustomXP>();
125             SkASSERT(xp.hasHWBlendEquation());
126
127             GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
128             fragBuilder->enableAdvancedBlendEquationIfNeeded(xp.fHWBlendEquation);
129
130             // Apply coverage by multiplying it into the src color before blending. This will "just
131             // work" automatically. (See analysisProperties())
132             fragBuilder->codeAppendf("%s = %s * %s;",
133                                      args.fOutputPrimary,
134                                      args.fInputCoverage,
135                                      args.fInputColor);
136         }
137
138         void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
139                                      GrGLSLUniformHandler* uniformHandler,
140                                      const char* srcColor,
141                                      const char* srcCoverage,
142                                      const char* dstColor,
143                                      const char* outColor,
144                                      const char* outColorSecondary,
145                                      const GrXferProcessor& proc) override {
146             const CustomXP& xp = proc.cast<CustomXP>();
147             SkASSERT(!xp.hasHWBlendEquation());
148
149             std::string blendExpr = GrGLSLBlend::BlendExpression(
150                     &xp, uniformHandler, &fBlendUniform, srcColor, dstColor, xp.fMode);
151             fragBuilder->codeAppendf("%s = %s;", outColor, blendExpr.c_str());
152
153             // Apply coverage.
154             DefaultCoverageModulation(fragBuilder,
155                                       srcCoverage,
156                                       dstColor,
157                                       outColor,
158                                       outColorSecondary,
159                                       xp);
160         }
161
162         void onSetData(const GrGLSLProgramDataManager& pdman,
163                        const GrXferProcessor& proc) override {
164             if (fBlendUniform.isValid()) {
165                 const CustomXP& xp = proc.cast<CustomXP>();
166                 GrGLSLBlend::SetBlendModeUniformData(pdman, fBlendUniform, xp.fMode);
167             }
168         }
169
170         GrGLSLUniformHandler::UniformHandle fBlendUniform;
171     };
172
173     return std::make_unique<Impl>();
174 }
175
176 bool CustomXP::onIsEqual(const GrXferProcessor& other) const {
177     const CustomXP& s = other.cast<CustomXP>();
178     return fMode == s.fMode && fHWBlendEquation == s.fHWBlendEquation;
179 }
180
181 GrXferBarrierType CustomXP::xferBarrierType(const GrCaps& caps) const {
182     if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport()) {
183         return kBlend_GrXferBarrierType;
184     }
185     return kNone_GrXferBarrierType;
186 }
187
188 void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const {
189     if (this->hasHWBlendEquation()) {
190         blendInfo->fEquation = fHWBlendEquation;
191     }
192 }
193
194 ///////////////////////////////////////////////////////////////////////////////
195
196 // See the comment above GrXPFactory's definition about this warning suppression.
197 #if defined(__GNUC__)
198 #pragma GCC diagnostic push
199 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
200 #endif
201 #if defined(__clang__)
202 #pragma clang diagnostic push
203 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
204 #endif
205 class CustomXPFactory : public GrXPFactory {
206 public:
207     constexpr CustomXPFactory(SkBlendMode mode)
208             : fMode(mode), fHWBlendEquation(hw_blend_equation(mode)) {}
209
210 private:
211     sk_sp<const GrXferProcessor> makeXferProcessor(const GrProcessorAnalysisColor&,
212                                                    GrProcessorAnalysisCoverage,
213                                                    const GrCaps&,
214                                                    GrClampType) const override;
215
216     AnalysisProperties analysisProperties(const GrProcessorAnalysisColor&,
217                                           const GrProcessorAnalysisCoverage&,
218                                           const GrCaps&,
219                                           GrClampType) const override;
220
221     GR_DECLARE_XP_FACTORY_TEST
222
223     SkBlendMode fMode;
224     skgpu::BlendEquation fHWBlendEquation;
225
226     using INHERITED = GrXPFactory;
227 };
228 #if defined(__GNUC__)
229 #pragma GCC diagnostic pop
230 #endif
231 #if defined(__clang__)
232 #pragma clang diagnostic pop
233 #endif
234
235 sk_sp<const GrXferProcessor> CustomXPFactory::makeXferProcessor(
236         const GrProcessorAnalysisColor&,
237         GrProcessorAnalysisCoverage coverage,
238         const GrCaps& caps,
239         GrClampType clampType) const {
240     SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
241     if (can_use_hw_blend_equation(fHWBlendEquation, coverage, caps)) {
242         return sk_sp<GrXferProcessor>(new CustomXP(fMode, fHWBlendEquation));
243     }
244     return sk_sp<GrXferProcessor>(new CustomXP(fMode, coverage));
245 }
246
247 GrXPFactory::AnalysisProperties CustomXPFactory::analysisProperties(
248         const GrProcessorAnalysisColor&, const GrProcessorAnalysisCoverage& coverage,
249         const GrCaps& caps, GrClampType clampType) const {
250     /*
251       The general SVG blend equation is defined in the spec as follows:
252
253         Dca' = B(Sc, Dc) * Sa * Da + Y * Sca * (1-Da) + Z * Dca * (1-Sa)
254         Da'  = X * Sa * Da + Y * Sa * (1-Da) + Z * Da * (1-Sa)
255
256       (Note that Sca, Dca indicate RGB vectors that are premultiplied by alpha,
257        and that B(Sc, Dc) is a mode-specific function that accepts non-multiplied
258        RGB colors.)
259
260       For every blend mode supported by this class, i.e. the "advanced" blend
261       modes, X=Y=Z=1 and this equation reduces to the PDF blend equation.
262
263       It can be shown that when X=Y=Z=1, these equations can modulate alpha for
264       coverage.
265
266
267       == Color ==
268
269       We substitute Y=Z=1 and define a blend() function that calculates Dca' in
270       terms of premultiplied alpha only:
271
272         blend(Sca, Dca, Sa, Da) = {Dca : if Sa == 0,
273                                    Sca : if Da == 0,
274                                    B(Sca/Sa, Dca/Da) * Sa * Da + Sca * (1-Da) + Dca * (1-Sa) : if
275       Sa,Da != 0}
276
277       And for coverage modulation, we use a post blend src-over model:
278
279         Dca'' = f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
280
281       (Where f is the fractional coverage.)
282
283       Next we show that canTweakAlphaForCoverage() is true by proving the
284       following relationship:
285
286         blend(f*Sca, Dca, f*Sa, Da) == f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
287
288       General case (f,Sa,Da != 0):
289
290         f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
291           = f * (B(Sca/Sa, Dca/Da) * Sa * Da + Sca * (1-Da) + Dca * (1-Sa)) + (1-f) * Dca  [Sa,Da !=
292       0, definition of blend()]
293           = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + f*Dca * (1-Sa) + Dca - f*Dca
294           = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca - f*Sca * Da + f*Dca - f*Dca * Sa + Dca - f*Dca
295           = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca - f*Sca * Da - f*Dca * Sa + Dca
296           = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) - f*Dca * Sa + Dca
297           = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + Dca * (1 - f*Sa)
298           = B(f*Sca/f*Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + Dca * (1 - f*Sa)  [f!=0]
299           = blend(f*Sca, Dca, f*Sa, Da)  [definition of blend()]
300
301       Corner cases (Sa=0, Da=0, and f=0):
302
303         Sa=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
304                 = f * Dca + (1-f) * Dca  [Sa=0, definition of blend()]
305                 = Dca
306                 = blend(0, Dca, 0, Da)  [definition of blend()]
307                 = blend(f*Sca, Dca, f*Sa, Da)  [Sa=0]
308
309         Da=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
310                 = f * Sca + (1-f) * Dca  [Da=0, definition of blend()]
311                 = f * Sca  [Da=0]
312                 = blend(f*Sca, 0, f*Sa, 0)  [definition of blend()]
313                 = blend(f*Sca, Dca, f*Sa, Da)  [Da=0]
314
315         f=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca
316                = Dca  [f=0]
317                = blend(0, Dca, 0, Da)  [definition of blend()]
318                = blend(f*Sca, Dca, f*Sa, Da)  [f=0]
319
320       == Alpha ==
321
322       We substitute X=Y=Z=1 and define a blend() function that calculates Da':
323
324         blend(Sa, Da) = Sa * Da + Sa * (1-Da) + Da * (1-Sa)
325                       = Sa * Da + Sa - Sa * Da + Da - Da * Sa
326                       = Sa + Da - Sa * Da
327
328       We use the same model for coverage modulation as we did with color:
329
330         Da'' = f * blend(Sa, Da) + (1-f) * Da
331
332       And show that canTweakAlphaForCoverage() is true by proving the following
333       relationship:
334
335         blend(f*Sa, Da) == f * blend(Sa, Da) + (1-f) * Da
336
337
338         f * blend(Sa, Da) + (1-f) * Da
339           = f * (Sa + Da - Sa * Da) + (1-f) * Da
340           = f*Sa + f*Da - f*Sa * Da + Da - f*Da
341           = f*Sa - f*Sa * Da + Da
342           = f*Sa + Da - f*Sa * Da
343           = blend(f*Sa, Da)
344     */
345     if (can_use_hw_blend_equation(fHWBlendEquation, coverage, caps)) {
346         if (caps.blendEquationSupport() == GrCaps::kAdvancedCoherent_BlendEquationSupport) {
347             return AnalysisProperties::kCompatibleWithCoverageAsAlpha;
348         } else {
349             return AnalysisProperties::kCompatibleWithCoverageAsAlpha |
350                    AnalysisProperties::kRequiresNonOverlappingDraws |
351                    AnalysisProperties::kUsesNonCoherentHWBlending;
352         }
353     }
354     return AnalysisProperties::kCompatibleWithCoverageAsAlpha |
355            AnalysisProperties::kReadsDstInShader;
356 }
357
358 GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory);
359 #if GR_TEST_UTILS
360 const GrXPFactory* CustomXPFactory::TestGet(GrProcessorTestData* d) {
361     int mode = d->fRandom->nextRangeU((int)SkBlendMode::kLastCoeffMode + 1,
362                                       (int)SkBlendMode::kLastSeparableMode);
363
364     return GrCustomXfermode::Get((SkBlendMode)mode);
365 }
366 #endif
367
368 ///////////////////////////////////////////////////////////////////////////////
369
370 const GrXPFactory* GrCustomXfermode::Get(SkBlendMode mode) {
371     static constexpr const CustomXPFactory gOverlay(SkBlendMode::kOverlay);
372     static constexpr const CustomXPFactory gDarken(SkBlendMode::kDarken);
373     static constexpr const CustomXPFactory gLighten(SkBlendMode::kLighten);
374     static constexpr const CustomXPFactory gColorDodge(SkBlendMode::kColorDodge);
375     static constexpr const CustomXPFactory gColorBurn(SkBlendMode::kColorBurn);
376     static constexpr const CustomXPFactory gHardLight(SkBlendMode::kHardLight);
377     static constexpr const CustomXPFactory gSoftLight(SkBlendMode::kSoftLight);
378     static constexpr const CustomXPFactory gDifference(SkBlendMode::kDifference);
379     static constexpr const CustomXPFactory gExclusion(SkBlendMode::kExclusion);
380     static constexpr const CustomXPFactory gMultiply(SkBlendMode::kMultiply);
381     static constexpr const CustomXPFactory gHue(SkBlendMode::kHue);
382     static constexpr const CustomXPFactory gSaturation(SkBlendMode::kSaturation);
383     static constexpr const CustomXPFactory gColor(SkBlendMode::kColor);
384     static constexpr const CustomXPFactory gLuminosity(SkBlendMode::kLuminosity);
385     switch (mode) {
386         case SkBlendMode::kOverlay:
387             return &gOverlay;
388         case SkBlendMode::kDarken:
389             return &gDarken;
390         case SkBlendMode::kLighten:
391             return &gLighten;
392         case SkBlendMode::kColorDodge:
393             return &gColorDodge;
394         case SkBlendMode::kColorBurn:
395             return &gColorBurn;
396         case SkBlendMode::kHardLight:
397             return &gHardLight;
398         case SkBlendMode::kSoftLight:
399             return &gSoftLight;
400         case SkBlendMode::kDifference:
401             return &gDifference;
402         case SkBlendMode::kExclusion:
403             return &gExclusion;
404         case SkBlendMode::kMultiply:
405             return &gMultiply;
406         case SkBlendMode::kHue:
407             return &gHue;
408         case SkBlendMode::kSaturation:
409             return &gSaturation;
410         case SkBlendMode::kColor:
411             return &gColor;
412         case SkBlendMode::kLuminosity:
413             return &gLuminosity;
414         default:
415             SkASSERT(!GrCustomXfermode::IsSupportedMode(mode));
416             return nullptr;
417     }
418 }