/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 |