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 | int numToSkip = 0; |
58 | for (const auto& fp : GrFragmentProcessor::FPCRange(*fFP)) { |
59 | if (&fp == child) { |
60 | return BuilderInputProvider(child, fTs + numToSkip); |
61 | } |
62 | numToSkip += (fp.*COUNT)(); |
63 | } |
64 | SK_ABORT("Didn't find the child." ); |
65 | return {nullptr, nullptr}; |
66 | } |
67 | |
68 | private: |
69 | const GrFragmentProcessor* fFP; |
70 | const T* fTs; |
71 | }; |
72 | |
73 | public: |
74 | using TransformedCoordVars = BuilderInputProvider<GrGLSLPrimitiveProcessor::TransformVar, |
75 | &GrFragmentProcessor::numCoordTransforms>; |
76 | using TextureSamplers = |
77 | BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>; |
78 | |
79 | /** Called when the program stage should insert its code into the shaders. The code in each |
80 | shader will be in its own block ({}) and so locally scoped names will not collide across |
81 | stages. |
82 | |
83 | @param fragBuilder Interface used to emit code in the shaders. |
84 | @param fp The processor that generated this program stage. |
85 | @param key The key that was computed by GenKey() from the generating |
86 | GrProcessor. |
87 | @param outputColor A predefined half4 in the FS in which the stage should place its |
88 | output color (or coverage). |
89 | @param inputColor A half4 that holds the input color to the stage in the FS. This may |
90 | be nullptr in which case the fInputColor is set to "half4(1.0)" |
91 | (solid white) so this is guaranteed non-null. |
92 | TODO: Better system for communicating optimization info |
93 | (e.g. input color is solid white, trans black, known to be opaque, |
94 | etc.) that allows the processor to communicate back similar known |
95 | info about its output. |
96 | @param transformedCoords Fragment shader variables containing the coords computed using |
97 | each of the GrFragmentProcessor's GrCoordTransforms. |
98 | @param texSamplers Contains one entry for each TextureSampler of the GrProcessor. |
99 | These can be passed to the builder to emit texture reads in the |
100 | generated code. |
101 | */ |
102 | struct EmitArgs { |
103 | EmitArgs(GrGLSLFPFragmentBuilder* fragBuilder, |
104 | GrGLSLUniformHandler* uniformHandler, |
105 | const GrShaderCaps* caps, |
106 | const GrFragmentProcessor& fp, |
107 | const char* outputColor, |
108 | const char* inputColor, |
109 | const TransformedCoordVars& transformedCoordVars, |
110 | const TextureSamplers& textureSamplers) |
111 | : fFragBuilder(fragBuilder) |
112 | , fUniformHandler(uniformHandler) |
113 | , fShaderCaps(caps) |
114 | , fFp(fp) |
115 | , fOutputColor(outputColor) |
116 | , fInputColor(inputColor ? inputColor : "half4(1.0)" ) |
117 | , fTransformedCoords(transformedCoordVars) |
118 | , fTexSamplers(textureSamplers) {} |
119 | GrGLSLFPFragmentBuilder* fFragBuilder; |
120 | GrGLSLUniformHandler* fUniformHandler; |
121 | const GrShaderCaps* fShaderCaps; |
122 | const GrFragmentProcessor& fFp; |
123 | const char* fOutputColor; |
124 | const char* fInputColor; |
125 | const TransformedCoordVars& fTransformedCoords; |
126 | const TextureSamplers& fTexSamplers; |
127 | }; |
128 | |
129 | virtual void emitCode(EmitArgs&) = 0; |
130 | |
131 | // This does not recurse to any attached child processors. Recursing the entire processor tree |
132 | // is the responsibility of the caller. |
133 | void setData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor); |
134 | |
135 | int numChildProcessors() const { return fChildProcessors.count(); } |
136 | |
137 | GrGLSLFragmentProcessor* childProcessor(int index) const { return fChildProcessors[index]; } |
138 | |
139 | // Invoke the child with the default input color (solid white) |
140 | inline SkString invokeChild(int childIndex, EmitArgs& parentArgs, |
141 | SkSL::String skslCoords = "" ) { |
142 | return this->invokeChild(childIndex, nullptr, parentArgs, skslCoords); |
143 | } |
144 | |
145 | /** Invokes a child proc in its own scope. Pass in the parent's EmitArgs and invokeChild will |
146 | * automatically extract the coords and samplers of that child and pass them on to the child's |
147 | * emitCode(). Also, any uniforms or functions emitted by the child will have their names |
148 | * mangled to prevent redefinitions. The returned string contains the output color (as a call |
149 | * to the child's helper function). It is legal to pass nullptr as inputColor, since all |
150 | * fragment processors are required to work without an input color. |
151 | */ |
152 | SkString invokeChild(int childIndex, const char* inputColor, EmitArgs& parentArgs, |
153 | SkSL::String skslCoords = "" ); |
154 | |
155 | /** |
156 | * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of |
157 | * GLSLFPS. If initialized with an array color followed by coverage processors installed in a |
158 | * program thenthe iteration order will agree with a GrFragmentProcessor::Iter initialized with |
159 | * a GrPipeline that produces the same program key. |
160 | */ |
161 | class Iter { |
162 | public: |
163 | Iter(std::unique_ptr<GrGLSLFragmentProcessor> fps[], int cnt); |
164 | |
165 | GrGLSLFragmentProcessor& operator*() const; |
166 | GrGLSLFragmentProcessor* operator->() const; |
167 | Iter& operator++(); |
168 | operator bool() const { return !fFPStack.empty(); } |
169 | |
170 | // Because each iterator carries a stack we want to avoid copies. |
171 | Iter(const Iter&) = delete; |
172 | Iter& operator=(const Iter&) = delete; |
173 | |
174 | private: |
175 | SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; |
176 | }; |
177 | |
178 | protected: |
179 | /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces |
180 | the same stage key; this function reads data from a GrFragmentProcessor and uploads any |
181 | uniform variables required by the shaders created in emitCode(). The GrFragmentProcessor |
182 | parameter is guaranteed to be of the same type that created this GrGLSLFragmentProcessor and |
183 | to have an identical processor key as the one that created this GrGLSLFragmentProcessor. */ |
184 | virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {} |
185 | |
186 | private: |
187 | // one per child; either not present or empty string if not yet emitted |
188 | SkTArray<SkString> fFunctionNames; |
189 | |
190 | SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors; |
191 | |
192 | friend class GrFragmentProcessor; |
193 | }; |
194 | |
195 | #endif |
196 | |