1 | /* |
2 | * Copyright 2013 Google Inc. |
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 GrGLSLFragmentProcessor_DEFINED |
9 | #define GrGLSLFragmentProcessor_DEFINED |
10 | |
11 | #include "src/gpu/GrFragmentProcessor.h" |
12 | #include "src/gpu/GrShaderVar.h" |
13 | #include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h" |
14 | #include "src/gpu/glsl/GrGLSLProgramDataManager.h" |
15 | #include "src/gpu/glsl/GrGLSLUniformHandler.h" |
16 | #include "src/sksl/SkSLString.h" |
17 | |
18 | class GrProcessor; |
19 | class GrProcessorKeyBuilder; |
20 | class GrGLSLFPBuilder; |
21 | class GrGLSLFPFragmentBuilder; |
22 | |
23 | class GrGLSLFragmentProcessor { |
24 | public: |
25 | GrGLSLFragmentProcessor() {} |
26 | |
27 | virtual ~GrGLSLFragmentProcessor() { |
28 | for (int i = 0; i < fChildProcessors.count(); ++i) { |
29 | delete fChildProcessors[i]; |
30 | } |
31 | } |
32 | |
33 | using UniformHandle = GrGLSLUniformHandler::UniformHandle; |
34 | using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; |
35 | |
36 | private: |
37 | /** |
38 | * This class allows the shader builder to provide each GrGLSLFragmentProcessor with an array of |
39 | * generated variables where each generated variable corresponds to an element of an array on |
40 | * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a |
41 | * variable holding transformed coords for each GrCoordTransform owned by the FP. |
42 | */ |
43 | template <typename T, int (GrFragmentProcessor::*COUNT)() const> |
44 | class BuilderInputProvider { |
45 | public: |
46 | BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} |
47 | |
48 | const T& operator[] (int i) const { |
49 | SkASSERT(i >= 0 && i < (fFP->*COUNT)()); |
50 | return fTs[i]; |
51 | } |
52 | |
53 | int count() const { return (fFP->*COUNT)(); } |
54 | |
55 | BuilderInputProvider childInputs(int childIdx) const { |
56 | const GrFragmentProcessor* child = fFP->childProcessor(childIdx); |
57 | SkASSERT(child); |
58 | int numToSkip = 0; |
59 | for (const auto& fp : GrFragmentProcessor::FPRange(*fFP)) { |
60 | if (&fp == child) { |
61 | return BuilderInputProvider(child, fTs + numToSkip); |
62 | } |
63 | numToSkip += (fp.*COUNT)(); |
64 | } |
65 | SK_ABORT("Didn't find the child." ); |
66 | return {nullptr, nullptr}; |
67 | } |
68 | |
69 | private: |
70 | const GrFragmentProcessor* fFP; |
71 | const T* fTs; |
72 | }; |
73 | |
74 | public: |
75 | using TransformedCoordVars = |
76 | BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numVaryingCoordsUsed>; |
77 | |
78 | /** Called when the program stage should insert its code into the shaders. The code in each |
79 | shader will be in its own block ({}) and so locally scoped names will not collide across |
80 | stages. |
81 | |
82 | @param fragBuilder Interface used to emit code in the shaders. |
83 | @param fp The processor that generated this program stage. |
84 | @param key The key that was computed by GenKey() from the generating |
85 | GrProcessor. |
86 | @param outputColor A predefined half4 in the FS in which the stage should place its |
87 | output color (or coverage). |
88 | @param inputColor A half4 that holds the input color to the stage in the FS. This may |
89 | be nullptr in which case the fInputColor is set to "half4(1.0)" |
90 | (solid white) so this is guaranteed non-null. |
91 | TODO: Better system for communicating optimization info |
92 | (e.g. input color is solid white, trans black, known to be opaque, |
93 | etc.) that allows the processor to communicate back similar known |
94 | info about its output. |
95 | @param localCoord The name of a local coord reference to a float2 variable. |
96 | @param transformedCoords Fragment shader variables containing the coords computed using |
97 | each of the GrFragmentProcessor's GrCoordTransforms. |
98 | */ |
99 | struct EmitArgs { |
100 | EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, |
101 | GrGLSLUniformHandler* uniformHandler, |
102 | const GrShaderCaps* caps, |
103 | const GrFragmentProcessor& fp, |
104 | const char* outputColor, |
105 | const char* inputColor, |
106 | const char* sampleCoord, |
107 | const TransformedCoordVars& transformedCoordVars) |
108 | : fFragBuilder(fragBuilder) |
109 | , fUniformHandler(uniformHandler) |
110 | , fShaderCaps(caps) |
111 | , fFp(fp) |
112 | , fOutputColor(outputColor) |
113 | , fInputColor(inputColor ? inputColor : "half4(1.0)" ) |
114 | , fSampleCoord(sampleCoord) |
115 | , fTransformedCoords(transformedCoordVars) {} |
116 | GrGLSLFPFragmentBuilder* fFragBuilder; |
117 | GrGLSLUniformHandler* fUniformHandler; |
118 | const GrShaderCaps* fShaderCaps; |
119 | const GrFragmentProcessor& fFp; |
120 | const char* fOutputColor; |
121 | const char* fInputColor; |
122 | const char* fSampleCoord; |
123 | const TransformedCoordVars& fTransformedCoords; |
124 | }; |
125 | |
126 | virtual void emitCode(EmitArgs&) = 0; |
127 | |
128 | // This does not recurse to any attached child processors. Recursing the entire processor tree |
129 | // is the responsibility of the caller. |
130 | void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); |
131 | |
132 | int numChildProcessors() const { return fChildProcessors.count(); } |
133 | |
134 | GrGLSLFragmentProcessor* childProcessor(int index) const { return fChildProcessors[index]; } |
135 | |
136 | void emitChildFunction(int childIndex, EmitArgs& parentArgs); |
137 | |
138 | // Invoke the child with the default input color (solid white) |
139 | inline SkString invokeChild(int childIndex, EmitArgs& parentArgs, |
140 | SkSL::String skslCoords = "" ) { |
141 | return this->invokeChild(childIndex, nullptr, parentArgs, skslCoords); |
142 | } |
143 | |
144 | inline SkString invokeChildWithMatrix(int childIndex, EmitArgs& parentArgs, |
145 | SkSL::String skslMatrix = "" ) { |
146 | return this->invokeChildWithMatrix(childIndex, nullptr, parentArgs, skslMatrix); |
147 | } |
148 | |
149 | /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will |
150 | * automatically extract the coords and samplers of that child and pass them on to the child's |
151 | * emitCode(). Also, any uniforms or functions emitted by the child will have their names |
152 | * mangled to prevent redefinitions. The returned string contains the output color (as a call |
153 | * to the child's helper function). It is legal to pass nullptr as inputColor, since all |
154 | * fragment processors are required to work without an input color. |
155 | * |
156 | * When skslCoords is empty, invokeChild corresponds to a call to "sample(child, color)" |
157 | * in SkSL. When skslCoords is not empty, invokeChild corresponds to a call to |
158 | * "sample(child, color, float2)", where skslCoords is an SkSL expression that evaluates to a |
159 | * float2 and is passed in as the 3rd argument. |
160 | */ |
161 | SkString invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs, |
162 | SkSL::String skslCoords = "" ); |
163 | |
164 | /** |
165 | * As invokeChild, but transforms the coordinates according to the provided matrix. This variant |
166 | * corresponds to a call of "sample(child, color, matrix)" in SkSL, where skslMatrix is an SkSL |
167 | * expression that evaluates to a float3x3 and is passed in as the 3rd argument. |
168 | * |
169 | * If skslMatrix is the empty string, then it is automatically replaced with the expression |
170 | * attached to the child's SampleUsage object. This is only valid if the child is sampled with |
171 | * a const-uniform matrix. If the sample matrix is const-or-uniform, the expression will be |
172 | * automatically resolved to the mangled uniform name. |
173 | */ |
174 | SkString invokeChildWithMatrix(int childIndex, const char* inputColor, EmitArgs& parentArgs, |
175 | SkSL::String skslMatrix = "" ); |
176 | |
177 | /** |
178 | * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of |
179 | * GLSLFPS. If initialized with an array color followed by coverage processors installed in a |
180 | * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with |
181 | * a GrPipeline that produces the same program key. |
182 | */ |
183 | class Iter { |
184 | public: |
185 | Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt); |
186 | Iter(GrGLSLFragmentProcessor& fp) { fFPStack.push_back(&fp); } |
187 | |
188 | GrGLSLFragmentProcessor& operator*() const; |
189 | GrGLSLFragmentProcessor* operator->() const; |
190 | Iter& operator++(); |
191 | operator bool() const { return !fFPStack.empty(); } |
192 | |
193 | // Because each iterator carries a stack we want to avoid copies. |
194 | Iter(const Iter&) = delete; |
195 | Iter& operator=(const Iter&) = delete; |
196 | |
197 | private: |
198 | SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; |
199 | }; |
200 | |
201 | class ParallelIterEnd {}; |
202 | |
203 | /** |
204 | * Walks parallel trees of GrFragmentProcessor and associated GrGLSLFragmentProcessors. The |
205 | * GrGLSLFragmentProcessor used to initialize the iterator must have been created by calling |
206 | * GrFragmentProcessor::createGLSLInstance() on the passed GrFragmentProcessor. |
207 | */ |
208 | class ParallelIter { |
209 | public: |
210 | ParallelIter(const GrFragmentProcessor& fp, GrGLSLFragmentProcessor& glslFP); |
211 | |
212 | ParallelIter& operator++(); |
213 | |
214 | std::tuple<const GrFragmentProcessor&, GrGLSLFragmentProcessor&> operator*() const; |
215 | |
216 | bool operator==(const ParallelIterEnd& end) const; |
217 | |
218 | bool operator!=(const ParallelIterEnd& end) const { return !(*this == end); } |
219 | |
220 | private: |
221 | GrFragmentProcessor::CIter fpIter; |
222 | GrGLSLFragmentProcessor::Iter glslIter; |
223 | }; |
224 | |
225 | class ParallelRange { |
226 | public: |
227 | ParallelRange(const GrFragmentProcessor& fp, GrGLSLFragmentProcessor& glslFP); |
228 | |
229 | ParallelIter begin() { return {fInitialFP, fInitialGLSLFP}; } |
230 | |
231 | ParallelIterEnd end() { return {}; } |
232 | |
233 | private: |
234 | const GrFragmentProcessor& fInitialFP; |
235 | GrGLSLFragmentProcessor& fInitialGLSLFP; |
236 | }; |
237 | |
238 | protected: |
239 | /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces |
240 | the same stage key; this function reads data from a GrFragmentProcessor and uploads any |
241 | uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor |
242 | parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and |
243 | to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */ |
244 | virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} |
245 | |
246 | private: |
247 | // one per child; either not present or empty string if not yet emitted |
248 | SkTArray<SkString> fFunctionNames; |
249 | |
250 | SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; |
251 | |
252 | friend class GrFragmentProcessor; |
253 | }; |
254 | |
255 | #endif |
256 | |