Coverage Report

Created: 2024-09-14 07:19

/src/skia/include/effects/SkRuntimeEffect.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2019 Google LLC
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
#ifndef SkRuntimeEffect_DEFINED
9
#define SkRuntimeEffect_DEFINED
10
11
#include "include/core/SkBlender.h"  // IWYU pragma: keep
12
#include "include/core/SkColorFilter.h"  // IWYU pragma: keep
13
#include "include/core/SkData.h"
14
#include "include/core/SkFlattenable.h"
15
#include "include/core/SkMatrix.h"
16
#include "include/core/SkRefCnt.h"
17
#include "include/core/SkShader.h"
18
#include "include/core/SkSpan.h"
19
#include "include/core/SkString.h"
20
#include "include/core/SkTypes.h"
21
#include "include/private/SkSLSampleUsage.h"
22
#include "include/private/base/SkOnce.h"
23
#include "include/private/base/SkTemplates.h"
24
#include "include/private/base/SkTo.h"
25
#include "include/private/base/SkTypeTraits.h"
26
#include "include/sksl/SkSLDebugTrace.h"
27
#include "include/sksl/SkSLVersion.h"
28
29
#include <cstddef>
30
#include <cstdint>
31
#include <cstring>
32
#include <memory>
33
#include <optional>
34
#include <string>
35
#include <string_view>
36
#include <utility>
37
#include <vector>
38
39
struct SkIPoint;
40
41
namespace SkSL {
42
class DebugTracePriv;
43
class FunctionDefinition;
44
struct Program;
45
enum class ProgramKind : int8_t;
46
struct ProgramSettings;
47
}  // namespace SkSL
48
49
namespace SkSL::RP {
50
class Program;
51
}
52
53
/*
54
 * SkRuntimeEffect supports creating custom SkShader and SkColorFilter objects using Skia's SkSL
55
 * shading language.
56
 *
57
 * NOTE: This API is experimental and subject to change.
58
 */
59
class SK_API SkRuntimeEffect : public SkRefCnt {
60
public:
61
    // Reflected description of a uniform variable in the effect's SkSL
62
    struct SK_API Uniform {
63
        enum class Type {
64
            kFloat,
65
            kFloat2,
66
            kFloat3,
67
            kFloat4,
68
            kFloat2x2,
69
            kFloat3x3,
70
            kFloat4x4,
71
            kInt,
72
            kInt2,
73
            kInt3,
74
            kInt4,
75
        };
76
77
        enum Flags {
78
            // Uniform is declared as an array. 'count' contains array length.
79
            kArray_Flag = 0x1,
80
81
            // Uniform is declared with layout(color). Colors should be supplied as unpremultiplied,
82
            // extended-range (unclamped) sRGB (ie SkColor4f). The uniform will be automatically
83
            // transformed to unpremultiplied extended-range working-space colors.
84
            kColor_Flag = 0x2,
85
86
            // When used with SkMeshSpecification, indicates that the uniform is present in the
87
            // vertex shader. Not used with SkRuntimeEffect.
88
            kVertex_Flag = 0x4,
89
90
            // When used with SkMeshSpecification, indicates that the uniform is present in the
91
            // fragment shader. Not used with SkRuntimeEffect.
92
            kFragment_Flag = 0x8,
93
94
            // This flag indicates that the SkSL uniform uses a medium-precision type
95
            // (i.e., `half` instead of `float`).
96
            kHalfPrecision_Flag = 0x10,
97
        };
98
99
        std::string_view name;
100
        size_t           offset;
101
        Type             type;
102
        int              count;
103
        uint32_t         flags;
104
105
0
        bool isArray() const { return SkToBool(this->flags & kArray_Flag); }
106
0
        bool isColor() const { return SkToBool(this->flags & kColor_Flag); }
107
        size_t sizeInBytes() const;
108
    };
109
110
    // Reflected description of a uniform child (shader or colorFilter) in the effect's SkSL
111
    enum class ChildType {
112
        kShader,
113
        kColorFilter,
114
        kBlender,
115
    };
116
117
    struct Child {
118
        std::string_view name;
119
        ChildType        type;
120
        int              index;
121
    };
122
123
    class Options {
124
    public:
125
        // For testing purposes, disables optimization and inlining. (Normally, Runtime Effects
126
        // don't run the inliner directly, but they still get an inlining pass once they are
127
        // painted.)
128
        bool forceUnoptimized = false;
129
130
    private:
131
        friend class SkRuntimeEffect;
132
        friend class SkRuntimeEffectPriv;
133
134
        // This flag allows Runtime Effects to access Skia implementation details like sk_FragCoord
135
        // and functions with private identifiers (e.g. $rgb_to_hsl).
136
        bool allowPrivateAccess = false;
137
        // When not 0, this field allows Skia to assign a stable key to a known runtime effect
138
        uint32_t fStableKey = 0;
139
140
        // TODO(skia:11209) - Replace this with a promised SkCapabilities?
141
        // This flag lifts the ES2 restrictions on Runtime Effects that are gated by the
142
        // `strictES2Mode` check. Be aware that the software renderer and pipeline-stage effect are
143
        // still largely ES3-unaware and can still fail or crash if post-ES2 features are used.
144
        // This is only intended for use by tests and certain internally created effects.
145
        SkSL::Version maxVersionAllowed = SkSL::Version::k100;
146
    };
147
148
    // If the effect is compiled successfully, `effect` will be non-null.
149
    // Otherwise, `errorText` will contain the reason for failure.
150
    struct Result {
151
        sk_sp<SkRuntimeEffect> effect;
152
        SkString errorText;
153
    };
154
155
    // MakeForColorFilter and MakeForShader verify that the SkSL code is valid for those stages of
156
    // the Skia pipeline. In all of the signatures described below, color parameters and return
157
    // values are flexible. They are listed as being 'vec4', but they can also be 'half4' or
158
    // 'float4'. ('vec4' is an alias for 'float4').
159
160
    // We can't use a default argument for `options` due to a bug in Clang.
161
    // https://bugs.llvm.org/show_bug.cgi?id=36684
162
163
    // Color filter SkSL requires an entry point that looks like:
164
    //     vec4 main(vec4 inColor) { ... }
165
    static Result MakeForColorFilter(SkString sksl, const Options&);
166
0
    static Result MakeForColorFilter(SkString sksl) {
167
0
        return MakeForColorFilter(std::move(sksl), Options{});
168
0
    }
169
170
    // Shader SkSL requires an entry point that looks like:
171
    //     vec4 main(vec2 inCoords) { ... }
172
    static Result MakeForShader(SkString sksl, const Options&);
173
6
    static Result MakeForShader(SkString sksl) {
174
6
        return MakeForShader(std::move(sksl), Options{});
175
6
    }
176
177
    // Blend SkSL requires an entry point that looks like:
178
    //     vec4 main(vec4 srcColor, vec4 dstColor) { ... }
179
    static Result MakeForBlender(SkString sksl, const Options&);
180
1
    static Result MakeForBlender(SkString sksl) {
181
1
        return MakeForBlender(std::move(sksl), Options{});
182
1
    }
183
184
    // Object that allows passing a SkShader, SkColorFilter or SkBlender as a child
185
    class SK_API ChildPtr {
186
    public:
187
45.3k
        ChildPtr() = default;
188
48.8k
        ChildPtr(sk_sp<SkShader> s) : fChild(std::move(s)) {}
189
14.4k
        ChildPtr(sk_sp<SkColorFilter> cf) : fChild(std::move(cf)) {}
190
1.27k
        ChildPtr(sk_sp<SkBlender> b) : fChild(std::move(b)) {}
191
192
        // Asserts that the flattenable is either null, or one of the legal derived types
193
        ChildPtr(sk_sp<SkFlattenable> f);
194
195
        std::optional<ChildType> type() const;
196
197
        SkShader* shader() const;
198
        SkColorFilter* colorFilter() const;
199
        SkBlender* blender() const;
200
0
        SkFlattenable* flattenable() const { return fChild.get(); }
201
202
        using sk_is_trivially_relocatable = std::true_type;
203
204
    private:
205
        sk_sp<SkFlattenable> fChild;
206
207
        static_assert(::sk_is_trivially_relocatable<decltype(fChild)>::value);
208
    };
209
210
    sk_sp<SkShader> makeShader(sk_sp<const SkData> uniforms,
211
                               sk_sp<SkShader> children[],
212
                               size_t childCount,
213
                               const SkMatrix* localMatrix = nullptr) const;
214
    sk_sp<SkShader> makeShader(sk_sp<const SkData> uniforms,
215
                               SkSpan<const ChildPtr> children,
216
                               const SkMatrix* localMatrix = nullptr) const;
217
218
    sk_sp<SkColorFilter> makeColorFilter(sk_sp<const SkData> uniforms) const;
219
    sk_sp<SkColorFilter> makeColorFilter(sk_sp<const SkData> uniforms,
220
                                         sk_sp<SkColorFilter> children[],
221
                                         size_t childCount) const;
222
    sk_sp<SkColorFilter> makeColorFilter(sk_sp<const SkData> uniforms,
223
                                         SkSpan<const ChildPtr> children) const;
224
225
    sk_sp<SkBlender> makeBlender(sk_sp<const SkData> uniforms,
226
                                 SkSpan<const ChildPtr> children = {}) const;
227
228
    /**
229
     * Creates a new Runtime Effect patterned after an already-existing one. The new shader behaves
230
     * like the original, but also creates a debug trace of its execution at the requested
231
     * coordinate. After painting with this shader, the associated DebugTrace object will contain a
232
     * shader execution trace. Call `writeTrace` on the debug trace object to generate a full trace
233
     * suitable for a debugger, or call `dump` to emit a human-readable trace.
234
     *
235
     * Debug traces are only supported on a raster (non-GPU) canvas.
236
237
     * Debug traces are currently only supported on shaders. Color filter and blender tracing is a
238
     * work-in-progress.
239
     */
240
    struct TracedShader {
241
        sk_sp<SkShader> shader;
242
        sk_sp<SkSL::DebugTrace> debugTrace;
243
    };
244
    static TracedShader MakeTraced(sk_sp<SkShader> shader, const SkIPoint& traceCoord);
245
246
    // Returns the SkSL source of the runtime effect shader.
247
    const std::string& source() const;
248
249
    // Combined size of all 'uniform' variables. When calling makeColorFilter or makeShader,
250
    // provide an SkData of this size, containing values for all of those variables.
251
    size_t uniformSize() const;
252
253
876k
    SkSpan<const Uniform> uniforms() const { return SkSpan(fUniforms); }
254
242k
    SkSpan<const Child> children() const { return SkSpan(fChildren); }
255
256
    // Returns pointer to the named uniform variable's description, or nullptr if not found
257
    const Uniform* findUniform(std::string_view name) const;
258
259
    // Returns pointer to the named child's description, or nullptr if not found
260
    const Child* findChild(std::string_view name) const;
261
262
    // Allows the runtime effect type to be identified.
263
43.0k
    bool allowShader()        const { return (fFlags & kAllowShader_Flag);        }
264
281k
    bool allowColorFilter()   const { return (fFlags & kAllowColorFilter_Flag);   }
265
267k
    bool allowBlender()       const { return (fFlags & kAllowBlender_Flag);       }
266
267
    static void RegisterFlattenables();
268
    ~SkRuntimeEffect() override;
269
270
private:
271
    enum Flags {
272
        kUsesSampleCoords_Flag    = 0x001,
273
        kAllowColorFilter_Flag    = 0x002,
274
        kAllowShader_Flag         = 0x004,
275
        kAllowBlender_Flag        = 0x008,
276
        kSamplesOutsideMain_Flag  = 0x010,
277
        kUsesColorTransform_Flag  = 0x020,
278
        kAlwaysOpaque_Flag        = 0x040,
279
        kAlphaUnchanged_Flag      = 0x080,
280
        kDisableOptimization_Flag = 0x100,
281
    };
282
283
    SkRuntimeEffect(std::unique_ptr<SkSL::Program> baseProgram,
284
                    const Options& options,
285
                    const SkSL::FunctionDefinition& main,
286
                    std::vector<Uniform>&& uniforms,
287
                    std::vector<Child>&& children,
288
                    std::vector<SkSL::SampleUsage>&& sampleUsages,
289
                    uint32_t flags);
290
291
    sk_sp<SkRuntimeEffect> makeUnoptimizedClone();
292
293
    static Result MakeFromSource(SkString sksl, const Options& options, SkSL::ProgramKind kind);
294
295
    static Result MakeInternal(std::unique_ptr<SkSL::Program> program,
296
                               const Options& options,
297
                               SkSL::ProgramKind kind);
298
299
    static SkSL::ProgramSettings MakeSettings(const Options& options);
300
301
190k
    uint32_t hash() const { return fHash; }
302
264k
    bool usesSampleCoords()   const { return (fFlags & kUsesSampleCoords_Flag);   }
303
0
    bool samplesOutsideMain() const { return (fFlags & kSamplesOutsideMain_Flag); }
304
18.2k
    bool usesColorTransform() const { return (fFlags & kUsesColorTransform_Flag); }
305
13.0k
    bool alwaysOpaque()       const { return (fFlags & kAlwaysOpaque_Flag);       }
306
4.46k
    bool isAlphaUnchanged()   const { return (fFlags & kAlphaUnchanged_Flag);     }
307
308
    const SkSL::RP::Program* getRPProgram(SkSL::DebugTracePriv* debugTrace) const;
309
310
    friend class GrSkSLFP;              // usesColorTransform
311
    friend class SkRuntimeShader;       // fBaseProgram, fMain, fSampleUsages, getRPProgram()
312
    friend class SkRuntimeBlender;      //
313
    friend class SkRuntimeColorFilter;  //
314
315
    friend class SkRuntimeEffectPriv;
316
317
    uint32_t fHash;
318
    uint32_t fStableKey;
319
320
    std::unique_ptr<SkSL::Program> fBaseProgram;
321
    std::unique_ptr<SkSL::RP::Program> fRPProgram;
322
    mutable SkOnce fCompileRPProgramOnce;
323
    const SkSL::FunctionDefinition& fMain;
324
    std::vector<Uniform> fUniforms;
325
    std::vector<Child> fChildren;
326
    std::vector<SkSL::SampleUsage> fSampleUsages;
327
328
    uint32_t fFlags;  // Flags
329
};
330
331
/**
332
 * SkRuntimeEffectBuilder is a utility to simplify creating SkShader, SkColorFilter, and SkBlender
333
 * objects from SkRuntimeEffects.
334
 *
335
 * NOTE: Like SkRuntimeEffect, this API is experimental and subject to change!
336
 *
337
 * Given an SkRuntimeEffect, the SkRuntimeEffectBuilder manages creating an input data block and
338
 * provides named access to the 'uniform' variables in that block, as well as named access
339
 * to a list of child shader slots. Usage:
340
 *
341
 *   sk_sp<SkRuntimeEffect> effect = ...;
342
 *   SkRuntimeEffectBuilder builder(effect);
343
 *   builder.uniform("some_uniform_float")  = 3.14f;
344
 *   builder.uniform("some_uniform_matrix") = SkM44::Rotate(...);
345
 *   builder.child("some_child_effect")     = mySkImage->makeShader(...);
346
 *   ...
347
 *   sk_sp<SkShader> shader = builder.makeShader(nullptr, false);
348
 *
349
 * Upon calling makeShader, makeColorFilter, or makeBlender, the builder will check the validity
350
 * of the SkSL to see if the entry point is correct.
351
 *
352
 * Note that SkRuntimeEffectBuilder is built entirely on the public API of SkRuntimeEffect,
353
 * so can be used as-is or serve as inspiration for other interfaces or binding techniques.
354
 */
355
class SkRuntimeEffectBuilder {
356
public:
357
    explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect)
358
            : fEffect(std::move(effect))
359
            , fUniforms(SkData::MakeZeroInitialized(fEffect->uniformSize()))
360
40.8k
            , fChildren(fEffect->children().size()) {}
361
    explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> uniforms)
362
            : fEffect(std::move(effect))
363
            , fUniforms(std::move(uniforms))
364
0
            , fChildren(fEffect->children().size()) {}
365
366
    // This is currently required by Android Framework but may go away if that dependency
367
    // can be removed.
368
0
    SkRuntimeEffectBuilder(const SkRuntimeEffectBuilder&) = default;
369
370
    struct BuilderUniform {
371
        // Copy 'val' to this variable. No type conversion is performed - 'val' must be same
372
        // size as expected by the effect. Information about the variable can be queried by
373
        // looking at fVar. If the size is incorrect, no copy will be performed, and debug
374
        // builds will abort. If this is the result of querying a missing variable, fVar will
375
        // be nullptr, and assigning will also do nothing (and abort in debug builds).
376
        template <typename T>
377
        std::enable_if_t<std::is_trivially_copyable<T>::value, BuilderUniform&> operator=(
378
123k
                const T& val) {
379
123k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
123k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
123k
            } else {
384
123k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
123k
                       &val, sizeof(val));
386
123k
            }
387
123k
            return *this;
388
123k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI6SkRectEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
378
4.42k
                const T& val) {
379
4.42k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
4.42k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
4.42k
            } else {
384
4.42k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
4.42k
                       &val, sizeof(val));
386
4.42k
            }
387
4.42k
            return *this;
388
4.42k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV2EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
378
21.9k
                const T& val) {
379
21.9k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
21.9k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
21.9k
            } else {
384
21.9k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
21.9k
                       &val, sizeof(val));
386
21.9k
            }
387
21.9k
            return *this;
388
21.9k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV4EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
378
17.9k
                const T& val) {
379
17.9k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
17.9k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
17.9k
            } else {
384
17.9k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
17.9k
                       &val, sizeof(val));
386
17.9k
            }
387
17.9k
            return *this;
388
17.9k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSIfEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS4_
Line
Count
Source
378
38.5k
                const T& val) {
379
38.5k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
38.5k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
38.5k
            } else {
384
38.5k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
38.5k
                       &val, sizeof(val));
386
38.5k
            }
387
38.5k
            return *this;
388
38.5k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV3EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
378
3.10k
                const T& val) {
379
3.10k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
3.10k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
3.10k
            } else {
384
3.10k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
3.10k
                       &val, sizeof(val));
386
3.10k
            }
387
3.10k
            return *this;
388
3.10k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI7SkISizeEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
378
2.63k
                const T& val) {
379
2.63k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
2.63k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
2.63k
            } else {
384
2.63k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
2.63k
                       &val, sizeof(val));
386
2.63k
            }
387
2.63k
            return *this;
388
2.63k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSIN4skif7IVectorEEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS6_
Line
Count
Source
378
2.63k
                const T& val) {
379
2.63k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
2.63k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
2.63k
            } else {
384
2.63k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
2.63k
                       &val, sizeof(val));
386
2.63k
            }
387
2.63k
            return *this;
388
2.63k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSIiEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS4_
Line
Count
Source
378
5.64k
                const T& val) {
379
5.64k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
5.64k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
5.64k
            } else {
384
5.64k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
5.64k
                       &val, sizeof(val));
386
5.64k
            }
387
5.64k
            return *this;
388
5.64k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayI4SkV4Lm7EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS7_
Line
Count
Source
378
64
                const T& val) {
379
64
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
64
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
64
            } else {
384
64
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
64
                       &val, sizeof(val));
386
64
            }
387
64
            return *this;
388
64
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayI4SkV4Lm14EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS7_
Line
Count
Source
378
2.84k
                const T& val) {
379
2.84k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
2.84k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
2.84k
            } else {
384
2.84k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
2.84k
                       &val, sizeof(val));
386
2.84k
            }
387
2.84k
            return *this;
388
2.84k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayIfLm9EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS6_
Line
Count
Source
378
11.7k
                const T& val) {
379
11.7k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
11.7k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
11.7k
            } else {
384
11.7k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
11.7k
                       &val, sizeof(val));
386
11.7k
            }
387
11.7k
            return *this;
388
11.7k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI6SkSizeEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
378
11.7k
                const T& val) {
379
11.7k
            if (!fVar) {
380
0
                SkDEBUGFAIL("Assigning to missing variable");
381
11.7k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
382
0
                SkDEBUGFAIL("Incorrect value size");
383
11.7k
            } else {
384
11.7k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
385
11.7k
                       &val, sizeof(val));
386
11.7k
            }
387
11.7k
            return *this;
388
11.7k
        }
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSI7SkPointEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSIA16_fEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSIA4_fEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSI6SkRectEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayI4SkV4Lm7EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS7_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayI4SkV4Lm14EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS7_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV2EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV4EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSIfEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS4_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV3EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSI7SkISizeEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSIN4skif7IVectorEEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS6_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSIiEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS4_
389
390
0
        BuilderUniform& operator=(const SkMatrix& val) {
391
0
            if (!fVar) {
392
0
                SkDEBUGFAIL("Assigning to missing variable");
393
0
            } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
394
0
                SkDEBUGFAIL("Incorrect value size");
395
0
            } else {
396
0
                float* data = SkTAddOffset<float>(fOwner->writableUniformData(),
397
0
                                                  (ptrdiff_t)fVar->offset);
398
0
                data[0] = val.get(0); data[1] = val.get(3); data[2] = val.get(6);
399
0
                data[3] = val.get(1); data[4] = val.get(4); data[5] = val.get(7);
400
0
                data[6] = val.get(2); data[7] = val.get(5); data[8] = val.get(8);
401
0
            }
402
0
            return *this;
403
0
        }
404
405
        template <typename T>
406
2.61k
        bool set(const T val[], const int count) {
407
2.61k
            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
408
2.61k
            if (!fVar) {
409
0
                SkDEBUGFAIL("Assigning to missing variable");
410
0
                return false;
411
2.61k
            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
412
0
                SkDEBUGFAIL("Incorrect value size");
413
0
                return false;
414
2.61k
            } else {
415
2.61k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
416
2.61k
                       val, sizeof(T) * count);
417
2.61k
            }
418
2.61k
            return true;
419
2.61k
        }
bool SkRuntimeEffectBuilder::BuilderUniform::set<float>(float const*, int)
Line
Count
Source
406
2.61k
        bool set(const T val[], const int count) {
407
2.61k
            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
408
2.61k
            if (!fVar) {
409
0
                SkDEBUGFAIL("Assigning to missing variable");
410
0
                return false;
411
2.61k
            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
412
0
                SkDEBUGFAIL("Incorrect value size");
413
0
                return false;
414
2.61k
            } else {
415
2.61k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
416
2.61k
                       val, sizeof(T) * count);
417
2.61k
            }
418
2.61k
            return true;
419
2.61k
        }
Unexecuted instantiation: bool SkRuntimeEffectBuilder::BuilderUniform::set<float>(float const*, int)
420
421
        SkRuntimeEffectBuilder*         fOwner;
422
        const SkRuntimeEffect::Uniform* fVar;    // nullptr if the variable was not found
423
    };
424
425
    struct BuilderChild {
426
46.3k
        template <typename T> BuilderChild& operator=(sk_sp<T> val) {
427
46.3k
            if (!fChild) {
428
0
                SkDEBUGFAIL("Assigning to missing child");
429
46.3k
            } else {
430
46.3k
                fOwner->fChildren[(size_t)fChild->index] = std::move(val);
431
46.3k
            }
432
46.3k
            return *this;
433
46.3k
        }
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild& SkRuntimeEffectBuilder::BuilderChild::operator=<SkBlender>(sk_sp<SkBlender>)
SkRuntimeEffectBuilder::BuilderChild& SkRuntimeEffectBuilder::BuilderChild::operator=<SkShader>(sk_sp<SkShader>)
Line
Count
Source
426
46.3k
        template <typename T> BuilderChild& operator=(sk_sp<T> val) {
427
46.3k
            if (!fChild) {
428
0
                SkDEBUGFAIL("Assigning to missing child");
429
46.3k
            } else {
430
46.3k
                fOwner->fChildren[(size_t)fChild->index] = std::move(val);
431
46.3k
            }
432
46.3k
            return *this;
433
46.3k
        }
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild& SkRuntimeEffectBuilder::BuilderChild::operator=<SkColorFilter>(sk_sp<SkColorFilter>)
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild& SkRuntimeEffectBuilder::BuilderChild::operator=<SkBlender>(sk_sp<SkBlender>)
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild& SkRuntimeEffectBuilder::BuilderChild::operator=<SkColorFilter>(sk_sp<SkColorFilter>)
434
435
0
        BuilderChild& operator=(std::nullptr_t) {
436
0
            if (!fChild) {
437
0
                SkDEBUGFAIL("Assigning to missing child");
438
0
            } else {
439
0
                fOwner->fChildren[(size_t)fChild->index] = SkRuntimeEffect::ChildPtr{};
440
0
            }
441
0
            return *this;
442
0
        }
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild::operator=(decltype(nullptr))
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild::operator=(decltype(nullptr))
443
444
        SkRuntimeEffectBuilder*       fOwner;
445
        const SkRuntimeEffect::Child* fChild;  // nullptr if the child was not found
446
    };
447
448
41.7k
    const SkRuntimeEffect* effect() const { return fEffect.get(); }
449
450
125k
    BuilderUniform uniform(std::string_view name) { return { this, fEffect->findUniform(name) }; }
451
46.3k
    BuilderChild child(std::string_view name) { return { this, fEffect->findChild(name) }; }
452
453
    // Get access to the collated uniforms and children (in the order expected by APIs like
454
    // makeShader on the effect):
455
41.7k
    sk_sp<const SkData> uniforms() const { return fUniforms; }
456
41.7k
    SkSpan<const SkRuntimeEffect::ChildPtr> children() const { return fChildren; }
457
458
    // Build methods, at this point checks are made to ensure the SkSL entry point `main` is correct
459
    sk_sp<SkShader> makeShader(const SkMatrix* localMatrix = nullptr) const;
460
    sk_sp<SkColorFilter> makeColorFilter() const;
461
    sk_sp<SkBlender> makeBlender() const;
462
463
40.8k
    ~SkRuntimeEffectBuilder() = default;
464
465
protected:
466
    SkRuntimeEffectBuilder() = delete;
467
468
    SkRuntimeEffectBuilder(SkRuntimeEffectBuilder&&) = default;
469
470
    SkRuntimeEffectBuilder& operator=(SkRuntimeEffectBuilder&&) = delete;
471
    SkRuntimeEffectBuilder& operator=(const SkRuntimeEffectBuilder&) = delete;
472
473
private:
474
125k
    void* writableUniformData() {
475
125k
        if (!fUniforms->unique()) {
476
0
            fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
477
0
        }
478
125k
        return fUniforms->writable_data();
479
125k
    }
480
481
    sk_sp<SkRuntimeEffect>                 fEffect;
482
    sk_sp<SkData>                          fUniforms;
483
    std::vector<SkRuntimeEffect::ChildPtr> fChildren;
484
485
    friend class SkRuntimeImageFilter;
486
};
487
488
/**
489
 * DEPRECATED: Subclass logic has been moved to base class SkRuntimeEffectBuilder.
490
 */
491
using SkRuntimeShaderBuilder = SkRuntimeEffectBuilder;
492
using SkRuntimeColorFilterBuilder = SkRuntimeEffectBuilder;
493
using SkRuntimeBlendBuilder = SkRuntimeEffectBuilder;
494
495
#endif  // SkRuntimeEffect_DEFINED