blob: 6eaf575ba3f7d6a19b844b67daa09bd6b8707b97 [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 */
joshualittbd769d02014-09-04 08:56:46 -070087
88 bool genProgram(const GrEffectStage* inGeometryProcessor,
89 const GrEffectStage* inColorStages[],
joshualitt30ba4362014-08-21 20:18:45 -070090 const GrEffectStage* inCoverageStages[]);
91
joshualittbd769d02014-09-04 08:56:46 -070092 GrGLProgramEffects* getGeometryProcessor() const {
93 SkASSERT(fProgramID); return fGeometryProcessor.get();
94 }
joshualitt30ba4362014-08-21 20:18:45 -070095 GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
96 GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
97 const BuiltinUniformHandles& getBuiltinUniformHandles() const {
98 SkASSERT(fProgramID);
99 return fUniformHandles;
100 }
101 GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
102 bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
103 int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
104 const UniformInfoArray& getUniformInfos() const { return fUniforms; }
kkinnunenec56e452014-08-25 22:21:16 -0700105 const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
106 return fSeparableVaryingInfos;
107 }
joshualitt30ba4362014-08-21 20:18:45 -0700108
109 virtual ~GrGLProgramBuilder() {}
110
111 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
112 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
113 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
114 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
115 it will refer to the final uniform name after return. Use the addUniformArray variant to add
116 an array of uniforms. */
117 GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
118 GrSLType type,
119 const char* name,
120 const char** outName = NULL) {
121 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
122 }
123 GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
124 GrSLType type,
125 const char* name,
126 int arrayCount,
127 const char** outName = NULL);
128
129 const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
130 return fUniforms[u.toShaderBuilderIndex()].fVariable;
131 }
132
133 /**
134 * Shortcut for getUniformVariable(u).c_str()
135 */
136 const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
137 return this->getUniformVariable(u).c_str();
138 }
139
140 const GrGLContextInfo& ctxInfo() const;
141
142 GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
kkinnunenec56e452014-08-25 22:21:16 -0700143 GrGpuGL* gpu() const { return fGpu; }
joshualitt30ba4362014-08-21 20:18:45 -0700144
145protected:
146 typedef GrTAllocator<GrGLShaderVar> VarArray;
147 GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
148
joshualitt30ba4362014-08-21 20:18:45 -0700149 const GrGLProgramDesc& desc() const { return fDesc; }
150
151 // Helper for emitEffects().
152 void createAndEmitEffects(GrGLProgramEffectsBuilder*,
153 const GrEffectStage* effectStages[],
154 int effectCnt,
155 const GrGLProgramDesc::EffectKeyProvider&,
156 GrGLSLExpr4* inOutFSColor);
157
158 // Generates a name for a variable. The generated string will be name prefixed by the prefix
159 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
160 // generating stage code.
161 void nameVariable(SkString* out, char prefix, const char* name);
162
163 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
164
165 virtual void bindProgramLocations(GrGLuint programId);
166 void resolveProgramLocations(GrGLuint programId);
167
168 void appendDecls(const VarArray&, SkString*) const;
169 void appendUniformDecls(ShaderVisibility, SkString*) const;
170
joshualittbd769d02014-09-04 08:56:46 -0700171 SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
joshualitt30ba4362014-08-21 20:18:45 -0700172 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
173 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
174 BuiltinUniformHandles fUniformHandles;
175 bool fFragOnly;
176 int fTexCoordSetCnt;
177 GrGLuint fProgramID;
178 GrGLFragmentShaderBuilder fFS;
kkinnunenec56e452014-08-25 22:21:16 -0700179 SeparableVaryingInfoArray fSeparableVaryingInfos;
joshualittbd769d02014-09-04 08:56:46 -0700180
joshualitt30ba4362014-08-21 20:18:45 -0700181 class CodeStage : SkNoncopyable {
182 public:
183 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
184
185 bool inStageCode() const {
186 this->validate();
bsalomon49f085d2014-09-05 13:34:00 -0700187 return SkToBool(fEffectStage);
joshualitt30ba4362014-08-21 20:18:45 -0700188 }
189
190 const GrEffectStage* effectStage() const {
191 this->validate();
192 return fEffectStage;
193 }
194
195 int stageIndex() const {
196 this->validate();
197 return fCurrentIndex;
198 }
199
200 class AutoStageRestore : SkNoncopyable {
201 public:
202 AutoStageRestore(CodeStage* codeStage, const GrEffectStage* newStage) {
bsalomon49f085d2014-09-05 13:34:00 -0700203 SkASSERT(codeStage);
joshualitt30ba4362014-08-21 20:18:45 -0700204 fSavedIndex = codeStage->fCurrentIndex;
205 fSavedEffectStage = codeStage->fEffectStage;
206
207 if (NULL == newStage) {
208 codeStage->fCurrentIndex = -1;
209 } else {
210 codeStage->fCurrentIndex = codeStage->fNextIndex++;
211 }
212 codeStage->fEffectStage = newStage;
213
214 fCodeStage = codeStage;
215 }
216 ~AutoStageRestore() {
217 fCodeStage->fCurrentIndex = fSavedIndex;
218 fCodeStage->fEffectStage = fSavedEffectStage;
219 }
220 private:
221 CodeStage* fCodeStage;
222 int fSavedIndex;
223 const GrEffectStage* fSavedEffectStage;
224 };
225 private:
226 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
227 int fNextIndex;
228 int fCurrentIndex;
229 const GrEffectStage* fEffectStage;
230 } fCodeStage;
joshualitt249af152014-09-15 11:41:13 -0700231
joshualittbd769d02014-09-04 08:56:46 -0700232private:
joshualitt30ba4362014-08-21 20:18:45 -0700233
234 /**
235 * The base class will emit the fragment code that precedes the per-effect code and then call
236 * this function. The subclass can use it to insert additional fragment code that should
237 * execute before the effects' code and/or emit other shaders (e.g. geometry, vertex).
238 *
239 * The subclass can modify the initial color or coverage
240 */
joshualittbd769d02014-09-04 08:56:46 -0700241 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
242 GrGLSLExpr4* coverage) = 0;
243
244 /*
245 * Full shader builder needs to emit code after the color stages and before the coverage stages
246 */
247 virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
248 GrGLSLExpr4* coverage) = 0;
joshualitt30ba4362014-08-21 20:18:45 -0700249
250 /**
251 * Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
252 * deleting it when finished. effectStages contains the effects to add. The effect key provider
253 * is used to communicate the key each effect created in its GenKey function. inOutFSColor
254 * specifies the input color to the first stage and is updated to be the output color of the
255 * last stage. The handles to texture samplers for effectStage[i] are added to
256 * effectSamplerHandles[i].
257 */
258 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
259 int effectCnt,
260 const GrGLProgramDesc::EffectKeyProvider&,
261 GrGLSLExpr4* inOutFSColor) = 0;
262
263 /**
264 * Similar to emitCodeBeforeEffects() but called after per-effect code is emitted.
265 */
266 virtual void emitCodeAfterEffects() = 0;
267
268 /**
269 * Compiles all the shaders, links them into a program, and writes the program id to the output
270 * struct.
271 **/
272 bool finish();
273
274 const GrGLProgramDesc& fDesc;
275 GrGpuGL* fGpu;
276 UniformInfoArray fUniforms;
277
278 friend class GrGLShaderBuilder;
279 friend class GrGLVertexShaderBuilder;
280 friend class GrGLFragmentShaderBuilder;
281 friend class GrGLGeometryShaderBuilder;
282};
283
284////////////////////////////////////////////////////////////////////////////////
285
286class GrGLFullProgramBuilder : public GrGLProgramBuilder {
287public:
288 GrGLFullProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
289
290 /** Add a varying variable to the current program to pass values between vertex and fragment
291 shaders. If the last two parameters are non-NULL, they are filled in with the name
292 generated. */
293 void addVarying(GrSLType type,
294 const char* name,
295 const char** vsOutName = NULL,
egdaniel6db91282014-09-02 08:02:38 -0700296 const char** fsInName = NULL,
297 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
joshualitt30ba4362014-08-21 20:18:45 -0700298
kkinnunenec56e452014-08-25 22:21:16 -0700299 /** Add a separable varying input variable to the current program.
300 * A separable varying (fragment shader input) is a varying that can be used also when vertex
301 * shaders are not used. With a vertex shader, the operation is same as with other
302 * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
303 * populate the variable. The APIs can refer to the variable through the returned handle.
304 */
305 VaryingHandle addSeparableVarying(GrSLType type,
306 const char* name,
307 const char** vsOutName,
308 const char** fsInName);
309
joshualitt30ba4362014-08-21 20:18:45 -0700310 GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
311
312private:
joshualittbd769d02014-09-04 08:56:46 -0700313 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
314 GrGLSLExpr4* coverage) SK_OVERRIDE;
315
316 virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
317 GrGLSLExpr4* coverage) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700318
319 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
320 int effectCnt,
321 const GrGLProgramDesc::EffectKeyProvider&,
322 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
323
joshualittbd769d02014-09-04 08:56:46 -0700324 /*
325 * These functions are temporary and will eventually operate not on effects but on
326 * geometry processors
327 */
328 void createAndEmitEffect(GrGLProgramEffectsBuilder*,
329 const GrEffectStage* effectStage,
330 const GrGLProgramDesc::EffectKeyProvider&,
331 GrGLSLExpr4* inOutFSColor);
332
333 GrGLProgramEffects* createAndEmitEffect(const GrEffectStage* geometryProcessor,
334 const GrGLProgramDesc::EffectKeyProvider&,
335 GrGLSLExpr4* inOutFSColor);
336
joshualitt30ba4362014-08-21 20:18:45 -0700337 virtual void emitCodeAfterEffects() SK_OVERRIDE;
338
339 virtual bool compileAndAttachShaders(GrGLuint programId,
340 SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
341
342 virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
343
344 GrGLGeometryShaderBuilder fGS;
345 GrGLVertexShaderBuilder fVS;
346
347 typedef GrGLProgramBuilder INHERITED;
348};
349
350////////////////////////////////////////////////////////////////////////////////
351
352class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder {
353public:
354 GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
355
356 int addTexCoordSets(int count);
357
358private:
joshualittbd769d02014-09-04 08:56:46 -0700359 virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
360 GrGLSLExpr4* coverage) SK_OVERRIDE {}
361
362 virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
363 GrGLSLExpr4* coverage) SK_OVERRIDE {
364 SkASSERT(NULL == geometryProcessor);
365 }
joshualitt30ba4362014-08-21 20:18:45 -0700366
367 virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
368 int effectCnt,
369 const GrGLProgramDesc::EffectKeyProvider&,
370 GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
371
372 virtual void emitCodeAfterEffects() SK_OVERRIDE {}
373
374 typedef GrGLProgramBuilder INHERITED;
375};
376
377#endif