1/*
2 * Copyright 2015 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 GrGLSLProgramBuilder_DEFINED
9#define GrGLSLProgramBuilder_DEFINED
10
11#include "GrGeometryProcessor.h"
12#include "GrGpu.h"
13#include "glsl/GrGLSLFragmentShaderBuilder.h"
14#include "glsl/GrGLSLGeometryShaderBuilder.h"
15#include "glsl/GrGLSLPrimitiveProcessor.h"
16#include "glsl/GrGLSLProgramDataManager.h"
17#include "glsl/GrGLSLUniformHandler.h"
18#include "glsl/GrGLSLTextureSampler.h"
19#include "glsl/GrGLSLVertexShaderBuilder.h"
20#include "glsl/GrGLSLXferProcessor.h"
21
22class GrGLSLCaps;
23class GrGLSLShaderVar;
24class GrGLSLVaryingHandler;
25
26typedef SkSTArray<8, GrGLSLFragmentProcessor*, true> GrGLSLFragProcs;
27
28class GrGLSLProgramBuilder {
29public:
30    typedef GrGpu::DrawArgs DrawArgs;
31    typedef GrGLSLUniformHandler::UniformHandle UniformHandle;
32
33    virtual ~GrGLSLProgramBuilder() {}
34
35    virtual const GrCaps* caps() const = 0;
36    virtual const GrGLSLCaps* glslCaps() const = 0;
37
38    const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
39    const GrPipeline& pipeline() const { return *fArgs.fPipeline; }
40    const GrProgramDesc& desc() const { return *fArgs.fDesc; }
41    const GrProgramDesc::KeyHeader& header() const { return fArgs.fDesc->header(); }
42
43    void appendUniformDecls(GrShaderFlags visibility, SkString*) const;
44
45    // Handles for program uniforms (other than per-effect uniforms)
46    struct BuiltinUniformHandles {
47        UniformHandle       fRTAdjustmentUni;
48
49        // We use the render target height to provide a y-down frag coord when specifying
50        // origin_upper_left is not supported.
51        UniformHandle       fRTHeightUni;
52    };
53
54    // Used to add a uniform in the vertex shader for transforming into normalized device space.
55    void addRTAdjustmentUniform(GrSLPrecision precision, const char* name, const char** outName);
56    const char* rtAdjustment() const { return "rtAdjustment"; }
57
58    // Used to add a uniform for the RenderTarget height (used for frag position) without mangling
59    // the name of the uniform inside of a stage.
60    void addRTHeightUniform(const char* name, const char** outName);
61
62    // Generates a name for a variable. The generated string will be name prefixed by the prefix
63    // char (unless the prefix is '\0'). It also will mangle the name to be stage-specific unless
64    // explicitly asked not to.
65    void nameVariable(SkString* out, char prefix, const char* name, bool mangle = true);
66
67    virtual GrGLSLUniformHandler* uniformHandler() = 0;
68    virtual const GrGLSLUniformHandler* uniformHandler() const = 0;
69    virtual GrGLSLVaryingHandler* varyingHandler() = 0;
70
71    // Used for backend customization of the output color and secondary color variables from the
72    // fragment processor. Only used if the outputs are explicitly declared in the shaders
73    virtual void finalizeFragmentOutputColor(GrGLSLShaderVar& outputColor) {}
74    virtual void finalizeFragmentSecondaryColor(GrGLSLShaderVar& outputColor) {}
75
76    // number of each input/output type in a single allocation block, used by many builders
77    static const int kVarsPerBlock;
78
79    GrGLSLVertexBuilder         fVS;
80    GrGLSLGeometryBuilder       fGS;
81    GrGLSLFragmentShaderBuilder fFS;
82
83    int fStageIndex;
84
85    const DrawArgs& fArgs;
86
87    BuiltinUniformHandles fUniformHandles;
88
89    GrGLSLPrimitiveProcessor* fGeometryProcessor;
90    GrGLSLXferProcessor* fXferProcessor;
91    GrGLSLFragProcs fFragmentProcessors;
92
93protected:
94    explicit GrGLSLProgramBuilder(const DrawArgs& args);
95
96    bool emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage, int maxTextures);
97
98    void cleanupFragmentProcessors();
99
100    void finalizeShaders();
101
102private:
103    // reset is called by program creator between each processor's emit code.  It increments the
104    // stage offset for variable name mangling, and also ensures verfication variables in the
105    // fragment shader are cleared.
106    void reset() {
107        this->addStage();
108        fFS.reset();
109    }
110    void addStage() { fStageIndex++; }
111
112    class AutoStageAdvance {
113    public:
114        AutoStageAdvance(GrGLSLProgramBuilder* pb)
115            : fPB(pb) {
116            fPB->reset();
117            // Each output to the fragment processor gets its own code section
118            fPB->fFS.nextStage();
119        }
120        ~AutoStageAdvance() {}
121    private:
122        GrGLSLProgramBuilder* fPB;
123    };
124
125    // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
126    // If GrGLSLExpr4 has a valid name then it will use that instead
127    void nameExpression(GrGLSLExpr4*, const char* baseName);
128
129    void emitAndInstallPrimProc(const GrPrimitiveProcessor&,
130                                GrGLSLExpr4* outputColor,
131                                GrGLSLExpr4* outputCoverage);
132    void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
133    void emitAndInstallFragProc(const GrFragmentProcessor&,
134                                int index,
135                                const GrGLSLExpr4& input,
136                                GrGLSLExpr4* output);
137    void emitAndInstallXferProc(const GrXferProcessor&,
138                                const GrGLSLExpr4& colorIn,
139                                const GrGLSLExpr4& coverageIn,
140                                bool ignoresCoverage,
141                                GrPixelLocalStorageState plsState);
142    void emitFSOutputSwizzle(bool hasSecondaryOutput);
143
144    void verify(const GrPrimitiveProcessor&);
145    void verify(const GrXferProcessor&);
146    void verify(const GrFragmentProcessor&);
147
148    virtual void emitSamplers(const GrProcessor& processor,
149                              GrGLSLTextureSampler::TextureSamplerArray* outSamplers) = 0;
150
151    GrGLSLPrimitiveProcessor::TransformsIn  fCoordTransforms;
152    GrGLSLPrimitiveProcessor::TransformsOut fOutCoords;
153};
154
155#endif
156