Coverage Report

Created: 2024-05-20 07:14

/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
3
    static Result MakeForShader(SkString sksl) {
174
3
        return MakeForShader(std::move(sksl), Options{});
175
3
    }
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
46.4k
        ChildPtr() = default;
188
52.1k
        ChildPtr(sk_sp<SkShader> s) : fChild(std::move(s)) {}
189
14.7k
        ChildPtr(sk_sp<SkColorFilter> cf) : fChild(std::move(cf)) {}
190
2.83k
        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
285k
    SkSpan<const Uniform> uniforms() const { return SkSpan(fUniforms); }
254
93.9k
    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.6k
    bool allowShader()        const { return (fFlags & kAllowShader_Flag);        }
264
104k
    bool allowColorFilter()   const { return (fFlags & kAllowColorFilter_Flag);   }
265
92.1k
    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
28.6k
    uint32_t hash() const { return fHash; }
302
88.6k
    bool usesSampleCoords()   const { return (fFlags & kUsesSampleCoords_Flag);   }
303
0
    bool samplesOutsideMain() const { return (fFlags & kSamplesOutsideMain_Flag); }
304
11.6k
    bool usesColorTransform() const { return (fFlags & kUsesColorTransform_Flag); }
305
18.5k
    bool alwaysOpaque()       const { return (fFlags & kAlwaysOpaque_Flag);       }
306
6.60k
    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
/** Base class for SkRuntimeShaderBuilder, defined below. */
332
class SkRuntimeEffectBuilder {
333
public:
334
    struct BuilderUniform {
335
        // Copy 'val' to this variable. No type conversion is performed - 'val' must be same
336
        // size as expected by the effect. Information about the variable can be queried by
337
        // looking at fVar. If the size is incorrect, no copy will be performed, and debug
338
        // builds will abort. If this is the result of querying a missing variable, fVar will
339
        // be nullptr, and assigning will also do nothing (and abort in debug builds).
340
        template <typename T>
341
        std::enable_if_t<std::is_trivially_copyable<T>::value, BuilderUniform&> operator=(
342
121k
                const T& val) {
343
121k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
121k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
121k
            } else {
348
121k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
121k
                       &val, sizeof(val));
350
121k
            }
351
121k
            return *this;
352
121k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI6SkRectEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
342
6.76k
                const T& val) {
343
6.76k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
6.76k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
6.76k
            } else {
348
6.76k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
6.76k
                       &val, sizeof(val));
350
6.76k
            }
351
6.76k
            return *this;
352
6.76k
        }
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayI4SkV4Lm7EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS7_
Unexecuted instantiation: _ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayI4SkV4Lm14EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS7_
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV2EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
342
20.5k
                const T& val) {
343
20.5k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
20.5k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
20.5k
            } else {
348
20.5k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
20.5k
                       &val, sizeof(val));
350
20.5k
            }
351
20.5k
            return *this;
352
20.5k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV4EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
342
23.1k
                const T& val) {
343
23.1k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
23.1k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
23.1k
            } else {
348
23.1k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
23.1k
                       &val, sizeof(val));
350
23.1k
            }
351
23.1k
            return *this;
352
23.1k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSIfEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS4_
Line
Count
Source
342
35.7k
                const T& val) {
343
35.7k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
35.7k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
35.7k
            } else {
348
35.7k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
35.7k
                       &val, sizeof(val));
350
35.7k
            }
351
35.7k
            return *this;
352
35.7k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI4SkV3EENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
342
4.03k
                const T& val) {
343
4.03k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
4.03k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
4.03k
            } else {
348
4.03k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
4.03k
                       &val, sizeof(val));
350
4.03k
            }
351
4.03k
            return *this;
352
4.03k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI7SkISizeEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
342
2.77k
                const T& val) {
343
2.77k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
2.77k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
2.77k
            } else {
348
2.77k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
2.77k
                       &val, sizeof(val));
350
2.77k
            }
351
2.77k
            return *this;
352
2.77k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSIN4skif7IVectorEEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS6_
Line
Count
Source
342
2.77k
                const T& val) {
343
2.77k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
2.77k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
2.77k
            } else {
348
2.77k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
2.77k
                       &val, sizeof(val));
350
2.77k
            }
351
2.77k
            return *this;
352
2.77k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSIiEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS4_
Line
Count
Source
342
5.95k
                const T& val) {
343
5.95k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
5.95k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
5.95k
            } else {
348
5.95k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
5.95k
                       &val, sizeof(val));
350
5.95k
            }
351
5.95k
            return *this;
352
5.95k
        }
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_
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSINSt3__15arrayIfLm9EEEEENS2_9enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS6_
Line
Count
Source
342
9.89k
                const T& val) {
343
9.89k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
9.89k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
9.89k
            } else {
348
9.89k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
9.89k
                       &val, sizeof(val));
350
9.89k
            }
351
9.89k
            return *this;
352
9.89k
        }
_ZN22SkRuntimeEffectBuilder14BuilderUniformaSI6SkSizeEENSt3__19enable_ifIXsr3std21is_trivially_copyableIT_EE5valueERS0_E4typeERKS5_
Line
Count
Source
342
9.89k
                const T& val) {
343
9.89k
            if (!fVar) {
344
0
                SkDEBUGFAIL("Assigning to missing variable");
345
9.89k
            } else if (sizeof(val) != fVar->sizeInBytes()) {
346
0
                SkDEBUGFAIL("Incorrect value size");
347
9.89k
            } else {
348
9.89k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
349
9.89k
                       &val, sizeof(val));
350
9.89k
            }
351
9.89k
            return *this;
352
9.89k
        }
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_
353
354
0
        BuilderUniform& operator=(const SkMatrix& val) {
355
0
            if (!fVar) {
356
0
                SkDEBUGFAIL("Assigning to missing variable");
357
0
            } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
358
0
                SkDEBUGFAIL("Incorrect value size");
359
0
            } else {
360
0
                float* data = SkTAddOffset<float>(fOwner->writableUniformData(),
361
0
                                                  (ptrdiff_t)fVar->offset);
362
0
                data[0] = val.get(0); data[1] = val.get(3); data[2] = val.get(6);
363
0
                data[3] = val.get(1); data[4] = val.get(4); data[5] = val.get(7);
364
0
                data[6] = val.get(2); data[7] = val.get(5); data[8] = val.get(8);
365
0
            }
366
0
            return *this;
367
0
        }
368
369
        template <typename T>
370
2.74k
        bool set(const T val[], const int count) {
371
2.74k
            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
372
2.74k
            if (!fVar) {
373
0
                SkDEBUGFAIL("Assigning to missing variable");
374
0
                return false;
375
2.74k
            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
376
0
                SkDEBUGFAIL("Incorrect value size");
377
0
                return false;
378
2.74k
            } else {
379
2.74k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
380
2.74k
                       val, sizeof(T) * count);
381
2.74k
            }
382
2.74k
            return true;
383
2.74k
        }
bool SkRuntimeEffectBuilder::BuilderUniform::set<float>(float const*, int)
Line
Count
Source
370
2.74k
        bool set(const T val[], const int count) {
371
2.74k
            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
372
2.74k
            if (!fVar) {
373
0
                SkDEBUGFAIL("Assigning to missing variable");
374
0
                return false;
375
2.74k
            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
376
0
                SkDEBUGFAIL("Incorrect value size");
377
0
                return false;
378
2.74k
            } else {
379
2.74k
                memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset),
380
2.74k
                       val, sizeof(T) * count);
381
2.74k
            }
382
2.74k
            return true;
383
2.74k
        }
Unexecuted instantiation: bool SkRuntimeEffectBuilder::BuilderUniform::set<float>(float const*, int)
384
385
        SkRuntimeEffectBuilder*         fOwner;
386
        const SkRuntimeEffect::Uniform* fVar;    // nullptr if the variable was not found
387
    };
388
389
    struct BuilderChild {
390
46.4k
        template <typename T> BuilderChild& operator=(sk_sp<T> val) {
391
46.4k
            if (!fChild) {
392
0
                SkDEBUGFAIL("Assigning to missing child");
393
46.4k
            } else {
394
46.4k
                fOwner->fChildren[(size_t)fChild->index] = std::move(val);
395
46.4k
            }
396
46.4k
            return *this;
397
46.4k
        }
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild& SkRuntimeEffectBuilder::BuilderChild::operator=<SkBlender>(sk_sp<SkBlender>)
SkRuntimeEffectBuilder::BuilderChild& SkRuntimeEffectBuilder::BuilderChild::operator=<SkShader>(sk_sp<SkShader>)
Line
Count
Source
390
46.4k
        template <typename T> BuilderChild& operator=(sk_sp<T> val) {
391
46.4k
            if (!fChild) {
392
0
                SkDEBUGFAIL("Assigning to missing child");
393
46.4k
            } else {
394
46.4k
                fOwner->fChildren[(size_t)fChild->index] = std::move(val);
395
46.4k
            }
396
46.4k
            return *this;
397
46.4k
        }
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>)
398
399
0
        BuilderChild& operator=(std::nullptr_t) {
400
0
            if (!fChild) {
401
0
                SkDEBUGFAIL("Assigning to missing child");
402
0
            } else {
403
0
                fOwner->fChildren[(size_t)fChild->index] = SkRuntimeEffect::ChildPtr{};
404
0
            }
405
0
            return *this;
406
0
        }
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild::operator=(decltype(nullptr))
Unexecuted instantiation: SkRuntimeEffectBuilder::BuilderChild::operator=(decltype(nullptr))
407
408
        SkRuntimeEffectBuilder*       fOwner;
409
        const SkRuntimeEffect::Child* fChild;  // nullptr if the child was not found
410
    };
411
412
40.8k
    const SkRuntimeEffect* effect() const { return fEffect.get(); }
413
414
124k
    BuilderUniform uniform(std::string_view name) { return { this, fEffect->findUniform(name) }; }
415
46.4k
    BuilderChild child(std::string_view name) { return { this, fEffect->findChild(name) }; }
416
417
    // Get access to the collated uniforms and children (in the order expected by APIs like
418
    // makeShader on the effect):
419
40.8k
    sk_sp<const SkData> uniforms() const { return fUniforms; }
420
40.8k
    SkSpan<const SkRuntimeEffect::ChildPtr> children() const { return fChildren; }
421
422
protected:
423
    SkRuntimeEffectBuilder() = delete;
424
    explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect)
425
            : fEffect(std::move(effect))
426
            , fUniforms(SkData::MakeZeroInitialized(fEffect->uniformSize()))
427
40.8k
            , fChildren(fEffect->children().size()) {}
428
    explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> uniforms)
429
            : fEffect(std::move(effect))
430
            , fUniforms(std::move(uniforms))
431
0
            , fChildren(fEffect->children().size()) {}
432
433
    SkRuntimeEffectBuilder(SkRuntimeEffectBuilder&&) = default;
434
0
    SkRuntimeEffectBuilder(const SkRuntimeEffectBuilder&) = default;
435
436
    SkRuntimeEffectBuilder& operator=(SkRuntimeEffectBuilder&&) = delete;
437
    SkRuntimeEffectBuilder& operator=(const SkRuntimeEffectBuilder&) = delete;
438
439
private:
440
124k
    void* writableUniformData() {
441
124k
        if (!fUniforms->unique()) {
442
0
            fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
443
0
        }
444
124k
        return fUniforms->writable_data();
445
124k
    }
446
447
    sk_sp<SkRuntimeEffect>                 fEffect;
448
    sk_sp<SkData>                          fUniforms;
449
    std::vector<SkRuntimeEffect::ChildPtr> fChildren;
450
};
451
452
/**
453
 * SkRuntimeShaderBuilder is a utility to simplify creating SkShader objects from SkRuntimeEffects.
454
 *
455
 * NOTE: Like SkRuntimeEffect, this API is experimental and subject to change!
456
 *
457
 * Given an SkRuntimeEffect, the SkRuntimeShaderBuilder manages creating an input data block and
458
 * provides named access to the 'uniform' variables in that block, as well as named access
459
 * to a list of child shader slots. Usage:
460
 *
461
 *   sk_sp<SkRuntimeEffect> effect = ...;
462
 *   SkRuntimeShaderBuilder builder(effect);
463
 *   builder.uniform("some_uniform_float")  = 3.14f;
464
 *   builder.uniform("some_uniform_matrix") = SkM44::Rotate(...);
465
 *   builder.child("some_child_effect")     = mySkImage->makeShader(...);
466
 *   ...
467
 *   sk_sp<SkShader> shader = builder.makeShader(nullptr, false);
468
 *
469
 * Note that SkRuntimeShaderBuilder is built entirely on the public API of SkRuntimeEffect,
470
 * so can be used as-is or serve as inspiration for other interfaces or binding techniques.
471
 */
472
class SK_API SkRuntimeShaderBuilder : public SkRuntimeEffectBuilder {
473
public:
474
    explicit SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect>);
475
    // This is currently required by Android Framework but may go away if that dependency
476
    // can be removed.
477
0
    SkRuntimeShaderBuilder(const SkRuntimeShaderBuilder&) = default;
478
    ~SkRuntimeShaderBuilder();
479
480
    sk_sp<SkShader> makeShader(const SkMatrix* localMatrix = nullptr) const;
481
482
private:
483
    explicit SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> uniforms)
484
0
            : SkRuntimeEffectBuilder(std::move(effect), std::move(uniforms)) {}
485
486
    friend class SkRuntimeImageFilter;
487
};
488
489
/**
490
 * SkRuntimeColorFilterBuilder makes it easy to setup and assign uniforms to runtime color filters.
491
 */
492
class SK_API SkRuntimeColorFilterBuilder : public SkRuntimeEffectBuilder {
493
public:
494
    explicit SkRuntimeColorFilterBuilder(sk_sp<SkRuntimeEffect>);
495
    ~SkRuntimeColorFilterBuilder();
496
497
    SkRuntimeColorFilterBuilder(const SkRuntimeColorFilterBuilder&) = delete;
498
    SkRuntimeColorFilterBuilder& operator=(const SkRuntimeColorFilterBuilder&) = delete;
499
500
    sk_sp<SkColorFilter> makeColorFilter() const;
501
};
502
503
/**
504
 * SkRuntimeBlendBuilder is a utility to simplify creation and uniform setup of runtime blenders.
505
 */
506
class SK_API SkRuntimeBlendBuilder : public SkRuntimeEffectBuilder {
507
public:
508
    explicit SkRuntimeBlendBuilder(sk_sp<SkRuntimeEffect>);
509
    ~SkRuntimeBlendBuilder();
510
511
    SkRuntimeBlendBuilder(const SkRuntimeBlendBuilder&) = delete;
512
    SkRuntimeBlendBuilder& operator=(const SkRuntimeBlendBuilder&) = delete;
513
514
    sk_sp<SkBlender> makeBlender() const;
515
};
516
517
#endif  // SkRuntimeEffect_DEFINED