blob: 2afdd099f4322abf2246bedb0181137159808df0 [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
joshualitt30ba4362014-08-21 20:18:45 -070011#include "GrGLFragmentShaderBuilder.h"
12#include "GrGLGeometryShaderBuilder.h"
13#include "GrGLVertexShaderBuilder.h"
joshualitt47bb3822014-10-07 16:43:25 -070014#include "../GrGLProgramDataManager.h"
15#include "../GrGLUniformHandle.h"
joshualitta5305a12014-10-10 17:47:00 -070016#include "../GrGLGeometryProcessor.h"
joshualitt89c7a2e2014-10-10 14:11:59 -070017
joshualitt47bb3822014-10-07 16:43:25 -070018/*
19 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
20 * NO data members because it is used in multiple interface inheritance.
21 * Heirarchy:
22 * GrGLUniformBuilder
23 * / \
24 * GrGLFPBuilder GrGLGPBuilder
25 * \ /
26 * GrGLProgramBuilder(internal use only)
27 */
28class GrGLUniformBuilder {
joshualitt30ba4362014-08-21 20:18:45 -070029public:
30 enum ShaderVisibility {
31 kVertex_Visibility = 0x1,
32 kGeometry_Visibility = 0x2,
33 kFragment_Visibility = 0x4,
34 };
35
joshualitt47bb3822014-10-07 16:43:25 -070036 virtual ~GrGLUniformBuilder() {}
37
joshualitt30ba4362014-08-21 20:18:45 -070038 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -070039
40 /** Add a uniform variable to the current program, that has visibility in one or more shaders.
41 visibility is a bitfield of ShaderVisibility values indicating from which shaders the
42 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
43 supported at this time. The actual uniform name will be mangled. If outName is not NULL then
44 it will refer to the final uniform name after return. Use the addUniformArray variant to add
45 an array of uniforms. */
46 virtual UniformHandle addUniform(uint32_t visibility,
47 GrSLType type,
48 const char* name,
49 const char** outName = NULL) = 0;
50 virtual UniformHandle addUniformArray(uint32_t visibility,
51 GrSLType type,
52 const char* name,
53 int arrayCount,
54 const char** outName = NULL) = 0;
55
56 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
57
58 /**
59 * Shortcut for getUniformVariable(u).c_str()
60 */
61 virtual const char* getUniformCStr(UniformHandle u) const = 0;
62
63 virtual const GrGLContextInfo& ctxInfo() const = 0;
64
65 virtual GrGpuGL* gpu() const = 0;
66
67 /*
68 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
69 */
70};
71
72/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
73class GrGLGPBuilder : public virtual GrGLUniformBuilder {
74public:
75 virtual void addVarying(GrSLType type,
76 const char* name,
77 const char** vsOutName = NULL,
78 const char** fsInName = NULL,
79 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
80
81 // TODO rename getFragmentBuilder
82 virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
83 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
84
85 /*
86 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
87 */
88};
89
90/* a specializations for FPs. Lets the user add uniforms and FS code */
91class GrGLFPBuilder : public virtual GrGLUniformBuilder {
92public:
93 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
94
95 /*
96 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
97 */
98};
99
joshualitta5305a12014-10-10 17:47:00 -0700100struct GrGLInstalledProc;
101struct GrGLInstalledGeoProc;
102struct GrGLInstalledFragProc;
103struct GrGLInstalledFragProcs;
104
joshualitt47bb3822014-10-07 16:43:25 -0700105/*
106 * Please note - no diamond problems because of virtual inheritance. Also, both base classes
107 * are pure virtual with no data members. This is the base class for program building.
108 * Subclasses are nearly identical but each has their own way of emitting transforms. State for
109 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
110 * respective builders
111*/
112class GrGLProgramBuilder : public GrGLGPBuilder,
113 public GrGLFPBuilder {
114public:
115 /** Generates a shader program.
116 *
117 * The program implements what is specified in the stages given as input.
118 * After successful generation, the builder result objects are available
119 * to be used.
120 * @return true if generation was successful.
121 */
122 static GrGLProgram* CreateProgram(const GrOptDrawState&,
123 const GrGLProgramDesc&,
124 GrGpu::DrawType,
joshualitt47bb3822014-10-07 16:43:25 -0700125 GrGpuGL* gpu);
126
127 virtual UniformHandle addUniform(uint32_t visibility,
128 GrSLType type,
129 const char* name,
130 const char** outName = NULL) SK_OVERRIDE {
131 return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
132 }
133 virtual UniformHandle addUniformArray(uint32_t visibility,
134 GrSLType type,
135 const char* name,
136 int arrayCount,
137 const char** outName = NULL) SK_OVERRIDE;
138
139 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
140 return fUniforms[u.toShaderBuilderIndex()].fVariable;
141 }
142
143 virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
144 return this->getUniformVariable(u).c_str();
145 }
146
147 virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
148
149 virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
150
joshualitt15988992014-10-09 15:04:05 -0700151 virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
joshualitt47bb3822014-10-07 16:43:25 -0700152 virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
153
joshualitta5305a12014-10-10 17:47:00 -0700154 virtual void addVarying(
155 GrSLType type,
156 const char* name,
157 const char** vsOutName = NULL,
158 const char** fsInName = NULL,
159 GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
joshualitt30ba4362014-08-21 20:18:45 -0700160
161 // Handles for program uniforms (other than per-effect uniforms)
162 struct BuiltinUniformHandles {
163 UniformHandle fViewMatrixUni;
164 UniformHandle fRTAdjustmentUni;
165 UniformHandle fColorUni;
166 UniformHandle fCoverageUni;
167
168 // We use the render target height to provide a y-down frag coord when specifying
169 // origin_upper_left is not supported.
170 UniformHandle fRTHeightUni;
171
172 // Uniforms for computing texture coords to do the dst-copy lookup
173 UniformHandle fDstCopyTopLeftUni;
174 UniformHandle fDstCopyScaleUni;
175 UniformHandle fDstCopySamplerUni;
176 };
177
joshualittdb0d3ca2014-10-07 12:42:26 -0700178protected:
joshualitta5305a12014-10-10 17:47:00 -0700179 typedef GrGLProgramDesc::ProcKeyProvider ProcKeyProvider;
180 typedef GrGLProgramDataManager::UniformInfo UniformInfo;
181 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
182
joshualitt47bb3822014-10-07 16:43:25 -0700183 static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
184 const GrOptDrawState&,
185 GrGpu::DrawType,
186 bool hasGeometryProcessor,
187 GrGpuGL*);
188
egdaniel307796b2014-10-06 12:13:54 -0700189 GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
joshualitt30ba4362014-08-21 20:18:45 -0700190
egdaniel307796b2014-10-06 12:13:54 -0700191 const GrOptDrawState& optState() const { return fOptState; }
joshualitt30ba4362014-08-21 20:18:45 -0700192 const GrGLProgramDesc& desc() const { return fDesc; }
joshualitt47bb3822014-10-07 16:43:25 -0700193 const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
joshualitt23e280d2014-09-18 12:26:38 -0700194
joshualitt30ba4362014-08-21 20:18:45 -0700195 // Generates a name for a variable. The generated string will be name prefixed by the prefix
196 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
197 // generating stage code.
198 void nameVariable(SkString* out, char prefix, const char* name);
joshualitt47bb3822014-10-07 16:43:25 -0700199 void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
joshualitta5305a12014-10-10 17:47:00 -0700200 void emitAndInstallProcs(const GrOptDrawState& optState,
201 GrGLSLExpr4* inputColor,
202 GrGLSLExpr4* inputCoverage);
203 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
204 template <class Proc>
205 void emitAndInstallProc(const Proc&,
206 int index,
207 const ProcKeyProvider,
208 const GrGLSLExpr4& input,
209 GrGLSLExpr4* output);
210
211 // these emit functions help to keep the createAndEmitProcessors template general
212 void emitAndInstallProc(const GrFragmentStage&,
213 const GrProcessorKey&,
214 const char* outColor,
215 const char* inColor);
216 void emitAndInstallProc(const GrGeometryProcessor&,
217 const GrProcessorKey&,
218 const char* outColor,
219 const char* inColor);
joshualitt47bb3822014-10-07 16:43:25 -0700220 void verify(const GrGeometryProcessor&);
221 void verify(const GrFragmentProcessor&);
222 void emitSamplers(const GrProcessor&,
223 GrGLProcessor::TextureSamplerArray* outSamplers,
joshualitta5305a12014-10-10 17:47:00 -0700224 GrGLInstalledProc*);
joshualitt30ba4362014-08-21 20:18:45 -0700225
joshualitt47bb3822014-10-07 16:43:25 -0700226 // each specific program builder has a distinct transform and must override this function
joshualitta5305a12014-10-10 17:47:00 -0700227 virtual void emitTransforms(const GrFragmentStage&,
joshualitt47bb3822014-10-07 16:43:25 -0700228 GrGLProcessor::TransformedCoordsArray* outCoords,
joshualitta5305a12014-10-10 17:47:00 -0700229 GrGLInstalledFragProc*);
joshualitt47bb3822014-10-07 16:43:25 -0700230 GrGLProgram* finalize();
231 void bindUniformLocations(GrGLuint programID);
232 bool checkLinkStatus(GrGLuint programID);
233 void resolveUniformLocations(GrGLuint programID);
joshualitt47bb3822014-10-07 16:43:25 -0700234 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
235 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
joshualitt30ba4362014-08-21 20:18:45 -0700236
joshualitt47bb3822014-10-07 16:43:25 -0700237 // Subclasses create different programs
238 virtual GrGLProgram* createProgram(GrGLuint programID);
239
joshualitt30ba4362014-08-21 20:18:45 -0700240 void appendUniformDecls(ShaderVisibility, SkString*) const;
241
joshualitt47bb3822014-10-07 16:43:25 -0700242 // reset is called by program creator between each processor's emit code. It increments the
243 // stage offset for variable name mangling, and also ensures verfication variables in the
244 // fragment shader are cleared.
245 void reset() {
246 this->enterStage();
247 this->addStage();
248 fFS.reset();
249 }
250 void addStage() { fStageIndex++; }
251
252 // This simple class exits the stage and then restores the stage when it goes out of scope
253 class AutoStageRestore {
joshualitt30ba4362014-08-21 20:18:45 -0700254 public:
joshualitt47bb3822014-10-07 16:43:25 -0700255 AutoStageRestore(GrGLProgramBuilder* pb)
256 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
257 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
joshualittb0a8a372014-09-23 09:50:21 -0700258 private:
joshualitt47bb3822014-10-07 16:43:25 -0700259 GrGLProgramBuilder* fPB;
260 bool fOutOfStage;
joshualittb0a8a372014-09-23 09:50:21 -0700261 };
joshualitt47bb3822014-10-07 16:43:25 -0700262 class AutoStageAdvance {
joshualittdb0d3ca2014-10-07 12:42:26 -0700263 public:
joshualitt47bb3822014-10-07 16:43:25 -0700264 AutoStageAdvance(GrGLProgramBuilder* pb) : fPB(pb) { fPB->reset(); }
265 ~AutoStageAdvance() { fPB->exitStage(); }
joshualittdb0d3ca2014-10-07 12:42:26 -0700266 private:
joshualitt47bb3822014-10-07 16:43:25 -0700267 GrGLProgramBuilder* fPB;
268 };
269 void exitStage() { fOutOfStage = true; }
270 void enterStage() { fOutOfStage = false; }
271 int stageIndex() const { return fStageIndex; }
272
joshualitt47bb3822014-10-07 16:43:25 -0700273 // number of each input/output type in a single allocation block, used by many builders
274 static const int kVarsPerBlock;
275
276 BuiltinUniformHandles fUniformHandles;
277 GrGLVertexBuilder fVS;
278 GrGLGeometryBuilder fGS;
279 GrGLFragmentShaderBuilder fFS;
280 bool fOutOfStage;
281 int fStageIndex;
282
joshualitta5305a12014-10-10 17:47:00 -0700283 GrGLInstalledGeoProc* fGeometryProcessor;
284 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
joshualitt47bb3822014-10-07 16:43:25 -0700285
286 const GrOptDrawState& fOptState;
287 const GrGLProgramDesc& fDesc;
288 GrGpuGL* fGpu;
289 UniformInfoArray fUniforms;
290
291 friend class GrGLShaderBuilder;
292 friend class GrGLVertexBuilder;
293 friend class GrGLFragmentShaderBuilder;
294 friend class GrGLGeometryBuilder;
295};
296
297/**
joshualitta5305a12014-10-10 17:47:00 -0700298 * The below structs represent processors installed in programs. All processors can have texture
299 * samplers, but only frag processors have coord transforms, hence the need for different structs
joshualitt47bb3822014-10-07 16:43:25 -0700300 */
joshualitta5305a12014-10-10 17:47:00 -0700301struct GrGLInstalledProc {
302 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
joshualitt47bb3822014-10-07 16:43:25 -0700303
joshualitta5305a12014-10-10 17:47:00 -0700304 struct Sampler {
305 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
306 UniformHandle fUniform;
307 int fTextureUnit;
308 };
309 SkSTArray<4, Sampler, true> fSamplers;
310};
joshualitt47bb3822014-10-07 16:43:25 -0700311
joshualitta5305a12014-10-10 17:47:00 -0700312struct GrGLInstalledGeoProc : public GrGLInstalledProc {
313 SkAutoTDelete<GrGLGeometryProcessor> fGLProc;
314};
joshualitt47bb3822014-10-07 16:43:25 -0700315
joshualitta5305a12014-10-10 17:47:00 -0700316struct GrGLInstalledFragProc : public GrGLInstalledProc {
317 GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {}
joshualitt47bb3822014-10-07 16:43:25 -0700318 class ShaderVarHandle {
319 public:
320 bool isValid() const { return fHandle > -1; }
321 ShaderVarHandle() : fHandle(-1) {}
322 ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
323 int handle() const { SkASSERT(this->isValid()); return fHandle; }
324 UniformHandle convertToUniformHandle() {
325 SkASSERT(this->isValid());
326 return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
327 }
joshualittdb0d3ca2014-10-07 12:42:26 -0700328
joshualitt47bb3822014-10-07 16:43:25 -0700329 private:
330 int fHandle;
331 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700332
joshualitt47bb3822014-10-07 16:43:25 -0700333 struct Transform {
334 Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
335 ShaderVarHandle fHandle;
336 SkMatrix fCurrentValue;
337 GrSLType fType;
338 };
joshualittdb0d3ca2014-10-07 12:42:26 -0700339
joshualitta5305a12014-10-10 17:47:00 -0700340 SkAutoTDelete<GrGLFragmentProcessor> fGLProc;
341 SkSTArray<2, Transform, true> fTransforms;
342 bool fLocalCoordAttrib;
343};
joshualittdb0d3ca2014-10-07 12:42:26 -0700344
joshualitta5305a12014-10-10 17:47:00 -0700345struct GrGLInstalledFragProcs : public SkRefCnt {
346 virtual ~GrGLInstalledFragProcs();
347 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
joshualitt30ba4362014-08-21 20:18:45 -0700348};
349
joshualitt30ba4362014-08-21 20:18:45 -0700350#endif