aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/glsl/GrGLSLProgramBuilder.h
blob: 952db7e09b7be294eca8154fe80d916c98dbd6de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrGLSLProgramBuilder_DEFINED
#define GrGLSLProgramBuilder_DEFINED

#include "GrGeometryProcessor.h"
#include "GrGpu.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLGeometryShaderBuilder.h"
#include "glsl/GrGLSLPrimitiveProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLUniformHandler.h"
#include "glsl/GrGLSLTextureSampler.h"
#include "glsl/GrGLSLVertexShaderBuilder.h"
#include "glsl/GrGLSLXferProcessor.h"

class GrGLSLCaps;
class GrGLSLShaderVar;
class GrGLSLVaryingHandler;

typedef SkSTArray<8, GrGLSLFragmentProcessor*, true> GrGLSLFragProcs;

class GrGLSLProgramBuilder {
public:
    typedef GrGLSLUniformHandler::UniformHandle UniformHandle;

    virtual ~GrGLSLProgramBuilder() {}

    virtual const GrCaps* caps() const = 0;
    virtual const GrGLSLCaps* glslCaps() const = 0;

    const GrPrimitiveProcessor& primitiveProcessor() const { return fPrimProc; }
    const GrPipeline& pipeline() const { return fPipeline; }
    const GrProgramDesc& desc() const { return fDesc; }
    const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); }

    void appendUniformDecls(GrShaderFlags visibility, SkString*) const;

    // Handles for program uniforms (other than per-effect uniforms)
    struct BuiltinUniformHandles {
        UniformHandle       fRTAdjustmentUni;

        // We use the render target height to provide a y-down frag coord when specifying
        // origin_upper_left is not supported.
        UniformHandle       fRTHeightUni;
    };

    // Used to add a uniform in the vertex shader for transforming into normalized device space.
    void addRTAdjustmentUniform(GrSLPrecision precision, const char* name, const char** outName);
    const char* rtAdjustment() const { return "rtAdjustment"; }

    // Used to add a uniform for the RenderTarget height (used for frag position) without mangling
    // the name of the uniform inside of a stage.
    void addRTHeightUniform(const char* name, const char** outName);

    // Generates a name for a variable. The generated string will be name prefixed by the prefix
    // char (unless the prefix is '\0'). It also will mangle the name to be stage-specific unless
    // explicitly asked not to.
    void nameVariable(SkString* out, char prefix, const char* name, bool mangle = true);

    virtual GrGLSLUniformHandler* uniformHandler() = 0;
    virtual const GrGLSLUniformHandler* uniformHandler() const = 0;
    virtual GrGLSLVaryingHandler* varyingHandler() = 0;

    // Used for backend customization of the output color and secondary color variables from the
    // fragment processor. Only used if the outputs are explicitly declared in the shaders
    virtual void finalizeFragmentOutputColor(GrGLSLShaderVar& outputColor) {}
    virtual void finalizeFragmentSecondaryColor(GrGLSLShaderVar& outputColor) {}

    // number of each input/output type in a single allocation block, used by many builders
    static const int kVarsPerBlock;

    GrGLSLVertexBuilder         fVS;
    GrGLSLGeometryBuilder       fGS;
    GrGLSLFragmentShaderBuilder fFS;

    int fStageIndex;

    const GrPipeline&           fPipeline;
    const GrPrimitiveProcessor& fPrimProc;
    const GrProgramDesc&        fDesc;

    BuiltinUniformHandles fUniformHandles;

    GrGLSLPrimitiveProcessor* fGeometryProcessor;
    GrGLSLXferProcessor* fXferProcessor;
    GrGLSLFragProcs fFragmentProcessors;

protected:
    explicit GrGLSLProgramBuilder(const GrPipeline&,
                                  const GrPrimitiveProcessor&,
                                  const GrProgramDesc&);

    void addFeature(GrShaderFlags shaders, uint32_t featureBit, const char* extensionName);

    bool emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);

    void cleanupFragmentProcessors();

    void finalizeShaders();

    SkTArray<UniformHandle> fSamplerUniforms;

private:
    // reset is called by program creator between each processor's emit code.  It increments the
    // stage offset for variable name mangling, and also ensures verfication variables in the
    // fragment shader are cleared.
    void reset() {
        this->addStage();
        SkDEBUGCODE(fFS.resetVerification();)
    }
    void addStage() { fStageIndex++; }

    class AutoStageAdvance {
    public:
        AutoStageAdvance(GrGLSLProgramBuilder* pb)
            : fPB(pb) {
            fPB->reset();
            // Each output to the fragment processor gets its own code section
            fPB->fFS.nextStage();
        }
        ~AutoStageAdvance() {}
    private:
        GrGLSLProgramBuilder* fPB;
    };

    // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
    // If GrGLSLExpr4 has a valid name then it will use that instead
    void nameExpression(GrGLSLExpr4*, const char* baseName);

    void emitAndInstallPrimProc(const GrPrimitiveProcessor&,
                                GrGLSLExpr4* outputColor,
                                GrGLSLExpr4* outputCoverage);
    void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
    void emitAndInstallFragProc(const GrFragmentProcessor&,
                                int index,
                                const GrGLSLExpr4& input,
                                GrGLSLExpr4* output);
    void emitAndInstallXferProc(const GrXferProcessor&,
                                const GrGLSLExpr4& colorIn,
                                const GrGLSLExpr4& coverageIn,
                                bool ignoresCoverage,
                                GrPixelLocalStorageState plsState);
    void emitSamplers(const GrProcessor& processor,
                      GrGLSLTextureSampler::TextureSamplerArray* outSamplers);
    void emitFSOutputSwizzle(bool hasSecondaryOutput);
    bool checkSamplerCounts();

#ifdef SK_DEBUG
    void verify(const GrPrimitiveProcessor&);
    void verify(const GrXferProcessor&);
    void verify(const GrFragmentProcessor&);
#endif

    GrGLSLPrimitiveProcessor::TransformsIn     fCoordTransforms;
    GrGLSLPrimitiveProcessor::TransformsOut    fOutCoords;
    int                                        fNumVertexSamplers;
    int                                        fNumGeometrySamplers;
    int                                        fNumFragmentSamplers;
};

#endif