C++11 override should now be supported by all of {bots,Chrome,Android,Mozilla}
[platform/upstream/libSkiaSharp.git] / src / gpu / gl / builders / GrGLProgramBuilder.h
1 /*
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 "GrGLFragmentShaderBuilder.h"
12 #include "GrGLGeometryShaderBuilder.h"
13 #include "GrGLVertexShaderBuilder.h"
14 #include "../GrGLProgramDataManager.h"
15 #include "../GrGLUniformHandle.h"
16 #include "../GrGLPrimitiveProcessor.h"
17 #include "../GrGLXferProcessor.h"
18 #include "../../GrPendingFragmentStage.h"
19 #include "../../GrPipeline.h"
20
21 /*
22  * This is the base class for a series of interfaces.  This base class *MUST* remain abstract with
23  * NO data members because it is used in multiple interface inheritance.
24  * Heirarchy:
25  *                      GrGLUniformBuilder
26  *                     /                  \
27  *                GrGLFPBuilder       GrGLGPBuilder
28  *                     \                  /
29  *                     GrGLProgramBuilder(internal use only)
30  */
31 class GrGLUniformBuilder {
32 public:
33     enum ShaderVisibility {
34         kVertex_Visibility   = 1 << kVertex_GrShaderType,
35         kGeometry_Visibility = 1 << kGeometry_GrShaderType,
36         kFragment_Visibility = 1 << kFragment_GrShaderType,
37     };
38
39     virtual ~GrGLUniformBuilder() {}
40
41     typedef GrGLProgramDataManager::UniformHandle UniformHandle;
42
43     /** Add a uniform variable to the current program, that has visibility in one or more shaders.
44         visibility is a bitfield of ShaderVisibility values indicating from which shaders the
45         uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
46         supported at this time. The actual uniform name will be mangled. If outName is not NULL then
47         it will refer to the final uniform name after return. Use the addUniformArray variant to add
48         an array of uniforms. */
49     UniformHandle addUniform(uint32_t visibility,
50                              GrSLType type,
51                              GrSLPrecision precision,
52                              const char* name,
53                              const char** outName = NULL) {
54         return this->addUniformArray(visibility, type, precision, name, 0, outName);
55     }
56
57     virtual UniformHandle addUniformArray(
58         uint32_t visibility,
59         GrSLType type,
60         GrSLPrecision precision,
61         const char* name,
62         int arrayCount,
63         const char** outName = NULL) = 0;
64
65     virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
66
67     /**
68      * Shortcut for getUniformVariable(u).c_str()
69      */
70     virtual const char* getUniformCStr(UniformHandle u) const = 0;
71
72     virtual const GrGLContextInfo& ctxInfo() const = 0;
73
74     virtual GrGLGpu* gpu() const = 0;
75
76     /*
77      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
78      */
79 };
80
81 // TODO move this into GrGLGPBuilder and move them both out of this file
82 class GrGLVarying {
83 public:
84     bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
85                                     kVertToGeo_Varying == fVarying; }
86     bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
87                                     kGeoToFrag_Varying == fVarying; }
88     const char* vsOut() const { return fVsOut; }
89     const char* gsIn() const { return fGsIn; }
90     const char* gsOut() const { return fGsOut; }
91     const char* fsIn() const { return fFsIn; }
92     GrSLType type() const { return fType; }
93
94 protected:
95     enum Varying {
96         kVertToFrag_Varying,
97         kVertToGeo_Varying,
98         kGeoToFrag_Varying,
99     };
100
101     GrGLVarying(GrSLType type, Varying varying)
102         : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL),
103           fFsIn(NULL) {}
104
105     Varying fVarying;
106
107 private:
108     GrSLType fType;
109     const char* fVsOut;
110     const char* fGsIn;
111     const char* fGsOut;
112     const char* fFsIn;
113
114     friend class GrGLVertexBuilder;
115     friend class GrGLGeometryBuilder;
116     friend class GrGLXferBuilder;
117     friend class GrGLFragmentShaderBuilder;
118 };
119
120 struct GrGLVertToFrag : public GrGLVarying {
121     GrGLVertToFrag(GrSLType type)
122         : GrGLVarying(type, kVertToFrag_Varying) {}
123 };
124
125 struct GrGLVertToGeo : public GrGLVarying {
126     GrGLVertToGeo(GrSLType type)
127         : GrGLVarying(type, kVertToGeo_Varying) {}
128 };
129
130 struct GrGLGeoToFrag : public GrGLVarying {
131     GrGLGeoToFrag(GrSLType type)
132         : GrGLVarying(type, kGeoToFrag_Varying) {}
133 };
134
135 /* a specialization of the above for GPs.  Lets the user add uniforms, varyings, and VS / FS code */
136 class GrGLGPBuilder : public virtual GrGLUniformBuilder {
137 public:
138     /*
139      * addVarying allows fine grained control for setting up varyings between stages.  If you just
140      * need to take an attribute and pass it through to an output value in a fragment shader, use
141      * addPassThroughAttribute.
142      * TODO convert most uses of addVarying to addPassThroughAttribute
143      */
144     virtual void addVarying(const char* name,
145                             GrGLVarying*,
146                             GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0;
147
148     /*
149      * This call can be used by GP to pass an attribute through all shaders directly to 'output' in
150      * the fragment shader.  Though this call effects both the vertex shader and fragment shader,
151      * it expects 'output' to be defined in the fragment shader before this call is made.
152      * TODO it might be nicer behavior to have a flag to declare output inside this call
153      */
154     virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*,
155                                          const char* output) = 0;
156
157     // TODO rename getFragmentBuilder
158     virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
159     virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
160
161     /*
162      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
163      */
164 };
165
166 /* a specializations for FPs. Lets the user add uniforms and FS code */
167 class GrGLFPBuilder : public virtual GrGLUniformBuilder {
168 public:
169     virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
170
171     /*
172      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
173      */
174 };
175
176 /* a specializations for XPs. Lets the user add uniforms and FS code */
177 class GrGLXPBuilder : public virtual GrGLUniformBuilder {
178 public:
179     virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
180
181     /*
182      * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
183      */
184 };
185
186 /**
187  * The below struct represent processors installed in programs.
188  */
189 template <class Proc>
190 struct GrGLInstalledProc {
191      typedef GrGLProgramDataManager::UniformHandle UniformHandle;
192
193      struct Sampler {
194          SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
195          UniformHandle  fUniform;
196          int            fTextureUnit;
197      };
198      SkSTArray<4, Sampler, true> fSamplers;
199      SkAutoTDelete<Proc> fGLProc;
200 };
201
202 typedef GrGLInstalledProc<GrGLPrimitiveProcessor> GrGLInstalledGeoProc;
203 typedef GrGLInstalledProc<GrGLXferProcessor> GrGLInstalledXferProc;
204 typedef GrGLInstalledProc<GrGLFragmentProcessor> GrGLInstalledFragProc;
205
206 struct GrGLInstalledFragProcs : public SkRefCnt {
207     virtual ~GrGLInstalledFragProcs();
208     SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
209 };
210
211 /*
212  * Please note - no diamond problems because of virtual inheritance.  Also, both base classes
213  * are pure virtual with no data members.  This is the base class for program building.
214  * Subclasses are nearly identical but each has their own way of emitting transforms.  State for
215  * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
216  * respective builders
217 */
218 class GrGLProgramBuilder : public GrGLGPBuilder,
219                            public GrGLFPBuilder,
220                            public GrGLXPBuilder {
221 public:
222     typedef GrGpu::DrawArgs DrawArgs;
223     /** Generates a shader program.
224      *
225      * The program implements what is specified in the stages given as input.
226      * After successful generation, the builder result objects are available
227      * to be used.
228      * @return true if generation was successful.
229      */
230     static GrGLProgram* CreateProgram(const DrawArgs&, GrGLGpu*);
231
232     UniformHandle addUniformArray(uint32_t visibility,
233                                   GrSLType type,
234                                   GrSLPrecision precision,
235                                   const char* name,
236                                   int arrayCount,
237                                   const char** outName) override;
238
239     const GrGLShaderVar& getUniformVariable(UniformHandle u) const override {
240         return fUniforms[u.toShaderBuilderIndex()].fVariable;
241     }
242
243     const char* getUniformCStr(UniformHandle u) const override {
244         return this->getUniformVariable(u).c_str();
245     }
246
247     const GrGLContextInfo& ctxInfo() const override;
248
249     GrGLGpu* gpu() const override { return fGpu; }
250
251     GrGLFPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; }
252     GrGLVertexBuilder* getVertexShaderBuilder() override { return &fVS; }
253
254     void addVarying(
255             const char* name,
256             GrGLVarying*,
257             GrSLPrecision fsPrecision = kDefault_GrSLPrecision) override;
258
259     void addPassThroughAttribute(const GrPrimitiveProcessor::Attribute*,
260                                  const char* output) override;
261
262
263     // Handles for program uniforms (other than per-effect uniforms)
264     struct BuiltinUniformHandles {
265         UniformHandle       fRTAdjustmentUni;
266
267         // We use the render target height to provide a y-down frag coord when specifying
268         // origin_upper_left is not supported.
269         UniformHandle       fRTHeightUni;
270     };
271
272 protected:
273     typedef GrGLProgramDataManager::UniformInfo UniformInfo;
274     typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
275
276     static GrGLProgramBuilder* CreateProgramBuilder(const DrawArgs&, GrGLGpu*);
277
278     GrGLProgramBuilder(GrGLGpu*, const DrawArgs&);
279
280     const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
281     const GrPipeline& pipeline() const { return *fArgs.fPipeline; }
282     const GrProgramDesc& desc() const { return *fArgs.fDesc; }
283     const GrBatchTracker& batchTracker() const { return *fArgs.fBatchTracker; }
284     const GrProgramDesc::KeyHeader& header() const { return fArgs.fDesc->header(); }
285
286     // Generates a name for a variable. The generated string will be name prefixed by the prefix
287     // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
288     // generating stage code.
289     void nameVariable(SkString* out, char prefix, const char* name);
290     // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
291     // If GrGLSLExpr4 has a valid name then it will use that instead
292     void nameExpression(GrGLSLExpr4*, const char* baseName);
293     void emitAndInstallProcs(GrGLSLExpr4* inputColor,
294                              GrGLSLExpr4* inputCoverage);
295     void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
296     void emitAndInstallProc(const GrPendingFragmentStage&,
297                             int index,
298                             const GrGLSLExpr4& input,
299                             GrGLSLExpr4* output);
300
301     void emitAndInstallProc(const GrPrimitiveProcessor&,
302                             GrGLSLExpr4* outputColor,
303                             GrGLSLExpr4* outputCoverage);
304
305     // these emit functions help to keep the createAndEmitProcessors template general
306     void emitAndInstallProc(const GrPendingFragmentStage&,
307                             int index,
308                             const char* outColor,
309                             const char* inColor);
310     void emitAndInstallProc(const GrPrimitiveProcessor&,
311                             const char* outColor,
312                             const char* outCoverage);
313     void emitAndInstallXferProc(const GrXferProcessor&,
314                                 const GrGLSLExpr4& colorIn,
315                                 const GrGLSLExpr4& coverageIn);
316
317     void verify(const GrPrimitiveProcessor&);
318     void verify(const GrXferProcessor&);
319     void verify(const GrFragmentProcessor&);
320     template <class Proc>
321     void emitSamplers(const GrProcessor&,
322                       GrGLProcessor::TextureSamplerArray* outSamplers,
323                       GrGLInstalledProc<Proc>*);
324
325     GrGLProgram* finalize();
326     void bindUniformLocations(GrGLuint programID);
327     bool checkLinkStatus(GrGLuint programID);
328     void resolveUniformLocations(GrGLuint programID);
329     void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
330     void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
331
332     // Subclasses create different programs
333     virtual GrGLProgram* createProgram(GrGLuint programID);
334
335     void appendUniformDecls(ShaderVisibility, SkString*) const;
336
337     // reset is called by program creator between each processor's emit code.  It increments the
338     // stage offset for variable name mangling, and also ensures verfication variables in the
339     // fragment shader are cleared.
340     void reset() {
341         this->enterStage();
342         this->addStage();
343         fFS.reset();
344     }
345     void addStage() { fStageIndex++; }
346
347     // This simple class exits the stage and then restores the stage when it goes out of scope
348     class AutoStageRestore {
349     public:
350         AutoStageRestore(GrGLProgramBuilder* pb)
351             : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
352         ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
353     private:
354         GrGLProgramBuilder* fPB;
355         bool fOutOfStage;
356     };
357     class AutoStageAdvance {
358     public:
359         AutoStageAdvance(GrGLProgramBuilder* pb)
360             : fPB(pb) {
361             fPB->reset();
362             // Each output to the fragment processor gets its own code section
363             fPB->fFS.nextStage();
364         }
365         ~AutoStageAdvance() { fPB->exitStage(); }
366     private:
367         GrGLProgramBuilder* fPB;
368     };
369     void exitStage() { fOutOfStage = true; }
370     void enterStage() { fOutOfStage = false; }
371     int stageIndex() const { return fStageIndex; }
372
373     const char* rtAdjustment() const { return "rtAdjustment"; }
374
375     // number of each input/output type in a single allocation block, used by many builders
376     static const int kVarsPerBlock;
377
378     BuiltinUniformHandles fUniformHandles;
379     GrGLVertexBuilder fVS;
380     GrGLGeometryBuilder fGS;
381     GrGLFragmentShaderBuilder fFS;
382     bool fOutOfStage;
383     int fStageIndex;
384
385     GrGLInstalledGeoProc* fGeometryProcessor;
386     GrGLInstalledXferProc* fXferProcessor;
387     SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
388
389     const DrawArgs& fArgs;
390     GrGLGpu* fGpu;
391     UniformInfoArray fUniforms;
392     GrGLPrimitiveProcessor::TransformsIn fCoordTransforms;
393     GrGLPrimitiveProcessor::TransformsOut fOutCoords;
394
395     friend class GrGLShaderBuilder;
396     friend class GrGLVertexBuilder;
397     friend class GrGLFragmentShaderBuilder;
398     friend class GrGLGeometryBuilder;
399 };
400 #endif