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