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/SkString.h" |
12 | |
13 | #include <vector> |
14 | |
15 | #if SK_SUPPORT_GPU |
16 | #include "include/gpu/GrContextOptions.h" |
17 | #include "include/private/GrTypesPriv.h" |
18 | #endif |
19 | |
20 | class GrShaderCaps; |
21 | class SkColorFilter; |
22 | class SkMatrix; |
23 | class SkShader; |
24 | |
25 | namespace SkSL { |
26 | class ByteCode; |
27 | struct PipelineStageArgs; |
28 | struct Program; |
29 | class SharedCompiler; |
30 | } |
31 | |
32 | /* |
33 | * SkRuntimeEffect supports creating custom SkShader and SkColorFilter objects using Skia's SkSL |
34 | * shading language. |
35 | * * |
36 | * This API is experimental and subject to change. |
37 | */ |
38 | class SK_API SkRuntimeEffect : public SkRefCnt { |
39 | public: |
40 | struct Variable { |
41 | enum class Qualifier { |
42 | kUniform, |
43 | kIn, |
44 | }; |
45 | |
46 | enum class Type { |
47 | kBool, |
48 | kInt, |
49 | kFloat, |
50 | kFloat2, |
51 | kFloat3, |
52 | kFloat4, |
53 | kFloat2x2, |
54 | kFloat3x3, |
55 | kFloat4x4, |
56 | }; |
57 | |
58 | enum Flags { |
59 | kArray_Flag = 0x1, |
60 | }; |
61 | |
62 | SkString fName; |
63 | size_t fOffset; |
64 | Qualifier fQualifier; |
65 | Type fType; |
66 | int fCount; |
67 | uint32_t fFlags; |
68 | |
69 | #if SK_SUPPORT_GPU |
70 | GrSLType fGPUType; |
71 | #endif |
72 | |
73 | bool isArray() const { return SkToBool(fFlags & kArray_Flag); } |
74 | size_t sizeInBytes() const; |
75 | }; |
76 | |
77 | struct Varying { |
78 | SkString fName; |
79 | int fWidth; // 1 - 4 (floats) |
80 | }; |
81 | |
82 | // [Effect, ErrorText] |
83 | // If successful, Effect != nullptr, otherwise, ErrorText contains the reason for failure. |
84 | using EffectResult = std::tuple<sk_sp<SkRuntimeEffect>, SkString>; |
85 | |
86 | static EffectResult Make(SkString sksl); |
87 | |
88 | sk_sp<SkShader> makeShader(sk_sp<SkData> inputs, sk_sp<SkShader> children[], size_t childCount, |
89 | const SkMatrix* localMatrix, bool isOpaque); |
90 | |
91 | sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs, sk_sp<SkColorFilter> children[], |
92 | size_t childCount); |
93 | sk_sp<SkColorFilter> makeColorFilter(sk_sp<SkData> inputs); |
94 | |
95 | const SkString& source() const { return fSkSL; } |
96 | uint32_t hash() const { return fHash; } |
97 | |
98 | template <typename T> |
99 | class ConstIterable { |
100 | public: |
101 | ConstIterable(const std::vector<T>& vec) : fVec(vec) {} |
102 | |
103 | using const_iterator = typename std::vector<T>::const_iterator; |
104 | |
105 | const_iterator begin() const { return fVec.begin(); } |
106 | const_iterator end() const { return fVec.end(); } |
107 | size_t count() const { return fVec.size(); } |
108 | |
109 | private: |
110 | const std::vector<T>& fVec; |
111 | }; |
112 | |
113 | // Combined size of all 'in' and 'uniform' variables. When calling makeColorFilter or |
114 | // makeShader, provide an SkData of this size, containing values for all of those variables. |
115 | size_t inputSize() const; |
116 | |
117 | // Combined size of just the 'uniform' variables. |
118 | size_t uniformSize() const { return fUniformSize; } |
119 | |
120 | ConstIterable<Variable> inputs() const { return ConstIterable<Variable>(fInAndUniformVars); } |
121 | ConstIterable<SkString> children() const { return ConstIterable<SkString>(fChildren); } |
122 | ConstIterable<Varying> varyings() const { return ConstIterable<Varying>(fVaryings); } |
123 | |
124 | #if SK_SUPPORT_GPU |
125 | // This re-compiles the program from scratch, using the supplied shader caps. |
126 | // This is necessary to get the correct values of settings. |
127 | bool toPipelineStage(const void* inputs, const GrShaderCaps* shaderCaps, |
128 | GrContextOptions::ShaderErrorHandler* errorHandler, |
129 | SkSL::PipelineStageArgs* outArgs); |
130 | #endif |
131 | |
132 | // [ByteCode, ErrorText] |
133 | // If successful, ByteCode != nullptr, otherwise, ErrorText contains the reason for failure. |
134 | using ByteCodeResult = std::tuple<std::unique_ptr<SkSL::ByteCode>, SkString>; |
135 | |
136 | ByteCodeResult toByteCode(const void* inputs) const; |
137 | |
138 | static void RegisterFlattenables(); |
139 | |
140 | ~SkRuntimeEffect(); |
141 | |
142 | private: |
143 | SkRuntimeEffect(SkString sksl, std::unique_ptr<SkSL::Program> baseProgram, |
144 | std::vector<Variable>&& inAndUniformVars, std::vector<SkString>&& children, |
145 | std::vector<Varying>&& varyings, size_t uniformSize); |
146 | |
147 | using SpecializeResult = std::tuple<std::unique_ptr<SkSL::Program>, SkString>; |
148 | SpecializeResult specialize(SkSL::Program& baseProgram, const void* inputs, |
149 | const SkSL::SharedCompiler&) const; |
150 | |
151 | uint32_t fHash; |
152 | SkString fSkSL; |
153 | |
154 | std::unique_ptr<SkSL::Program> fBaseProgram; |
155 | std::vector<Variable> fInAndUniformVars; |
156 | std::vector<SkString> fChildren; |
157 | std::vector<Varying> fVaryings; |
158 | |
159 | size_t fUniformSize; |
160 | }; |
161 | |
162 | #endif |
163 | |