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
18class GrProcessor;
19class GrProcessorKeyBuilder;
20class GrGLSLFPBuilder;
21class GrGLSLFPFragmentBuilder;
22
23class GrGLSLFragmentProcessor {
24public:
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
36private:
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
74public:
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
238protected:
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
246private:
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