Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / ganesh / GrXferProcessor.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/GrXferProcessor.h"
9
10 #include "src/gpu/KeyBuilder.h"
11 #include "src/gpu/ganesh/GrCaps.h"
12 #include "src/gpu/ganesh/GrPipeline.h"
13 #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
14 #include "src/gpu/ganesh/glsl/GrGLSLProgramDataManager.h"
15
16 GrXferProcessor::GrXferProcessor(ClassID classID)
17         : INHERITED(classID)
18         , fWillReadDstColor(false)
19         , fIsLCD(false) {}
20
21 GrXferProcessor::GrXferProcessor(ClassID classID, bool willReadDstColor,
22                                  GrProcessorAnalysisCoverage coverage)
23         : INHERITED(classID)
24         , fWillReadDstColor(willReadDstColor)
25         , fIsLCD(GrProcessorAnalysisCoverage::kLCD == coverage) {}
26
27 bool GrXferProcessor::hasSecondaryOutput() const {
28     if (!this->willReadDstColor()) {
29         return this->onHasSecondaryOutput();
30     }
31     return false;
32 }
33
34 void GrXferProcessor::addToKey(const GrShaderCaps& caps,
35                                skgpu::KeyBuilder* b,
36                                const GrSurfaceOrigin* originIfDstTexture,
37                                bool usesInputAttachmentForDstRead) const {
38     uint32_t key = this->willReadDstColor() ? 0x1 : 0x0;
39     if (key) {
40         if (originIfDstTexture) {
41             key |= 0x2;
42             if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) {
43                 key |= 0x4;
44             }
45             if (usesInputAttachmentForDstRead) {
46                 key |= 0x8;
47             }
48         }
49     }
50     if (fIsLCD) {
51         key |= 0x10;
52     }
53     b->add32(key);
54     this->onAddToKey(caps, b);
55 }
56
57 #ifdef SK_DEBUG
58 static const char* equation_string(skgpu::BlendEquation eq) {
59     switch (eq) {
60         case skgpu::BlendEquation::kAdd:
61             return "add";
62         case skgpu::BlendEquation::kSubtract:
63             return "subtract";
64         case skgpu::BlendEquation::kReverseSubtract:
65             return "reverse_subtract";
66         case skgpu::BlendEquation::kScreen:
67             return "screen";
68         case skgpu::BlendEquation::kOverlay:
69             return "overlay";
70         case skgpu::BlendEquation::kDarken:
71             return "darken";
72         case skgpu::BlendEquation::kLighten:
73             return "lighten";
74         case skgpu::BlendEquation::kColorDodge:
75             return "color_dodge";
76         case skgpu::BlendEquation::kColorBurn:
77             return "color_burn";
78         case skgpu::BlendEquation::kHardLight:
79             return "hard_light";
80         case skgpu::BlendEquation::kSoftLight:
81             return "soft_light";
82         case skgpu::BlendEquation::kDifference:
83             return "difference";
84         case skgpu::BlendEquation::kExclusion:
85             return "exclusion";
86         case skgpu::BlendEquation::kMultiply:
87             return "multiply";
88         case skgpu::BlendEquation::kHSLHue:
89             return "hsl_hue";
90         case skgpu::BlendEquation::kHSLSaturation:
91             return "hsl_saturation";
92         case skgpu::BlendEquation::kHSLColor:
93             return "hsl_color";
94         case skgpu::BlendEquation::kHSLLuminosity:
95             return "hsl_luminosity";
96         case skgpu::BlendEquation::kIllegal:
97             SkASSERT(false);
98             return "<illegal>";
99     }
100     return "";
101 }
102
103 static const char* coeff_string(skgpu::BlendCoeff coeff) {
104     switch (coeff) {
105         case skgpu::BlendCoeff::kZero:
106             return "zero";
107         case skgpu::BlendCoeff::kOne:
108             return "one";
109         case skgpu::BlendCoeff::kSC:
110             return "src_color";
111         case skgpu::BlendCoeff::kISC:
112             return "inv_src_color";
113         case skgpu::BlendCoeff::kDC:
114             return "dst_color";
115         case skgpu::BlendCoeff::kIDC:
116             return "inv_dst_color";
117         case skgpu::BlendCoeff::kSA:
118             return "src_alpha";
119         case skgpu::BlendCoeff::kISA:
120             return "inv_src_alpha";
121         case skgpu::BlendCoeff::kDA:
122             return "dst_alpha";
123         case skgpu::BlendCoeff::kIDA:
124             return "inv_dst_alpha";
125         case skgpu::BlendCoeff::kConstC:
126             return "const_color";
127         case skgpu::BlendCoeff::kIConstC:
128             return "inv_const_color";
129         case skgpu::BlendCoeff::kS2C:
130             return "src2_color";
131         case skgpu::BlendCoeff::kIS2C:
132             return "inv_src2_color";
133         case skgpu::BlendCoeff::kS2A:
134             return "src2_alpha";
135         case skgpu::BlendCoeff::kIS2A:
136             return "inv_src2_alpha";
137         case skgpu::BlendCoeff::kIllegal:
138             SkASSERT(false);
139             return "<illegal>";
140     }
141     return "";
142 }
143
144 SkString GrXferProcessor::BlendInfo::dump() const {
145     SkString out;
146     out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)",
147                fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend),
148                coeff_string(fDstBlend), fBlendConstant.toBytes_RGBA());
149     return out;
150 }
151 #endif
152
153 ///////////////////////////////////////////////////////////////////////////////
154
155 GrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties(
156         const GrXPFactory* factory,
157         const GrProcessorAnalysisColor& color,
158         const GrProcessorAnalysisCoverage& coverage,
159         const GrCaps& caps,
160         GrClampType clampType) {
161     AnalysisProperties result;
162     if (factory) {
163         result = factory->analysisProperties(color, coverage, caps, clampType);
164     } else {
165         result = GrPorterDuffXPFactory::SrcOverAnalysisProperties(color, coverage, caps, clampType);
166     }
167     if (coverage == GrProcessorAnalysisCoverage::kNone) {
168         result |= AnalysisProperties::kCompatibleWithCoverageAsAlpha;
169     }
170     SkASSERT(!(result & AnalysisProperties::kRequiresDstTexture));
171     if ((result & AnalysisProperties::kReadsDstInShader) &&
172         !caps.shaderCaps()->dstReadInShaderSupport()) {
173         result |= AnalysisProperties::kRequiresDstTexture |
174                   AnalysisProperties::kRequiresNonOverlappingDraws;
175     }
176     return result;
177 }
178
179 sk_sp<const GrXferProcessor> GrXPFactory::MakeXferProcessor(const GrXPFactory* factory,
180                                                             const GrProcessorAnalysisColor& color,
181                                                             GrProcessorAnalysisCoverage coverage,
182                                                             const GrCaps& caps,
183                                                             GrClampType clampType) {
184     if (factory) {
185         return factory->makeXferProcessor(color, coverage, caps, clampType);
186     } else {
187         return GrPorterDuffXPFactory::MakeSrcOverXferProcessor(color, coverage, caps);
188     }
189 }
190
191 //////////////////////////////////////////////////////////////////////////////
192
193 using ProgramImpl = GrXferProcessor::ProgramImpl;
194
195 // This is only called for cases where we are doing LCD coverage and not using in shader blending.
196 // For these cases we assume the the src alpha is 1, thus we can just use the max for the alpha
197 // coverage since src alpha will always be greater than or equal to dst alpha.
198 static void adjust_for_lcd_coverage(GrGLSLXPFragmentBuilder* fragBuilder,
199                                     const char* srcCoverage,
200                                     const GrXferProcessor& proc) {
201     if (srcCoverage && proc.isLCD()) {
202         fragBuilder->codeAppendf("%s.a = max(max(%s.r, %s.g), %s.b);",
203                                  srcCoverage,
204                                  srcCoverage,
205                                  srcCoverage,
206                                  srcCoverage);
207     }
208 }
209
210 void ProgramImpl::emitCode(const EmitArgs& args) {
211     if (!args.fXP.willReadDstColor()) {
212         adjust_for_lcd_coverage(args.fXPFragBuilder, args.fInputCoverage, args.fXP);
213         this->emitOutputsForBlendState(args);
214     } else {
215         GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder;
216         GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
217         const char* dstColor = fragBuilder->dstColor();
218
219         bool needsLocalOutColor = false;
220
221         if (args.fDstTextureSamplerHandle.isValid()) {
222             if (args.fInputCoverage) {
223                 // We don't think any shaders actually output negative coverage, but just as a
224                 // safety check for floating point precision errors, we compare with <= here. We
225                 // just check the RGB values of the coverage, since the alpha may not have been set
226                 // when using LCD. If we are using single-channel coverage, alpha will be equal to
227                 // RGB anyway.
228                 //
229                 // The discard here also helps for batching text-draws together, which need to read
230                 // from a dst copy for blends. However, this only helps the case where the outer
231                 // bounding boxes of each letter overlap and not two actually parts of the text.
232                 fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, half3(0)))) {"
233                                          "    discard;"
234                                          "}",
235                                          args.fInputCoverage);
236             }
237         } else {
238             needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch();
239         }
240
241         const char* outColor = "_localColorOut";
242         if (!needsLocalOutColor) {
243             outColor = args.fOutputPrimary;
244         } else {
245             fragBuilder->codeAppendf("half4 %s;", outColor);
246         }
247
248         this->emitBlendCodeForDstRead(fragBuilder,
249                                       uniformHandler,
250                                       args.fInputColor,
251                                       args.fInputCoverage,
252                                       dstColor,
253                                       outColor,
254                                       args.fOutputSecondary,
255                                       args.fXP);
256         if (needsLocalOutColor) {
257             fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, outColor);
258         }
259     }
260
261     // Swizzle the fragment shader outputs if necessary.
262     this->emitWriteSwizzle(args.fXPFragBuilder,
263                            args.fWriteSwizzle,
264                            args.fOutputPrimary,
265                            args.fOutputSecondary);
266 }
267
268 void ProgramImpl::emitWriteSwizzle(GrGLSLXPFragmentBuilder* x,
269                                    const skgpu::Swizzle& swizzle,
270                                    const char* outColor,
271                                    const char* outColorSecondary) const {
272     if (skgpu::Swizzle::RGBA() != swizzle) {
273         x->codeAppendf("%s = %s.%s;", outColor, outColor, swizzle.asString().c_str());
274         if (outColorSecondary) {
275             x->codeAppendf("%s = %s.%s;",
276                            outColorSecondary,
277                            outColorSecondary,
278                            swizzle.asString().c_str());
279         }
280     }
281 }
282
283 void ProgramImpl::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) {
284     this->onSetData(pdm, xp);
285 }
286
287 void ProgramImpl::DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fragBuilder,
288                                             const char* srcCoverage,
289                                             const char* dstColor,
290                                             const char* outColor,
291                                             const char* outColorSecondary,
292                                             const GrXferProcessor& proc) {
293     if (srcCoverage) {
294         if (proc.isLCD()) {
295             fragBuilder->codeAppendf("half3 lerpRGB = mix(%s.aaa, %s.aaa, %s.rgb);",
296                                      dstColor,
297                                      outColor,
298                                      srcCoverage);
299         }
300         fragBuilder->codeAppendf("%s = %s * %s + (half4(1.0) - %s) * %s;",
301                                  outColor,
302                                  srcCoverage,
303                                  outColor,
304                                  srcCoverage,
305                                  dstColor);
306         if (proc.isLCD()) {
307             fragBuilder->codeAppendf("%s.a = max(max(lerpRGB.r, lerpRGB.b), lerpRGB.g);", outColor);
308         }
309     }
310 }