blob: f6397d8871bdbf4ac7e1f0a0afb105e4a98eb1d8 [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"
joshualittb0a8a372014-09-23 09:50:21 -070012#include "GrBackendProcessorFactory.h"
joshualitt30ba4362014-08-21 20:18:45 -070013#include "GrColor.h"
joshualittb0a8a372014-09-23 09:50:21 -070014#include "GrProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070015#include "GrGLFragmentShaderBuilder.h"
16#include "GrGLGeometryShaderBuilder.h"
17#include "GrGLVertexShaderBuilder.h"
18#include "SkTypes.h"
joshualittb0a8a372014-09-23 09:50:21 -070019#include "gl/GrGLProcessor.h"
joshualitt30ba4362014-08-21 20:18:45 -070020#include "gl/GrGLProgramDesc.h"
21#include "gl/GrGLProgramEffects.h"
22#include "gl/GrGLSL.h"
23#include "gl/GrGLProgramDataManager.h"
24
25#include <stdarg.h>
26
27class GrGLContextInfo;
joshualittb0a8a372014-09-23 09:50:21 -070028class GrProcessorStage;
joshualitt30ba4362014-08-21 20:18:45 -070029class GrGLProgramDesc;
30
31/**
32 Contains all the incremental state of a shader as it is being built,as well as helpers to
33 manipulate that state.
34*/
35class GrGLProgramBuilder {
36public:
37 enum ShaderVisibility {
38 kVertex_Visibility = 0x1,
39 kGeometry_Visibility = 0x2,
40 kFragment_Visibility = 0x4,
41 };
42
43 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
kkinnunenec56e452014-08-25 22:21:16 -070044 typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
joshualitt30ba4362014-08-21 20:18:45 -070045
46 // Handles for program uniforms (other than per-effect uniforms)
47 struct BuiltinUniformHandles {
48 UniformHandle fViewMatrixUni;
49 UniformHandle fRTAdjustmentUni;
50 UniformHandle fColorUni;
51 UniformHandle fCoverageUni;
52
53 // We use the render target height to provide a y-down frag coord when specifying
54 // origin_upper_left is not supported.
55 UniformHandle fRTHeightUni;
56
57 // Uniforms for computing texture coords to do the dst-copy lookup
58 UniformHandle fDstCopyTopLeftUni;
59 UniformHandle fDstCopyScaleUni;
60 UniformHandle fDstCopySamplerUni;
61 };
62
63 struct UniformInfo {
64 GrGLShaderVar fVariable;
65 uint32_t fVisibility;
66 GrGLint fLocation;
67 };
68
69 // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
70 // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
71 // name strings. Otherwise, we'd have to hand out copies.
72 typedef GrTAllocator<UniformInfo> UniformInfoArray;
73
kkinnunenec56e452014-08-25 22:21:16 -070074 struct SeparableVaryingInfo {
75 GrGLShaderVar fVariable;
76 GrGLint fLocation;
77 };
78
79 typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
80
joshualitt30ba4362014-08-21 20:18:45 -070081 /** Generates a shader program.
82 *
83 * The program implements what is specified in the stages given as input.
84 * After successful generation, the builder result objects are available
85 * to be used.
86 * @return true if generation was successful.
87 */
joshualittbd769d02014-09-04 08:56:46 -070088
joshualittb0a8a372014-09-23 09:50:21 -070089 bool genProgram(const GrGeometryStage* inGeometryProcessor,
90 const GrFragmentStage* inColorStages[],
91 const GrFragmentStage* inCoverageStages[]);
joshualitt30ba4362014-08-21 20:18:45 -070092
joshualittbd769d02014-09-04 08:56:46 -070093 GrGLProgramEffects* getGeometryProcessor() const {
94 SkASSERT(fProgramID); return fGeometryProcessor.get();
95 }
joshualitt30ba4362014-08-21 20:18:45 -070096 GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
97 GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
98 const BuiltinUniformHandles& getBuiltinUniformHandles() const {
99 SkASSERT(fProgramID);
100 return fUniformHandles;
101 }
102 GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
103 bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
104 int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
105 const UniformInfoArray& getUniformInfos() const { return fUniforms; }
kkinnunenec56e452014-08-25 22:21:16 -0700106 const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
107 return fSeparableVaryingInfos;
108 }
joshualitt30ba4362014-08-21 20:18:45 -0700109
110 virtual ~GrGLProgramBuilder() {}
111
112 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
113 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
114 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
115 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
116 it will refer to the final uniform name after return. Use the addUniformArray variant to add
117 an array of uniforms. */
118 GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
119 GrSLType type,
120 const char* name,
121 const char** outName = NULL) {
122 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
123 }
124 GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
125 GrSLType type,
126 const char* name,
127 int arrayCount,
128 const char** outName = NULL);
129
130 const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
131 return fUniforms[u.toShaderBuilderIndex()].fVariable;
132 }
133
134 /**
135 * Shortcut for getUniformVariable(u).c_str()
136 */
137 const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
138 return this->getUniformVariable(u).c_str();
139 }
140
141 const GrGLContextInfo& ctxInfo() const;
142
143 GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
kkinnunenec56e452014-08-25 22:21:16 -0700144 GrGpuGL* gpu() const { return fGpu; }
joshualitt30ba4362014-08-21 20:18:45 -0700145
146protected:
147 typedef GrTAllocator<GrGLShaderVar> VarArray;
148 GrGLProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);
149
joshualitt30ba4362014-08-21 20:18:45 -0700150 const GrGLProgramDesc& desc() const { return fDesc; }
151
152 // Helper for emitEffects().
joshualittb0a8a372014-09-23 09:50:21 -0700153 void createAndEmitEffects(const GrFragmentStage* effectStages[],
joshualitt30ba4362014-08-21 20:18:45 -0700154 int effectCnt,
155 const GrGLProgramDesc::EffectKeyProvider&,
156 GrGLSLExpr4* inOutFSColor);
157
joshualitt23e280d2014-09-18 12:26:38 -0700158 /*
159 * A helper function called to emit the geometry processor as well as individual coverage
160 * and color stages. this will call into subclasses emit effect
161 */
joshualittb0a8a372014-09-23 09:50:21 -0700162 void emitEffect(const GrProcessorStage& effectStage,
joshualitt23e280d2014-09-18 12:26:38 -0700163 int effectIndex,
164 const GrGLProgramDesc::EffectKeyProvider& keyProvider,
165 GrGLSLExpr4* inColor,
166 GrGLSLExpr4* outColor);
167
168 /**
169 * Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
170 * appends the necessary data to the TextureSamplerArray* object so effects can add texture
171 * lookups to their code. This method is only meant to be called during the construction phase.
172 */
joshualittb0a8a372014-09-23 09:50:21 -0700173 void emitSamplers(const GrProcessor& effect,
174 GrGLProcessor::TextureSamplerArray* outSamplers);
joshualitt23e280d2014-09-18 12:26:38 -0700175
joshualitt30ba4362014-08-21 20:18:45 -0700176 // Generates a name for a variable. The generated string will be name prefixed by the prefix
177 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
178 // generating stage code.
179 void nameVariable(SkString* out, char prefix, const char* name);
180
181 virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
182
183 virtual void bindProgramLocations(GrGLuint programId);
184 void resolveProgramLocations(GrGLuint programId);
185
186 void appendDecls(const VarArray&, SkString*) const;
187 void appendUniformDecls(ShaderVisibility, SkString*) const;
188
joshualitt30ba4362014-08-21 20:18:45 -0700189 class CodeStage : SkNoncopyable {
190 public:
191 CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
192
193 bool inStageCode() const {
194 this->validate();
bsalomon49f085d2014-09-05 13:34:00 -0700195 return SkToBool(fEffectStage);
joshualitt30ba4362014-08-21 20:18:45 -0700196 }
197
joshualittb0a8a372014-09-23 09:50:21 -0700198 const GrProcessorStage* effectStage() const {
joshualitt30ba4362014-08-21 20:18:45 -0700199 this->validate();
200 return fEffectStage;
201 }
202
203 int stageIndex() const {
204 this->validate();
205 return fCurrentIndex;
206 }
207
208 class AutoStageRestore : SkNoncopyable {
209 public:
joshualittb0a8a372014-09-23 09:50:21 -0700210 AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
bsalomon49f085d2014-09-05 13:34:00 -0700211 SkASSERT(codeStage);
joshualitt30ba4362014-08-21 20:18:45 -0700212 fSavedIndex = codeStage->fCurrentIndex;
213 fSavedEffectStage = codeStage->fEffectStage;
214
215 if (NULL == newStage) {
216 codeStage->fCurrentIndex = -1;
217 } else {
218 codeStage->fCurrentIndex = codeStage->fNextIndex++;
219 }
220 codeStage->fEffectStage = newStage;
221
222 fCodeStage = codeStage;
223 }
224 ~AutoStageRestore() {
225 fCodeStage->fCurrentIndex = fSavedIndex;
226 fCodeStage->fEffectStage = fSavedEffectStage;
227 }
228 private:
229 CodeStage* fCodeStage;
230 int fSavedIndex;
joshualittb0a8a372014-09-23 09:50:21 -0700231 const GrProcessorStage* fSavedEffectStage;
joshualitt30ba4362014-08-21 20:18:45 -0700232 };
233 private:
234 void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
235 int fNextIndex;
236 int fCurrentIndex;
joshualittb0a8a372014-09-23 09:50:21 -0700237 const GrProcessorStage* fEffectStage;
joshualitt23e280d2014-09-18 12:26:38 -0700238 };
239
joshualittb0a8a372014-09-23 09:50:21 -0700240 class GrGLProcessorEmitterInterface {
241 public:
242 virtual ~GrGLProcessorEmitterInterface() {}
243 virtual GrGLProcessor* createGLInstance() = 0;
244 virtual void emit(const GrProcessorKey& key,
245 const char* outColor,
246 const char* inColor,
247 const GrGLProcessor::TransformedCoordsArray& coords,
248 const GrGLProcessor::TextureSamplerArray& samplers) = 0;
249 };
250
251 class GrGLFragmentProcessorEmitter : public GrGLProcessorEmitterInterface {
252 public:
253 GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder)
254 : fBuilder(builder)
255 , fFragmentProcessor(NULL)
256 , fGLFragmentProcessor(NULL) {}
257 virtual ~GrGLFragmentProcessorEmitter() {}
258 void set(const GrFragmentProcessor* fp) {
259 SkASSERT(NULL == fFragmentProcessor);
260 fFragmentProcessor = fp;
261 }
262 virtual GrGLProcessor* createGLInstance() {
263 SkASSERT(fFragmentProcessor);
264 SkASSERT(NULL == fGLFragmentProcessor);
265 fGLFragmentProcessor =
266 fFragmentProcessor->getFactory().createGLInstance(*fFragmentProcessor);
267 return fGLFragmentProcessor;
268 }
269 virtual void emit(const GrProcessorKey& key,
270 const char* outColor,
271 const char* inColor,
272 const GrGLProcessor::TransformedCoordsArray& coords,
273 const GrGLProcessor::TextureSamplerArray& samplers) {
274 SkASSERT(fFragmentProcessor);
275 SkASSERT(fGLFragmentProcessor);
276 fGLFragmentProcessor->emitCode(fBuilder, *fFragmentProcessor, key, outColor, inColor,
277 coords, samplers);
278 // this will not leak because it hasa already been used by createGLInstance
279 fGLFragmentProcessor = NULL;
280 fFragmentProcessor = NULL;
281 }
282 private:
283 GrGLProgramBuilder* fBuilder;
284 const GrFragmentProcessor* fFragmentProcessor;
285 GrGLFragmentProcessor* fGLFragmentProcessor;
286 };
287
288 GrGLProcessorEmitterInterface* fEffectEmitter;
joshualitt23e280d2014-09-18 12:26:38 -0700289 CodeStage fCodeStage;
290 SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
291 SkAutoTUnref<GrGLProgramEffects> fColorEffects;
292 SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
293 BuiltinUniformHandles fUniformHandles;
294 bool fFragOnly;
295 int fTexCoordSetCnt;
296 GrGLuint fProgramID;
297 GrGLFragmentShaderBuilder fFS;
298 SeparableVaryingInfoArray fSeparableVaryingInfos;
joshualitt249af152014-09-15 11:41:13 -0700299
joshualittbd769d02014-09-04 08:56:46 -0700300private:
joshualittb0a8a372014-09-23 09:50:21 -0700301 virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
302 const GrFragmentStage* colorStages[],
303 const GrFragmentStage* coverageStages[],
joshualitt23e280d2014-09-18 12:26:38 -0700304 GrGLSLExpr4* inputColor,
305 GrGLSLExpr4* inputCoverage) = 0;
306 /*
307 * Subclasses override emitEffect below to emit data and code for a specific single effect
joshualitt30ba4362014-08-21 20:18:45 -0700308 */
joshualittb0a8a372014-09-23 09:50:21 -0700309 virtual void emitEffect(const GrProcessorStage&,
310 const GrProcessorKey&,
joshualitt23e280d2014-09-18 12:26:38 -0700311 const char* outColor,
312 const char* inColor,
313 int stageIndex) = 0;
joshualittbd769d02014-09-04 08:56:46 -0700314
315 /*
joshualitt23e280d2014-09-18 12:26:38 -0700316 * Because we have fragment only builders, and those builders need to implement a subclass
317 * of program effects, we have to have base classes overload the program effects here
joshualittbd769d02014-09-04 08:56:46 -0700318 */
joshualitt23e280d2014-09-18 12:26:38 -0700319 virtual GrGLProgramEffects* getProgramEffects() = 0;
joshualitt30ba4362014-08-21 20:18:45 -0700320
321 /**
322 * Compiles all the shaders, links them into a program, and writes the program id to the output
323 * struct.
324 **/
325 bool finish();
326
joshualittb0a8a372014-09-23 09:50:21 -0700327 GrGLFragmentProcessorEmitter fGrProcessorEmitter;
328
joshualitt30ba4362014-08-21 20:18:45 -0700329 const GrGLProgramDesc& fDesc;
330 GrGpuGL* fGpu;
331 UniformInfoArray fUniforms;
332
333 friend class GrGLShaderBuilder;
334 friend class GrGLVertexShaderBuilder;
335 friend class GrGLFragmentShaderBuilder;
336 friend class GrGLGeometryShaderBuilder;
337};
338
joshualitt30ba4362014-08-21 20:18:45 -0700339#endif