GrGLProgram.h revision e9144c64a6e75795b591d2adc28f627d7c3fb8f7
1/*
2 * Copyright 2011 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
9#ifndef GrGLProgram_DEFINED
10#define GrGLProgram_DEFINED
11
12#include "GrDrawState.h"
13#include "GrGLEffect.h"
14#include "GrGLContext.h"
15#include "GrGLSL.h"
16#include "GrGLTexture.h"
17#include "GrGLUniformManager.h"
18
19#include "SkString.h"
20#include "SkXfermode.h"
21
22class GrBinHashKeyBuilder;
23class GrGLEffect;
24class GrGLShaderBuilder;
25class SkMWCRandom;
26
27// optionally compile the experimental GS code. Set to GR_DEBUG
28// so that debug build bots will execute the code.
29#define GR_GL_EXPERIMENTAL_GS GR_DEBUG
30
31/**
32 * This class manages a GPU program and records per-program information.
33 * We can specify the attribute locations so that they are constant
34 * across our shaders. But the driver determines the uniform locations
35 * at link time. We don't need to remember the sampler uniform location
36 * because we will bind a texture slot to it and never change it
37 * Uniforms are program-local so we can't rely on fHWState to hold the
38 * previous uniform state after a program change.
39 */
40class GrGLProgram : public GrRefCnt {
41public:
42    SK_DECLARE_INST_COUNT(GrGLProgram)
43
44    class Desc;
45
46    /**
47     * Builds a program descriptor from a GrDrawState. Whether the primitive type is points, the
48     * output of GrDrawState::getBlendOpts, and the caps of the GrGpuGL are also inputs.
49     */
50    static void BuildDesc(const GrDrawState&,
51                          bool isPoints,
52                          GrDrawState::BlendOptFlags,
53                          GrBlendCoeff srcCoeff,
54                          GrBlendCoeff dstCoeff,
55                          const GrGpuGL* gpu,
56                          Desc* outDesc);
57
58    static GrGLProgram* Create(const GrGLContext& gl,
59                               const Desc& desc,
60                               const GrEffectStage* stages[]);
61
62    virtual ~GrGLProgram();
63
64    /**
65     * Call to abandon GL objects owned by this program.
66     */
67    void abandon();
68
69    /**
70     * The shader may modify the blend coefficients. Params are in/out
71     */
72    void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
73
74    const Desc& getDesc() { return fDesc; }
75
76    /**
77     * Gets the GL program ID for this program.
78     */
79    GrGLuint programID() const { return fProgramID; }
80
81    /**
82     * Some GL state that is relevant to programs is not stored per-program. In particular vertex
83     * attributes are global state. This struct is read and updated by GrGLProgram::setData to
84     * allow us to avoid setting this state redundantly.
85     */
86    struct SharedGLState {
87        GrColor fConstAttribColor;
88        GrColor fConstAttribCoverage;
89
90        SharedGLState() { this->invalidate(); }
91        void invalidate() {
92            fConstAttribColor = GrColor_ILLEGAL;
93            fConstAttribCoverage = GrColor_ILLEGAL;
94        }
95    };
96
97    /**
98     * The GrDrawState's view matrix along with the aspects of the render target determine the
99     * matrix sent to GL. The size of the render target affects the GL matrix because we must
100     * convert from Skia device coords to GL's normalized coords. Also the origin of the render
101     * target may require us to perform a mirror-flip.
102     */
103    struct MatrixState {
104        SkMatrix        fViewMatrix;
105        SkISize         fRenderTargetSize;
106        GrSurfaceOrigin fRenderTargetOrigin;
107
108        MatrixState() { this->invalidate(); }
109        void invalidate() {
110            fViewMatrix = SkMatrix::InvalidMatrix();
111            fRenderTargetSize.fWidth = -1;
112            fRenderTargetSize.fHeight = -1;
113            fRenderTargetOrigin = (GrSurfaceOrigin) -1;
114        }
115    };
116
117    /**
118     * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a
119     * draw occurs using the program after the program has already been bound. It also uses the
120     * GrGpuGL object to bind the textures required by the GrGLEffects.
121     *
122     * The color and coverage params override the GrDrawState's getColor() and getCoverage() values.
123     */
124    void setData(GrGpuGL*, GrColor color, GrColor coverage, SharedGLState*);
125
126    // Parameters that affect code generation
127    // This structs should be kept compact; it is input to an expensive hash key generator.
128    class Desc {
129    public:
130        Desc() {
131            // since we use this as part of a key we can't have any uninitialized
132            // padding
133            memset(this, 0, sizeof(Desc));
134        }
135
136        // returns this as a uint32_t array to be used as a key in the program cache
137        const uint32_t* asKey() const {
138            return reinterpret_cast<const uint32_t*>(this);
139        }
140
141        // For unit testing.
142        void setRandom(SkMWCRandom*,
143                       const GrGpuGL* gpu,
144                       const GrEffectStage stages[GrDrawState::kNumStages]);
145
146    private:
147        // Specifies where the initial color comes from before the stages are applied.
148        enum ColorInput {
149            kSolidWhite_ColorInput,
150            kTransBlack_ColorInput,
151            kAttribute_ColorInput,
152            kUniform_ColorInput,
153
154            kColorInputCnt
155        };
156        // Dual-src blending makes use of a secondary output color that can be
157        // used as a per-pixel blend coefficient. This controls whether a
158        // secondary source is output and what value it holds.
159        enum DualSrcOutput {
160            kNone_DualSrcOutput,
161            kCoverage_DualSrcOutput,
162            kCoverageISA_DualSrcOutput,
163            kCoverageISC_DualSrcOutput,
164
165            kDualSrcOutputCnt
166        };
167
168        // should the FS discard if the coverage is zero (to avoid stencil manipulation)
169        bool                        fDiscardIfZeroCoverage;
170
171        // stripped of bits that don't affect program generation
172        GrAttribBindings            fAttribBindings;
173
174        /** Non-zero if this stage has an effect */
175        GrGLEffect::EffectKey       fEffectKeys[GrDrawState::kNumStages];
176
177        // To enable experimental geometry shader code (not for use in
178        // production)
179#if GR_GL_EXPERIMENTAL_GS
180        bool                        fExperimentalGS;
181#endif
182        uint8_t                     fColorInput;            // casts to enum ColorInput
183        uint8_t                     fCoverageInput;         // casts to enum ColorInput
184        uint8_t                     fDualSrcOutput;         // casts to enum DualSrcOutput
185        int8_t                      fFirstCoverageStage;
186        SkBool8                     fEmitsPointSize;
187        uint8_t                     fColorFilterXfermode;   // casts to enum SkXfermode::Mode
188
189        int8_t                      fPositionAttributeIndex;
190        int8_t                      fColorAttributeIndex;
191        int8_t                      fCoverageAttributeIndex;
192        int8_t                      fLocalCoordsAttributeIndex;
193
194        friend class GrGLProgram;
195    };
196
197    // Layout information for OpenGL vertex attributes
198    struct AttribLayout {
199        GrGLint     fCount;
200        GrGLenum    fType;
201        GrGLboolean fNormalized;
202    };
203    static const AttribLayout kAttribLayouts[kGrVertexAttribTypeCount];
204
205private:
206    GrGLProgram(const GrGLContext& gl,
207                const Desc& desc,
208                const GrEffectStage* stages[]);
209
210    bool succeeded() const { return 0 != fProgramID; }
211
212    /**
213     *  This is the heavy initialization routine for building a GLProgram.
214     */
215    bool genProgram(const GrEffectStage* stages[]);
216
217    void genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
218
219    void genGeometryShader(GrGLShaderBuilder* segments) const;
220
221    typedef GrGLUniformManager::UniformHandle UniformHandle;
222
223    void genUniformCoverage(GrGLShaderBuilder* segments, SkString* inOutCoverage);
224
225    // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
226    bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
227                                          bool bindColorOut,
228                                          bool bindDualSrcOut);
229
230    // Sets the texture units for samplers
231    void initSamplerUniforms();
232
233    bool compileShaders(const GrGLShaderBuilder& builder);
234
235    const char* adjustInColor(const SkString& inColor) const;
236
237    // Helper for setData(). Makes GL calls to specify the initial color when there is not
238    // per-vertex colors.
239    void setColor(const GrDrawState&, GrColor color, SharedGLState*);
240
241    // Helper for setData(). Makes GL calls to specify the initial coverage when there is not
242    // per-vertex coverages.
243    void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*);
244
245    // Helper for setData() that sets the view matrix and loads the render target height uniform
246    void setMatrixAndRenderTargetHeight(const GrDrawState&);
247
248    typedef SkSTArray<4, UniformHandle, true> SamplerUniSArray;
249
250    struct UniformHandles {
251        UniformHandle       fViewMatrixUni;
252        UniformHandle       fColorUni;
253        UniformHandle       fCoverageUni;
254        UniformHandle       fColorFilterUni;
255        // We use the render target height to provide a y-down frag coord when specifying
256        // origin_upper_left is not supported.
257        UniformHandle       fRTHeightUni;
258        // An array of sampler uniform handles for each effect.
259        SamplerUniSArray    fSamplerUnis[GrDrawState::kNumStages];
260
261        UniformHandles() {
262            fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle;
263            fColorUni = GrGLUniformManager::kInvalidUniformHandle;
264            fCoverageUni = GrGLUniformManager::kInvalidUniformHandle;
265            fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle;
266            fRTHeightUni = GrGLUniformManager::kInvalidUniformHandle;
267        }
268    };
269
270    // GL IDs
271    GrGLuint                    fVShaderID;
272    GrGLuint                    fGShaderID;
273    GrGLuint                    fFShaderID;
274    GrGLuint                    fProgramID;
275
276    // these reflect the current values of uniforms (GL uniform values travel with program)
277    MatrixState                 fMatrixState;
278    GrColor                     fColor;
279    GrColor                     fCoverage;
280    GrColor                     fColorFilterColor;
281
282    GrGLEffect*                 fEffects[GrDrawState::kNumStages];
283
284    Desc                        fDesc;
285    const GrGLContext&          fContext;
286
287    GrGLUniformManager          fUniformManager;
288    UniformHandles              fUniformHandles;
289
290    typedef GrRefCnt INHERITED;
291};
292
293#endif
294