blob: d1af63fc4ee3fa5369274480fee71bf7232bed81 [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
2 * Copyright 2014 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 GrGLProgramBuilder_DEFINED
9#define GrGLProgramBuilder_DEFINED
10
11#include "GrAllocator.h"
12#include "GrBackendEffectFactory.h"
13#include "GrColor.h"
14#include "GrEffect.h"
15#include "GrGLFragmentShaderBuilder.h"
16#include "GrGLGeometryShaderBuilder.h"
17#include "GrGLVertexShaderBuilder.h"
18#include "SkTypes.h"
19#include "gl/GrGLProgramDesc.h"
20#include "gl/GrGLProgramEffects.h"
21#include "gl/GrGLSL.h"
22#include "gl/GrGLProgramDataManager.h"
23
24#include <stdarg.h>
25
26class GrGLContextInfo;
27class GrEffectStage;
28class GrGLProgramDesc;
29
30/**
31 Contains all the incremental state of a shader as it is being built,as well as helpers to
32 manipulate that state.
33*/
34class GrGLProgramBuilder {
35public:
36 enum ShaderVisibility {
37 kVertex_Visibility = 0x1,
38 kGeometry_Visibility = 0x2,
39 kFragment_Visibility = 0x4,
40 };
41
42 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
kkinnunenec56e452014-08-25 22:21:16 -070043 typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
joshualitt30ba4362014-08-21 20:18:45 -070044
45 // Handles for program uniforms (other than per-effect uniforms)
46 struct BuiltinUniformHandles {
47 UniformHandle fViewMatrixUni;
48 UniformHandle fRTAdjustmentUni;
49 UniformHandle fColorUni;
50 UniformHandle fCoverageUni;
51
52 // We use the render target height to provide a y-down frag coord when specifying
53 // origin_upper_left is not supported.
54 UniformHandle fRTHeightUni;
55
56 // Uniforms for computing texture coords to do the dst-copy lookup
57 UniformHandle fDstCopyTopLeftUni;
58 UniformHandle fDstCopyScaleUni;
59 UniformHandle fDstCopySamplerUni;
60 };
61
62 struct UniformInfo {
63 GrGLShaderVar fVariable;
64 uint32_t fVisibility;
65 GrGLint fLocation;
66 };
67
68 // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
69 // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
70 // name strings. Otherwise, we'd have to hand out copies.
71 typedef GrTAllocator<UniformInfo> UniformInfoArray;
72
kkinnunenec56e452014-08-25 22:21:16 -070073 struct SeparableVaryingInfo {
74 GrGLShaderVar fVariable;
75 GrGLint fLocation;
76 };
77
78 typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
79
joshualitt30ba4362014-08-21 20:18:45 -070080 /** Generates a shader program.
81 *
82 * The program implements what is specified in the stages given as input.
83 * After successful generation, the builder result objects are available
84 * to be used.
85 * @return true if generation was successful.
86 */
87 bool genProgram(const GrEffectStage* inColorStages[],
88 const GrEffectStage* inCoverageStages[]);
89
90 // Below are the results of the shader generation.
91
92 GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
93 GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
94 const BuiltinUniformHandles& getBuiltinUniformHandles() const {
95 SkASSERT(fProgramID);
96 return fUniformHandles;
97 }
98 GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
99 bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
100 int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
101 const UniformInfoArray& getUniformInfos() const { return fUniforms; }
kkinnunenec56e452014-08-25 22:21:16 -0700102 const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
103 return fSeparableVaryingInfos;
104 }
joshualitt30ba4362014-08-21 20:18:45 -0700105
106 virtual ~GrGLProgramBuilder() {}
107
108 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
109 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
110 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
111 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
112 it will refer to the final uniform name after return. Use the addUniformArray variant to add
113 an array of uniforms. */
114 GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
115 GrSLType type,
116 const char* name,
117 const char** outName = NULL) {
118 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
119 }
120 GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
121 GrSLType type,
122 const char* name,
123 int arrayCount,
124 const char** outName = NULL);
125
126 const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
127 return fUniforms[u.toShaderBuilderIndex()].fVariable;
128 }
129
130 /**
131 * Shortcut for getUniformVariable(u).c_str()
132 */
133 const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
134 return this->getUniformVariable(u).c_str();
135 }
136
137 const GrGLContextInfo& ctxInfo() const;
138
139 GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
kkinnunenec56e452014-08-25 22:21:16 -0700140 GrGpuGL* gpu() const { return fGpu; }
joshualitt30ba4362014-08-21 20:18:45 -0700141
142protected:
143 typedef GrTAllocator<GrGLShaderVar> VarArray;
144 GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
145
joshualitt30ba4362014-08-21 20:18:45 -0700146 const GrGLProgramDesc& desc() const { return fDesc; }
147
148 // Helper for emitEffects().
149 void createAndEmitEffects(GrGLProgramEffectsBuilder*,
150 const GrEffectStage* effectStages[],
151 int effectCnt,
152 const GrGLProgramDesc::EffectKeyProvider&,
153 GrGLSLExpr4* inOutFSColor);
154
155 // Generates a name for a variable. The generated string will be name prefixed by the prefix
156 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
157 // generating stage code.
158 void nameVariable(SkString* out, char prefix, const char* name);
159
160 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
161
162 virtual void bindProgramLocations(GrGLuint programId);
163 void resolveProgramLocations(GrGLuint programId);
164
165 void appendDecls(const VarArray&, SkString*) const;
166 void appendUniformDecls(ShaderVisibility, SkString*) const;
167
168 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
169 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
170 BuiltinUniformHandles fUniformHandles;
171 bool fFragOnly;
172 int fTexCoordSetCnt;
173 GrGLuint fProgramID;
174 GrGLFragmentShaderBuilder fFS;
kkinnunenec56e452014-08-25 22:21:16 -0700175 SeparableVaryingInfoArray fSeparableVaryingInfos;
joshualitt30ba4362014-08-21 20:18:45 -0700176private:
177 class CodeStage : SkNoncopyable {
178 public:
179 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
180
181 bool inStageCode() const {
182 this->validate();
183 return NULL != fEffectStage;
184 }
185
186 const GrEffectStage* effectStage() const {
187 this->validate();
188 return fEffectStage;
189 }
190
191 int stageIndex() const {
192 this->validate();
193 return fCurrentIndex;
194 }
195
196 class AutoStageRestore : SkNoncopyable {
197 public:
198 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
199 SkASSERT(NULL != codeStage);
200 fSavedIndex = codeStage->fCurrentIndex;
201 fSavedEffectStage = codeStage->fEffectStage;
202
203 if (NULL == newStage) {
204 codeStage->fCurrentIndex = -1;
205 } else {
206 codeStage->fCurrentIndex = codeStage->fNextIndex++;
207 }
208 codeStage->fEffectStage = newStage;
209
210 fCodeStage = codeStage;
211 }
212 ~AutoStageRestore() {
213 fCodeStage->fCurrentIndex = fSavedIndex;
214 fCodeStage->fEffectStage = fSavedEffectStage;
215 }
216 private:
217 CodeStage* fCodeStage;
218 int fSavedIndex;
219 const GrEffectStage* fSavedEffectStage;
220 };
221 private:
222 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
223 int fNextIndex;
224 int fCurrentIndex;
225 const GrEffectStage* fEffectStage;
226 } fCodeStage;
227
228 /**
229 * The base class will emit the fragment code that precedes the per-effect code and then call
230 * this function. The subclass can use it to insert additional fragment code that should
231 * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
232 *
233 * The subclass can modify the initial color or coverage
234 */
235 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;
236
237 /**
238 * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
239 * deleting it when finished. effectStages contains the effects to add. The effect key provider
240 * is used to communicate the key each effect created in its GenKey function. inOutFSColor
241 * specifies the input color to the first stage and is updated to be the output color of the
242 * last stage. The handles to texture samplers for effectStage[i] are added to
243 * effectSamplerHandles[i].
244 */
245 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
246 int effectCnt,
247 const GrGLProgramDesc::EffectKeyProvider&,
248 GrGLSLExpr4* inOutFSColor) = 0;
249
250 /**
251 * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
252 */
253 virtual void emitCodeAfterEffects() = 0;
254
255 /**
256 * Compiles all the shaders, links them into a program, and writes the program id to the output
257 * struct.
258 **/
259 bool finish();
260
261 const GrGLProgramDesc& fDesc;
262 GrGpuGL* fGpu;
263 UniformInfoArray fUniforms;
264
265 friend class GrGLShaderBuilder;
266 friend class GrGLVertexShaderBuilder;
267 friend class GrGLFragmentShaderBuilder;
268 friend class GrGLGeometryShaderBuilder;
269};
270
271////////////////////////////////////////////////////////////////////////////////
272
273class GrGLFullProgramBuilder : public GrGLProgramBuilder {
274public:
275 GrGLFullProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
276
277 /** Add a varying variable to the current program to pass values between vertex and fragment
278 shaders. If the last two parameters are non-NULL, they are filled in with the name
279 generated. */
280 void addVarying(GrSLType type,
281 const char* name,
282 const char** vsOutName = NULL,
283 const char** fsInName = NULL);
284
kkinnunenec56e452014-08-25 22:21:16 -0700285 /** Add a separable varying input variable to the current program.
286 * A separable varying (fragment shader input) is a varying that can be used also when vertex
287 * shaders are not used. With a vertex shader, the operation is same as with other
288 * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
289 * populate the variable. The APIs can refer to the variable through the returned handle.
290 */
291 VaryingHandle addSeparableVarying(GrSLType type,
292 const char* name,
293 const char** vsOutName,
294 const char** fsInName);
295
joshualitt30ba4362014-08-21 20:18:45 -0700296 GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
297
298private:
299 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
300
301 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
302 int effectCnt,
303 const GrGLProgramDesc::EffectKeyProvider&,
304 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
305
306 virtual void emitCodeAfterEffects() SK_OVERRIDE;
307
308 virtual bool compileAndAttachShaders(GrGLuint programId,
309 SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
310
311 virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
312
313 GrGLGeometryShaderBuilder fGS;
314 GrGLVertexShaderBuilder fVS;
315
316 typedef GrGLProgramBuilder INHERITED;
317};
318
319////////////////////////////////////////////////////////////////////////////////
320
321class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder {
322public:
323 GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
324
325 int addTexCoordSets(int count);
326
327private:
328 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
329
330 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
331 int effectCnt,
332 const GrGLProgramDesc::EffectKeyProvider&,
333 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
334
335 virtual void emitCodeAfterEffects() SK_OVERRIDE {}
336
337 typedef GrGLProgramBuilder INHERITED;
338};
339
340#endif