GrGLProgram.h revision dd182cbca60a7f0003330c01dfc64f69f56aea90
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef GrGLProgram_DEFINED
11#define GrGLProgram_DEFINED
12
13#include "../GrDrawState.h"
14#include "GrGLInterface.h"
15#include "GrGLSL.h"
16#include "../GrStringBuilder.h"
17#include "../GrGpu.h"
18
19#include "SkXfermode.h"
20
21class GrBinHashKeyBuilder;
22
23struct ShaderCodeSegments;
24
25// optionally compile the experimental GS code. Set to GR_DEBUG
26// so that debug build bots will execute the code.
27#define GR_GL_EXPERIMENTAL_GS GR_DEBUG
28
29/**
30 * This class manages a GPU program and records per-program information.
31 * We can specify the attribute locations so that they are constant
32 * across our shaders. But the driver determines the uniform locations
33 * at link time. We don't need to remember the sampler uniform location
34 * because we will bind a texture slot to it and never change it
35 * Uniforms are program-local so we can't rely on fHWState to hold the
36 * previous uniform state after a program change.
37 */
38class GrGLProgram {
39public:
40
41    class CachedData;
42
43    GrGLProgram();
44    ~GrGLProgram();
45
46    /**
47     *  This is the heavy initilization routine for building a GLProgram.
48     *  The result of heavy init is not stored in datamembers of GrGLProgam,
49     *  but in a separate cacheable container.
50     */
51    bool genProgram(const GrGLInterface* gl,
52                    GrGLSLGeneration glslVersion,
53                    CachedData* programData) const;
54
55     /**
56      * The shader may modify the blend coeffecients. Params are in/out
57      */
58     void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
59
60    /**
61     * Attribute indices. These should not overlap. Matrices consume 3 slots.
62     */
63    static int PositionAttributeIdx() { return 0; }
64    static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; }
65    static int ColorAttributeIdx() { return 1 + GrDrawState::kMaxTexCoords; }
66    static int CoverageAttributeIdx() {
67        return 2 + GrDrawState::kMaxTexCoords;
68    }
69    static int EdgeAttributeIdx() { return 3 + GrDrawState::kMaxTexCoords; }
70
71    static int ViewMatrixAttributeIdx() {
72        return 4 + GrDrawState::kMaxTexCoords;
73    }
74    static int TextureMatrixAttributeIdx(int stage) {
75        return 7 + GrDrawState::kMaxTexCoords + 3 * stage;
76    }
77
78public:
79
80    // Parameters that affect code generation
81    // These structs should be kept compact; they are the input to an
82    // expensive hash key generator.
83    struct ProgramDesc {
84        ProgramDesc() {
85            // since we use this as part of a key we can't have any unitialized
86            // padding
87            memset(this, 0, sizeof(ProgramDesc));
88        }
89
90        enum OutputPM {
91            // PM-color OR color with no alpha channel
92            kYes_OutputPM,
93            // nonPM-color with alpha channel
94            kNo_OutputPM,
95
96            kOutputPMCnt
97        };
98
99        struct StageDesc {
100            enum OptFlagBits {
101                kNoPerspective_OptFlagBit       = 1 << 0,
102                kIdentityMatrix_OptFlagBit      = 1 << 1,
103                kCustomTextureDomain_OptFlagBit = 1 << 2,
104                kIsEnabled_OptFlagBit           = 1 << 7
105            };
106            enum FetchMode {
107                kSingle_FetchMode,
108                k2x2_FetchMode,
109                kConvolution_FetchMode,
110
111                kFetchModeCnt,
112            };
113            /**
114              Flags set based on a src texture's pixel config. The operations
115              described are performed after reading a texel.
116             */
117            enum InConfigFlags {
118                kNone_InConfigFlag              = 0x0,
119
120                /**
121                  Swap the R and B channels. This is incompatible with
122                  kSmearAlpha. It is prefereable to perform the swizzle outside
123                  the shader using GL_ARB_texture_swizzle if possible rather
124                  than setting this flag.
125                 */
126                kSwapRAndB_InConfigFlag         = 0x1,
127
128                /**
129                 Smear alpha across all four channels. This is incompatible with
130                 kSwapRAndB and kPremul.  It is prefereable to perform the
131                 smear outside the shader using GL_ARB_texture_swizzle if
132                 possible rather than setting this flag.
133                */
134                kSmearAlpha_InConfigFlag        = 0x2,
135
136                /**
137                 Multiply r,g,b by a after texture reads. This flag incompatible
138                 with kSmearAlpha and may only be used with FetchMode kSingle.
139                 */
140                kMulRGBByAlpha_InConfigFlag     =  0x4,
141
142                kDummyInConfigFlag,
143                kInConfigBitMask = (kDummyInConfigFlag-1) |
144                                   (kDummyInConfigFlag-2)
145            };
146            enum CoordMapping {
147                kIdentity_CoordMapping,
148                kRadialGradient_CoordMapping,
149                kSweepGradient_CoordMapping,
150                kRadial2Gradient_CoordMapping,
151                // need different shader computation when quadratic
152                // eq describing the gradient degenerates to a linear eq.
153                kRadial2GradientDegenerate_CoordMapping,
154                kCoordMappingCnt
155            };
156
157            uint8_t fOptFlags;
158            uint8_t fInConfigFlags; // bitfield of InConfigFlags values
159            uint8_t fFetchMode;     // casts to enum FetchMode
160            uint8_t fCoordMapping;  // casts to enum CoordMapping
161            uint8_t fKernelWidth;
162
163            GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask ==
164                             kInConfigBitMask);
165
166            inline bool isEnabled() const {
167                return SkToBool(fOptFlags & kIsEnabled_OptFlagBit);
168            }
169            inline void setEnabled(bool newValue) {
170                if (newValue) {
171                    fOptFlags |= kIsEnabled_OptFlagBit;
172                } else {
173                    fOptFlags &= ~kIsEnabled_OptFlagBit;
174                }
175            }
176        };
177
178        // Specifies where the intitial color comes from before the stages are
179        // applied.
180        enum ColorInput {
181            kSolidWhite_ColorInput,
182            kTransBlack_ColorInput,
183            kAttribute_ColorInput,
184            kUniform_ColorInput,
185
186            kColorInputCnt
187        };
188        // Dual-src blending makes use of a secondary output color that can be
189        // used as a per-pixel blend coeffecient. This controls whether a
190        // secondary source is output and what value it holds.
191        enum DualSrcOutput {
192            kNone_DualSrcOutput,
193            kCoverage_DualSrcOutput,
194            kCoverageISA_DualSrcOutput,
195            kCoverageISC_DualSrcOutput,
196
197            kDualSrcOutputCnt
198        };
199
200        GrDrawState::VertexEdgeType fVertexEdgeType;
201
202        // stripped of bits that don't affect prog generation
203        GrVertexLayout fVertexLayout;
204
205        StageDesc fStages[GrDrawState::kNumStages];
206
207        // To enable experimental geometry shader code (not for use in
208        // production)
209#if GR_GL_EXPERIMENTAL_GS
210        bool fExperimentalGS;
211#endif
212
213        uint8_t fColorInput;        // casts to enum ColorInput
214        uint8_t fCoverageInput;     // casts to enum CoverageInput
215        uint8_t fOutputPM;          // cases to enum OutputPM
216        uint8_t fDualSrcOutput;     // casts to enum DualSrcOutput
217        int8_t fFirstCoverageStage;
218        SkBool8 fEmitsPointSize;
219        SkBool8 fEdgeAAConcave;
220        SkBool8 fColorMatrixEnabled;
221
222        int8_t fEdgeAANumEdges;
223        uint8_t fColorFilterXfermode;  // casts to enum SkXfermode::Mode
224        int8_t fPadding[3];
225
226    } fProgramDesc;
227    GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4));
228
229    // for code readability
230    typedef ProgramDesc::StageDesc StageDesc;
231
232private:
233
234    const ProgramDesc& getDesc() { return fProgramDesc; }
235    const char* adjustInColor(const GrStringBuilder& inColor) const;
236
237public:
238    enum {
239        kUnusedUniform = -1,
240        kSetAsAttribute = 1000,
241    };
242
243    struct StageUniLocations {
244        GrGLint fTextureMatrixUni;
245        GrGLint fNormalizedTexelSizeUni;
246        GrGLint fSamplerUni;
247        GrGLint fRadial2Uni;
248        GrGLint fTexDomUni;
249        GrGLint fKernelUni;
250        GrGLint fImageIncrementUni;
251        void reset() {
252            fTextureMatrixUni = kUnusedUniform;
253            fNormalizedTexelSizeUni = kUnusedUniform;
254            fSamplerUni = kUnusedUniform;
255            fRadial2Uni = kUnusedUniform;
256            fTexDomUni = kUnusedUniform;
257            fKernelUni = kUnusedUniform;
258            fImageIncrementUni = kUnusedUniform;
259        }
260    };
261
262    struct UniLocations {
263        GrGLint fViewMatrixUni;
264        GrGLint fColorUni;
265        GrGLint fCoverageUni;
266        GrGLint fEdgesUni;
267        GrGLint fColorFilterUni;
268        GrGLint fColorMatrixUni;
269        GrGLint fColorMatrixVecUni;
270        StageUniLocations fStages[GrDrawState::kNumStages];
271        void reset() {
272            fViewMatrixUni = kUnusedUniform;
273            fColorUni = kUnusedUniform;
274            fCoverageUni = kUnusedUniform;
275            fEdgesUni = kUnusedUniform;
276            fColorFilterUni = kUnusedUniform;
277            fColorMatrixUni = kUnusedUniform;
278            fColorMatrixVecUni = kUnusedUniform;
279            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
280                fStages[s].reset();
281            }
282        }
283    };
284
285    class CachedData : public ::GrNoncopyable {
286    public:
287        CachedData() {
288        }
289
290        ~CachedData() {
291        }
292
293        void copyAndTakeOwnership(CachedData& other) {
294            memcpy(this, &other, sizeof(*this));
295        }
296
297    public:
298
299        // IDs
300        GrGLuint    fVShaderID;
301        GrGLuint    fGShaderID;
302        GrGLuint    fFShaderID;
303        GrGLuint    fProgramID;
304        // shader uniform locations (-1 if shader doesn't use them)
305        UniLocations fUniLocations;
306
307        GrMatrix  fViewMatrix;
308
309        // these reflect the current values of uniforms
310        // (GL uniform values travel with program)
311        GrColor                     fColor;
312        GrColor                     fCoverage;
313        GrColor                     fColorFilterColor;
314        GrMatrix                    fTextureMatrices[GrDrawState::kNumStages];
315        // width and height used for normalized texel size
316        int                         fTextureWidth[GrDrawState::kNumStages];
317        int                         fTextureHeight[GrDrawState::kNumStages];
318        GrScalar                    fRadial2CenterX1[GrDrawState::kNumStages];
319        GrScalar                    fRadial2Radius0[GrDrawState::kNumStages];
320        bool                        fRadial2PosRoot[GrDrawState::kNumStages];
321        GrRect                      fTextureDomain[GrDrawState::kNumStages];
322
323    private:
324        enum Constants {
325            kUniLocationPreAllocSize = 8
326        };
327
328    }; // CachedData
329
330    enum Constants {
331        kProgramKeySize = sizeof(ProgramDesc)
332    };
333
334    // Provide an opaque ProgramDesc
335    const uint32_t* keyData() const{
336        return reinterpret_cast<const uint32_t*>(&fProgramDesc);
337    }
338
339private:
340
341    // Determines which uniforms will need to be bound.
342    void genStageCode(const GrGLInterface* gl,
343                      int stageNum,
344                      const ProgramDesc::StageDesc& desc,
345                      const char* fsInColor, // NULL means no incoming color
346                      const char* fsOutColor,
347                      const char* vsInCoord,
348                      ShaderCodeSegments* segments,
349                      StageUniLocations* locations) const;
350
351    void genGeometryShader(const GrGLInterface* gl,
352                           GrGLSLGeneration glslVersion,
353                           ShaderCodeSegments* segments) const;
354
355    // generates code to compute coverage based on edge AA.
356    void genEdgeCoverage(const GrGLInterface* gl,
357                         GrVertexLayout layout,
358                         CachedData* programData,
359                         GrStringBuilder* coverageVar,
360                         ShaderCodeSegments* segments) const;
361
362    static bool CompileShaders(const GrGLInterface* gl,
363                               GrGLSLGeneration glslVersion,
364                               const ShaderCodeSegments& segments,
365                               CachedData* programData);
366
367    // Compiles a GL shader, returns shader ID or 0 if failed
368    // params have same meaning as glShaderSource
369    static GrGLuint CompileShader(const GrGLInterface* gl,
370                                  GrGLenum type, int stringCnt,
371                                  const char** strings,
372                                  int* stringLengths);
373
374    // Creates a GL program ID, binds shader attributes to GL vertex attrs, and
375    // links the program
376    bool bindOutputsAttribsAndLinkProgram(
377                const GrGLInterface* gl,
378                GrStringBuilder texCoordAttrNames[GrDrawState::kMaxTexCoords],
379                bool bindColorOut,
380                bool bindDualSrcOut,
381                CachedData* programData) const;
382
383    // Binds uniforms; initializes cache to invalid values.
384    void getUniformLocationsAndInitCache(const GrGLInterface* gl,
385                                         CachedData* programData) const;
386
387    friend class GrGpuGLShaders;
388};
389
390#endif
391