Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / ganesh / effects / GrSkSLFP.cpp
1 /*
2  * Copyright 2018 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/GrSkSLFP.h"
9
10 #include "include/effects/SkRuntimeEffect.h"
11 #include "include/private/SkSLString.h"
12 #include "include/private/gpu/ganesh/GrContext_Base.h"
13 #include "src/core/SkColorSpacePriv.h"
14 #include "src/core/SkRuntimeEffectPriv.h"
15 #include "src/core/SkVM.h"
16 #include "src/gpu/KeyBuilder.h"
17 #include "src/gpu/ganesh/GrBaseContextPriv.h"
18 #include "src/gpu/ganesh/GrColorInfo.h"
19 #include "src/gpu/ganesh/GrTexture.h"
20 #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
21 #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
22 #include "src/sksl/SkSLUtil.h"
23 #include "src/sksl/codegen/SkSLPipelineStageCodeGenerator.h"
24 #include "src/sksl/ir/SkSLVarDeclarations.h"
25
26 class GrSkSLFP::Impl : public ProgramImpl {
27 public:
28     void emitCode(EmitArgs& args) override {
29         const GrSkSLFP& fp            = args.fFp.cast<GrSkSLFP>();
30         const SkSL::Program& program  = *fp.fEffect->fBaseProgram;
31
32         class FPCallbacks : public SkSL::PipelineStage::Callbacks {
33         public:
34             FPCallbacks(Impl* self,
35                         EmitArgs& args,
36                         const char* inputColor,
37                         const SkSL::Context& context,
38                         const uint8_t* uniformData,
39                         const GrSkSLFP::UniformFlags* uniformFlags)
40                     : fSelf(self)
41                     , fArgs(args)
42                     , fInputColor(inputColor)
43                     , fContext(context)
44                     , fUniformData(uniformData)
45                     , fUniformFlags(uniformFlags) {}
46
47             std::string declareUniform(const SkSL::VarDeclaration* decl) override {
48                 const SkSL::Variable& var = decl->var();
49                 if (var.type().isOpaque()) {
50                     // Nothing to do. The only opaque types we should see are children, and those
51                     // are handled specially, above.
52                     SkASSERT(var.type().isEffectChild());
53                     return std::string(var.name());
54                 }
55
56                 const SkSL::Type* type = &var.type();
57                 size_t sizeInBytes = type->slotCount() * sizeof(float);
58                 const float* floatData = reinterpret_cast<const float*>(fUniformData);
59                 const int* intData = reinterpret_cast<const int*>(fUniformData);
60                 fUniformData += sizeInBytes;
61
62                 bool isArray = false;
63                 if (type->isArray()) {
64                     type = &type->componentType();
65                     isArray = true;
66                 }
67
68                 SkSLType gpuType;
69                 SkAssertResult(SkSL::type_to_sksltype(fContext, *type, &gpuType));
70
71                 if (*fUniformFlags++ & GrSkSLFP::kSpecialize_Flag) {
72                     SkASSERTF(!isArray, "specializing array uniforms is not allowed");
73                     std::string value = GrGLSLTypeString(gpuType);
74                     value.append("(");
75
76                     bool isFloat = SkSLTypeIsFloatType(gpuType);
77                     size_t slots = type->slotCount();
78                     for (size_t i = 0; i < slots; ++i) {
79                         value.append(isFloat ? skstd::to_string(floatData[i])
80                                              : std::to_string(intData[i]));
81                         value.append(",");
82                     }
83                     value.back() = ')';
84                     return value;
85                 }
86
87                 const char* uniformName = nullptr;
88                 auto handle =
89                         fArgs.fUniformHandler->addUniformArray(&fArgs.fFp.cast<GrSkSLFP>(),
90                                                                kFragment_GrShaderFlag,
91                                                                gpuType,
92                                                                SkString(var.name()).c_str(),
93                                                                isArray ? var.type().columns() : 0,
94                                                                &uniformName);
95                 fSelf->fUniformHandles.push_back(handle);
96                 return std::string(uniformName);
97             }
98
99             std::string getMangledName(const char* name) override {
100                 return std::string(fArgs.fFragBuilder->getMangledFunctionName(name).c_str());
101             }
102
103             void defineFunction(const char* decl, const char* body, bool isMain) override {
104                 if (isMain) {
105                     fArgs.fFragBuilder->codeAppend(body);
106                 } else {
107                     fArgs.fFragBuilder->emitFunction(decl, body);
108                 }
109             }
110
111             void declareFunction(const char* decl) override {
112                 fArgs.fFragBuilder->emitFunctionPrototype(decl);
113             }
114
115             void defineStruct(const char* definition) override {
116                 fArgs.fFragBuilder->definitionAppend(definition);
117             }
118
119             void declareGlobal(const char* declaration) override {
120                 fArgs.fFragBuilder->definitionAppend(declaration);
121             }
122
123             std::string sampleShader(int index, std::string coords) override {
124                 // If the child was sampled using the coords passed to main (and they are never
125                 // modified), then we will have marked the child as PassThrough. The code generator
126                 // doesn't know that, and still supplies coords. Inside invokeChild, we assert that
127                 // any coords passed for a PassThrough child match args.fSampleCoords exactly.
128                 //
129                 // Normally, this is valid. Here, we *copied* the sample coords to a local variable
130                 // (so that they're mutable in the runtime effect SkSL). Thus, the coords string we
131                 // get here is the name of the local copy, and fSampleCoords still points to the
132                 // unmodified original (which might be a varying, for example).
133                 // To prevent the assert, we pass the empty string in this case. Note that for
134                 // children sampled like this, invokeChild doesn't even use the coords parameter,
135                 // except for that assert.
136                 const GrFragmentProcessor* child = fArgs.fFp.childProcessor(index);
137                 if (child && child->sampleUsage().isPassThrough()) {
138                     coords.clear();
139                 }
140                 return std::string(fSelf->invokeChild(index, fInputColor, fArgs, coords).c_str());
141             }
142
143             std::string sampleColorFilter(int index, std::string color) override {
144                 return std::string(fSelf->invokeChild(index,
145                                                  color.empty() ? fInputColor : color.c_str(),
146                                                  fArgs)
147                                       .c_str());
148             }
149
150             std::string sampleBlender(int index, std::string src, std::string dst) override {
151                 if (!fSelf->childProcessor(index)) {
152                     return SkSL::String::printf("blend_src_over(%s, %s)", src.c_str(), dst.c_str());
153                 }
154                 return std::string(
155                         fSelf->invokeChild(index, src.c_str(), dst.c_str(), fArgs).c_str());
156             }
157
158             // These intrinsics take and return 3-component vectors, but child FPs operate on
159             // 4-component vectors. We use swizzles here to paper over the difference.
160             std::string toLinearSrgb(std::string color) override {
161                 const GrSkSLFP& fp = fArgs.fFp.cast<GrSkSLFP>();
162                 if (fp.fToLinearSrgbChildIndex < 0) {
163                     return color;
164                 }
165                 color = SkSL::String::printf("(%s).rgb1", color.c_str());
166                 SkString xformedColor = fSelf->invokeChild(
167                         fp.fToLinearSrgbChildIndex, color.c_str(), fArgs);
168                 return SkSL::String::printf("(%s).rgb", xformedColor.c_str());
169             }
170
171             std::string fromLinearSrgb(std::string color) override {
172                 const GrSkSLFP& fp = fArgs.fFp.cast<GrSkSLFP>();
173                 if (fp.fFromLinearSrgbChildIndex < 0) {
174                     return color;
175                 }
176                 color = SkSL::String::printf("(%s).rgb1", color.c_str());
177                 SkString xformedColor = fSelf->invokeChild(
178                         fp.fFromLinearSrgbChildIndex, color.c_str(), fArgs);
179                 return SkSL::String::printf("(%s).rgb", xformedColor.c_str());
180             }
181
182             Impl*                         fSelf;
183             EmitArgs&                     fArgs;
184             const char*                   fInputColor;
185             const SkSL::Context&          fContext;
186             const uint8_t*                fUniformData;
187             const GrSkSLFP::UniformFlags* fUniformFlags;
188             int                           fUniformIndex = 0;
189         };
190
191         // If we have an input child, we invoke it now, and make the result of that be the "input
192         // color" for all other purposes later (eg, the default passed via sample calls, etc.)
193         if (fp.fInputChildIndex >= 0) {
194             args.fFragBuilder->codeAppendf("%s = %s;\n",
195                                            args.fInputColor,
196                                            this->invokeChild(fp.fInputChildIndex, args).c_str());
197         }
198
199         if (fp.fEffect->allowBlender()) {
200             // If we have an dest-color child, we invoke it now, and make the result of that be the
201             // "dest color" for all other purposes later.
202             if (fp.fDestColorChildIndex >= 0) {
203                 args.fFragBuilder->codeAppendf(
204                         "%s = %s;\n",
205                         args.fDestColor,
206                         this->invokeChild(fp.fDestColorChildIndex, args.fDestColor, args).c_str());
207             }
208         } else {
209             // We're not making a blender, so we don't expect a dest-color child FP to exist.
210             SkASSERT(fp.fDestColorChildIndex < 0);
211         }
212
213         // Snap off a global copy of the input color at the start of main. We need this when
214         // we call child processors (particularly from helper functions, which can't "see" the
215         // parameter to main). Even from within main, if the code mutates the parameter, calls to
216         // sample should still be passing the original color (by default).
217         SkString inputColorName;
218         if (fp.fEffect->samplesOutsideMain()) {
219             GrShaderVar inputColorCopy(args.fFragBuilder->getMangledFunctionName("inColor"),
220                                        SkSLType::kHalf4);
221             args.fFragBuilder->declareGlobal(inputColorCopy);
222             inputColorName = inputColorCopy.getName();
223             args.fFragBuilder->codeAppendf("%s = %s;\n", inputColorName.c_str(), args.fInputColor);
224         } else {
225             inputColorName = args.fFragBuilder->newTmpVarName("inColor");
226             args.fFragBuilder->codeAppendf(
227                     "half4 %s = %s;\n", inputColorName.c_str(), args.fInputColor);
228         }
229
230         // Copy the incoming coords to a local variable. Code in main might modify the coords
231         // parameter. fSampleCoord could be a varying, so writes to it would be illegal.
232         const char* coords = "float2(0)";
233         SkString coordsVarName;
234         if (fp.usesSampleCoordsDirectly()) {
235             coordsVarName = args.fFragBuilder->newTmpVarName("coords");
236             coords = coordsVarName.c_str();
237             args.fFragBuilder->codeAppendf("float2 %s = %s;\n", coords, args.fSampleCoord);
238         }
239
240         FPCallbacks callbacks(this,
241                               args,
242                               inputColorName.c_str(),
243                               *program.fContext,
244                               fp.uniformData(),
245                               fp.uniformFlags());
246         SkSL::PipelineStage::ConvertProgram(
247                 program, coords, args.fInputColor, args.fDestColor, &callbacks);
248     }
249
250 private:
251     void onSetData(const GrGLSLProgramDataManager& pdman,
252                    const GrFragmentProcessor& _proc) override {
253         using Type = SkRuntimeEffect::Uniform::Type;
254         size_t uniIndex = 0;
255         const GrSkSLFP& outer = _proc.cast<GrSkSLFP>();
256         const uint8_t* uniformData = outer.uniformData();
257         const GrSkSLFP::UniformFlags* uniformFlags = outer.uniformFlags();
258         for (const auto& v : outer.fEffect->uniforms()) {
259             if (*uniformFlags++ & GrSkSLFP::kSpecialize_Flag) {
260                 continue;
261             }
262             const UniformHandle handle = fUniformHandles[uniIndex++];
263             auto floatData = [=] { return SkTAddOffset<const float>(uniformData, v.offset); };
264             auto intData = [=] { return SkTAddOffset<const int>(uniformData, v.offset); };
265             switch (v.type) {
266                 case Type::kFloat:  pdman.set1fv(handle, v.count, floatData()); break;
267                 case Type::kFloat2: pdman.set2fv(handle, v.count, floatData()); break;
268                 case Type::kFloat3: pdman.set3fv(handle, v.count, floatData()); break;
269                 case Type::kFloat4: pdman.set4fv(handle, v.count, floatData()); break;
270
271                 case Type::kFloat2x2: pdman.setMatrix2fv(handle, v.count, floatData()); break;
272                 case Type::kFloat3x3: pdman.setMatrix3fv(handle, v.count, floatData()); break;
273                 case Type::kFloat4x4: pdman.setMatrix4fv(handle, v.count, floatData()); break;
274
275                 case Type::kInt:  pdman.set1iv(handle, v.count, intData()); break;
276                 case Type::kInt2: pdman.set2iv(handle, v.count, intData()); break;
277                 case Type::kInt3: pdman.set3iv(handle, v.count, intData()); break;
278                 case Type::kInt4: pdman.set4iv(handle, v.count, intData()); break;
279
280                 default:
281                     SkDEBUGFAIL("Unsupported uniform type");
282                     break;
283             }
284         }
285     }
286
287     std::vector<UniformHandle> fUniformHandles;
288 };
289
290 std::unique_ptr<GrSkSLFP> GrSkSLFP::MakeWithData(
291         sk_sp<SkRuntimeEffect> effect,
292         const char* name,
293         sk_sp<SkColorSpace> dstColorSpace,
294         std::unique_ptr<GrFragmentProcessor> inputFP,
295         std::unique_ptr<GrFragmentProcessor> destColorFP,
296         sk_sp<SkData> uniforms,
297         SkSpan<std::unique_ptr<GrFragmentProcessor>> childFPs) {
298     if (uniforms->size() != effect->uniformSize()) {
299         return nullptr;
300     }
301     size_t uniformSize = uniforms->size();
302     size_t uniformFlagSize = effect->uniforms().size() * sizeof(UniformFlags);
303     std::unique_ptr<GrSkSLFP> fp(new (uniformSize + uniformFlagSize)
304                                          GrSkSLFP(std::move(effect), name, OptFlags::kNone));
305     sk_careful_memcpy(fp->uniformData(), uniforms->data(), uniformSize);
306     for (auto& childFP : childFPs) {
307         fp->addChild(std::move(childFP), /*mergeOptFlags=*/true);
308     }
309     if (inputFP) {
310         fp->setInput(std::move(inputFP));
311     }
312     if (destColorFP) {
313         fp->setDestColorFP(std::move(destColorFP));
314     }
315     if (fp->fEffect->usesColorTransform() && dstColorSpace) {
316         fp->addColorTransformChildren(std::move(dstColorSpace));
317     }
318     return fp;
319 }
320
321 GrSkSLFP::GrSkSLFP(sk_sp<SkRuntimeEffect> effect, const char* name, OptFlags optFlags)
322         : INHERITED(kGrSkSLFP_ClassID,
323                     static_cast<OptimizationFlags>(optFlags) |
324                             (effect->getFilterColorProgram()
325                                      ? kConstantOutputForConstantInput_OptimizationFlag
326                                      : kNone_OptimizationFlags))
327         , fEffect(std::move(effect))
328         , fName(name)
329         , fUniformSize(SkToU32(fEffect->uniformSize())) {
330     memset(this->uniformFlags(), 0, fEffect->uniforms().size() * sizeof(UniformFlags));
331     if (fEffect->usesSampleCoords()) {
332         this->setUsesSampleCoordsDirectly();
333     }
334     if (fEffect->allowBlender()) {
335         this->setIsBlendFunction();
336     }
337 }
338
339 GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
340         : INHERITED(other)
341         , fEffect(other.fEffect)
342         , fName(other.fName)
343         , fUniformSize(other.fUniformSize)
344         , fInputChildIndex(other.fInputChildIndex)
345         , fDestColorChildIndex(other.fDestColorChildIndex)
346         , fToLinearSrgbChildIndex(other.fToLinearSrgbChildIndex)
347         , fFromLinearSrgbChildIndex(other.fFromLinearSrgbChildIndex) {
348     sk_careful_memcpy(this->uniformFlags(),
349                       other.uniformFlags(),
350                       fEffect->uniforms().size() * sizeof(UniformFlags));
351     sk_careful_memcpy(this->uniformData(), other.uniformData(), fUniformSize);
352 }
353
354 void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child, bool mergeOptFlags) {
355     SkASSERTF(fInputChildIndex == -1, "all addChild calls must happen before setInput");
356     SkASSERTF(fDestColorChildIndex == -1, "all addChild calls must happen before setDestColorFP");
357     int childIndex = this->numChildProcessors();
358     SkASSERT((size_t)childIndex < fEffect->fSampleUsages.size());
359     if (mergeOptFlags) {
360         this->mergeOptimizationFlags(ProcessorOptimizationFlags(child.get()));
361     }
362     this->registerChild(std::move(child), fEffect->fSampleUsages[childIndex]);
363 }
364
365 void GrSkSLFP::setInput(std::unique_ptr<GrFragmentProcessor> input) {
366     SkASSERTF(fInputChildIndex == -1, "setInput should not be called more than once");
367     fInputChildIndex = this->numChildProcessors();
368     SkASSERT((size_t)fInputChildIndex >= fEffect->fSampleUsages.size());
369     this->mergeOptimizationFlags(ProcessorOptimizationFlags(input.get()));
370     this->registerChild(std::move(input), SkSL::SampleUsage::PassThrough());
371 }
372
373 void GrSkSLFP::setDestColorFP(std::unique_ptr<GrFragmentProcessor> destColorFP) {
374     SkASSERTF(fEffect->allowBlender(), "dest colors are only used by blend effects");
375     SkASSERTF(fDestColorChildIndex == -1, "setDestColorFP should not be called more than once");
376     fDestColorChildIndex = this->numChildProcessors();
377     SkASSERT((size_t)fDestColorChildIndex >= fEffect->fSampleUsages.size());
378     this->mergeOptimizationFlags(ProcessorOptimizationFlags(destColorFP.get()));
379     this->registerChild(std::move(destColorFP), SkSL::SampleUsage::PassThrough());
380 }
381
382 void GrSkSLFP::addColorTransformChildren(sk_sp<SkColorSpace> dstColorSpace) {
383     SkASSERTF(fToLinearSrgbChildIndex == -1 && fFromLinearSrgbChildIndex == -1,
384               "addColorTransformChildren should not be called more than once");
385
386     // We use child FPs for the color transforms. They're really just code snippets that get
387     // invoked, but each one injects a collection of uniforms and helper functions. Doing it
388     // this way leverages per-FP name mangling to avoid conflicts.
389     auto workingToLinear = GrColorSpaceXformEffect::Make(nullptr,
390                                                          dstColorSpace.get(),
391                                                          kUnpremul_SkAlphaType,
392                                                          sk_srgb_linear_singleton(),
393                                                          kUnpremul_SkAlphaType);
394     auto linearToWorking = GrColorSpaceXformEffect::Make(nullptr,
395                                                          sk_srgb_linear_singleton(),
396                                                          kUnpremul_SkAlphaType,
397                                                          dstColorSpace.get(),
398                                                          kUnpremul_SkAlphaType);
399
400     fToLinearSrgbChildIndex = this->numChildProcessors();
401     SkASSERT((size_t)fToLinearSrgbChildIndex >= fEffect->fSampleUsages.size());
402     this->registerChild(std::move(workingToLinear), SkSL::SampleUsage::PassThrough());
403
404     fFromLinearSrgbChildIndex = this->numChildProcessors();
405     SkASSERT((size_t)fFromLinearSrgbChildIndex >= fEffect->fSampleUsages.size());
406     this->registerChild(std::move(linearToWorking), SkSL::SampleUsage::PassThrough());
407 }
408
409 std::unique_ptr<GrFragmentProcessor::ProgramImpl> GrSkSLFP::onMakeProgramImpl() const {
410     return std::make_unique<Impl>();
411 }
412
413 void GrSkSLFP::onAddToKey(const GrShaderCaps& caps, skgpu::KeyBuilder* b) const {
414     // In the unlikely event of a hash collision, we also include the uniform size in the key.
415     // That ensures that we will (at worst) use the wrong program, but one that expects the same
416     // amount of uniform data.
417     b->add32(fEffect->hash());
418     b->add32(fUniformSize);
419
420     const UniformFlags* flags = this->uniformFlags();
421     const uint8_t* uniformData = this->uniformData();
422     size_t uniformCount = fEffect->uniforms().size();
423     auto iter = fEffect->uniforms().begin();
424
425     for (size_t i = 0; i < uniformCount; ++i, ++iter) {
426         bool specialize = flags[i] & kSpecialize_Flag;
427         b->addBool(specialize, "specialize");
428         if (specialize) {
429             b->addBytes(iter->sizeInBytes(), uniformData + iter->offset, iter->name.c_str());
430         }
431     }
432 }
433
434 bool GrSkSLFP::onIsEqual(const GrFragmentProcessor& other) const {
435     const GrSkSLFP& sk = other.cast<GrSkSLFP>();
436     const size_t uniformFlagSize = fEffect->uniforms().size() * sizeof(UniformFlags);
437     return fEffect->hash() == sk.fEffect->hash() &&
438            fEffect->uniforms().size() == sk.fEffect->uniforms().size() &&
439            fUniformSize == sk.fUniformSize &&
440            !sk_careful_memcmp(
441                    this->uniformData(), sk.uniformData(), fUniformSize + uniformFlagSize);
442 }
443
444 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
445     return std::unique_ptr<GrFragmentProcessor>(new (UniformPayloadSize(fEffect.get()))
446                                                         GrSkSLFP(*this));
447 }
448
449 SkPMColor4f GrSkSLFP::constantOutputForConstantInput(const SkPMColor4f& inputColor) const {
450     const SkFilterColorProgram* program = fEffect->getFilterColorProgram();
451     SkASSERT(program);
452
453     auto evalChild = [&](int index, SkPMColor4f color) {
454         return ConstantOutputForConstantInput(this->childProcessor(index), color);
455     };
456
457     SkPMColor4f color = (fInputChildIndex >= 0)
458                                 ? ConstantOutputForConstantInput(
459                                           this->childProcessor(fInputChildIndex), inputColor)
460                                 : inputColor;
461     return program->eval(color, this->uniformData(), evalChild);
462 }
463
464 /**************************************************************************************************/
465
466 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSkSLFP);
467
468 #if GR_TEST_UTILS
469
470 #include "include/effects/SkOverdrawColorFilter.h"
471 #include "src/core/SkColorFilterBase.h"
472
473 extern const char* SKSL_OVERDRAW_SRC;
474
475 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::TestCreate(GrProcessorTestData* d) {
476     SkColor colors[SkOverdrawColorFilter::kNumColors];
477     for (SkColor& c : colors) {
478         c = d->fRandom->nextU();
479     }
480     auto filter = SkOverdrawColorFilter::MakeWithSkColors(colors);
481     auto [success, fp] = as_CFB(filter)->asFragmentProcessor(/*inputFP=*/nullptr, d->context(),
482                                                              GrColorInfo{});
483     SkASSERT(success);
484     return std::move(fp);
485 }
486
487 #endif