GrGLProgram.h revision d8f856c32b679d9f5a9926feac005e2c0186f83f
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 "GrGLContextInfo.h"
14#include "GrGLSL.h"
15#include "GrStringBuilder.h"
16#include "GrGpu.h"
17
18#include "SkXfermode.h"
19
20class GrBinHashKeyBuilder;
21class GrGLProgramStage;
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 GrGLContextInfo& gl,
52                    GrCustomStage** customStages,
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 OutputConfig {
91            // PM-color OR color with no alpha channel
92            kPremultiplied_OutputConfig,
93            // nonPM-color with alpha channel. Round components up after
94            // dividing by alpha. Assumes output is 8 bits for r, g, and b
95            kUnpremultiplied_RoundUp_OutputConfig,
96            // nonPM-color with alpha channel. Round components down after
97            // dividing by alpha. Assumes output is 8 bits for r, g, and b
98            kUnpremultiplied_RoundDown_OutputConfig,
99
100            kOutputConfigCnt
101        };
102
103        struct StageDesc {
104            enum OptFlagBits {
105                kNoPerspective_OptFlagBit       = 1 << 0,
106                kIdentityMatrix_OptFlagBit      = 1 << 1,
107                kCustomTextureDomain_OptFlagBit = 1 << 2,
108                kIsEnabled_OptFlagBit           = 1 << 7
109            };
110            // Convolution is obsolete; left in for testing only
111            enum FetchMode {
112                kSingle_FetchMode,
113                k2x2_FetchMode,
114                kConvolution_FetchMode,
115                kErode_FetchMode,
116                kDilate_FetchMode,
117
118                kFetchModeCnt,
119            };
120            /**
121              Flags set based on a src texture's pixel config. The operations
122              described are performed after reading a texel.
123             */
124            enum InConfigFlags {
125                kNone_InConfigFlag                      = 0x00,
126
127                /**
128                  Swap the R and B channels. This is incompatible with
129                  kSmearAlpha. It is prefereable to perform the swizzle outside
130                  the shader using GL_ARB_texture_swizzle if possible rather
131                  than setting this flag.
132                 */
133                kSwapRAndB_InConfigFlag                 = 0x01,
134
135                /**
136                 Smear alpha across all four channels. This is incompatible with
137                 kSwapRAndB, kMulRGBByAlpha* and kSmearRed. It is prefereable
138                 to perform the smear outside the shader using
139                 GL_ARB_texture_swizzle if possible rather than setting this
140                 flag.
141                */
142                kSmearAlpha_InConfigFlag                = 0x02,
143
144                /**
145                 Smear the red channel across all four channels. This flag is
146                 incompatible with kSwapRAndB, kMulRGBByAlpha*and kSmearAlpha.
147                 It is preferable to use GL_ARB_texture_swizzle instead of this
148                 flag.
149                */
150                kSmearRed_InConfigFlag                  = 0x04,
151
152                /**
153                 Multiply r,g,b by a after texture reads. This flag incompatible
154                 with kSmearAlpha and may only be used with FetchMode kSingle.
155
156                 It is assumed the src texture has 8bit color components. After
157                 reading the texture one version rounds up to the next multiple
158                 of 1/255.0 and the other rounds down. At most one of these
159                 flags may be set.
160                 */
161                kMulRGBByAlpha_RoundUp_InConfigFlag     =  0x08,
162                kMulRGBByAlpha_RoundDown_InConfigFlag   =  0x10,
163
164                kDummyInConfigFlag,
165                kInConfigBitMask = (kDummyInConfigFlag-1) |
166                                   (kDummyInConfigFlag-2)
167            };
168            enum CoordMapping {
169                kIdentity_CoordMapping,
170                kRadialGradient_CoordMapping,
171                kSweepGradient_CoordMapping,
172                kRadial2Gradient_CoordMapping,
173                // need different shader computation when quadratic
174                // eq describing the gradient degenerates to a linear eq.
175                kRadial2GradientDegenerate_CoordMapping,
176                kCoordMappingCnt
177            };
178
179            uint8_t fOptFlags;
180            uint8_t fInConfigFlags; // bitfield of InConfigFlags values
181            uint8_t fFetchMode;     // casts to enum FetchMode
182            uint8_t fCoordMapping;  // casts to enum CoordMapping
183            uint8_t fKernelWidth;
184
185            /** Non-zero if user-supplied code will write the stage's
186                contribution to the fragment shader. */
187            uint16_t fCustomStageKey;
188
189            GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask ==
190                             kInConfigBitMask);
191
192            inline bool isEnabled() const {
193                return SkToBool(fOptFlags & kIsEnabled_OptFlagBit);
194            }
195            inline void setEnabled(bool newValue) {
196                if (newValue) {
197                    fOptFlags |= kIsEnabled_OptFlagBit;
198                } else {
199                    fOptFlags &= ~kIsEnabled_OptFlagBit;
200                }
201            }
202        };
203
204        // Specifies where the intitial color comes from before the stages are
205        // applied.
206        enum ColorInput {
207            kSolidWhite_ColorInput,
208            kTransBlack_ColorInput,
209            kAttribute_ColorInput,
210            kUniform_ColorInput,
211
212            kColorInputCnt
213        };
214        // Dual-src blending makes use of a secondary output color that can be
215        // used as a per-pixel blend coeffecient. This controls whether a
216        // secondary source is output and what value it holds.
217        enum DualSrcOutput {
218            kNone_DualSrcOutput,
219            kCoverage_DualSrcOutput,
220            kCoverageISA_DualSrcOutput,
221            kCoverageISC_DualSrcOutput,
222
223            kDualSrcOutputCnt
224        };
225
226        GrDrawState::VertexEdgeType fVertexEdgeType;
227
228        // stripped of bits that don't affect prog generation
229        GrVertexLayout fVertexLayout;
230
231        StageDesc fStages[GrDrawState::kNumStages];
232
233        // To enable experimental geometry shader code (not for use in
234        // production)
235#if GR_GL_EXPERIMENTAL_GS
236        bool fExperimentalGS;
237#endif
238
239        uint8_t fColorInput;        // casts to enum ColorInput
240        uint8_t fCoverageInput;     // casts to enum CoverageInput
241        uint8_t fOutputConfig;      // casts to enum OutputConfig
242        uint8_t fDualSrcOutput;     // casts to enum DualSrcOutput
243        int8_t fFirstCoverageStage;
244        SkBool8 fEmitsPointSize;
245        SkBool8 fEdgeAAConcave;
246        SkBool8 fColorMatrixEnabled;
247
248        int8_t fEdgeAANumEdges;
249        uint8_t fColorFilterXfermode;  // casts to enum SkXfermode::Mode
250        int8_t fPadding[3];
251
252    } fProgramDesc;
253    GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4));
254
255    // for code readability
256    typedef ProgramDesc::StageDesc StageDesc;
257
258private:
259
260    const ProgramDesc& getDesc() { return fProgramDesc; }
261    const char* adjustInColor(const GrStringBuilder& inColor) const;
262
263public:
264    enum {
265        kUnusedUniform = -1,
266        kSetAsAttribute = 1000,
267    };
268
269    struct StageUniLocations {
270        GrGLint fTextureMatrixUni;
271        GrGLint fNormalizedTexelSizeUni;
272        GrGLint fSamplerUni;
273        GrGLint fRadial2Uni;
274        GrGLint fTexDomUni;
275        GrGLint fKernelUni;
276        GrGLint fImageIncrementUni;
277        void reset() {
278            fTextureMatrixUni = kUnusedUniform;
279            fNormalizedTexelSizeUni = kUnusedUniform;
280            fSamplerUni = kUnusedUniform;
281            fRadial2Uni = kUnusedUniform;
282            fTexDomUni = kUnusedUniform;
283            fKernelUni = kUnusedUniform;
284            fImageIncrementUni = kUnusedUniform;
285        }
286    };
287
288    struct UniLocations {
289        GrGLint fViewMatrixUni;
290        GrGLint fColorUni;
291        GrGLint fCoverageUni;
292        GrGLint fEdgesUni;
293        GrGLint fColorFilterUni;
294        GrGLint fColorMatrixUni;
295        GrGLint fColorMatrixVecUni;
296        StageUniLocations fStages[GrDrawState::kNumStages];
297        void reset() {
298            fViewMatrixUni = kUnusedUniform;
299            fColorUni = kUnusedUniform;
300            fCoverageUni = kUnusedUniform;
301            fEdgesUni = kUnusedUniform;
302            fColorFilterUni = kUnusedUniform;
303            fColorMatrixUni = kUnusedUniform;
304            fColorMatrixVecUni = kUnusedUniform;
305            for (int s = 0; s < GrDrawState::kNumStages; ++s) {
306                fStages[s].reset();
307            }
308        }
309    };
310
311    class CachedData : public ::GrNoncopyable {
312    public:
313        CachedData() {
314            for (int i = 0; i < GrDrawState::kNumStages; ++i) {
315                fCustomStage[i] = NULL;
316            }
317        }
318
319        ~CachedData();
320
321        void copyAndTakeOwnership(CachedData& other) {
322            memcpy(this, &other, sizeof(*this));
323            for (int i = 0; i < GrDrawState::kNumStages; ++i) {
324                other.fCustomStage[i] = NULL;
325            }
326        }
327
328    public:
329
330        // IDs
331        GrGLuint    fVShaderID;
332        GrGLuint    fGShaderID;
333        GrGLuint    fFShaderID;
334        GrGLuint    fProgramID;
335        // shader uniform locations (-1 if shader doesn't use them)
336        UniLocations fUniLocations;
337
338        GrMatrix  fViewMatrix;
339
340        // these reflect the current values of uniforms
341        // (GL uniform values travel with program)
342        GrColor                     fColor;
343        GrColor                     fCoverage;
344        GrColor                     fColorFilterColor;
345        GrMatrix                    fTextureMatrices[GrDrawState::kNumStages];
346        // width and height used for normalized texel size
347        int                         fTextureWidth[GrDrawState::kNumStages];
348        int                         fTextureHeight[GrDrawState::kNumStages];
349        GrScalar                    fRadial2CenterX1[GrDrawState::kNumStages];
350        GrScalar                    fRadial2Radius0[GrDrawState::kNumStages];
351        bool                        fRadial2PosRoot[GrDrawState::kNumStages];
352        GrRect                      fTextureDomain[GrDrawState::kNumStages];
353
354        GrGLProgramStage*           fCustomStage[GrDrawState::kNumStages];
355
356    private:
357        enum Constants {
358            kUniLocationPreAllocSize = 8
359        };
360
361    }; // CachedData
362
363    enum Constants {
364        kProgramKeySize = sizeof(ProgramDesc)
365    };
366
367    // Provide an opaque ProgramDesc
368    const uint32_t* keyData() const{
369        return reinterpret_cast<const uint32_t*>(&fProgramDesc);
370    }
371
372private:
373
374    // Determines which uniforms will need to be bound.
375    void genStageCode(const GrGLContextInfo& gl,
376                      int stageNum,
377                      const ProgramDesc::StageDesc& desc,
378                      const char* fsInColor, // NULL means no incoming color
379                      const char* fsOutColor,
380                      const char* vsInCoord,
381                      ShaderCodeSegments* segments,
382                      StageUniLocations* locations,
383                      GrGLProgramStage* override) const;
384
385    void genGeometryShader(const GrGLContextInfo& gl,
386                           ShaderCodeSegments* segments) const;
387
388    // generates code to compute coverage based on edge AA.
389    void genEdgeCoverage(const GrGLContextInfo& gl,
390                         GrVertexLayout layout,
391                         CachedData* programData,
392                         GrStringBuilder* coverageVar,
393                         ShaderCodeSegments* segments) const;
394
395    static bool CompileShaders(const GrGLContextInfo& gl,
396                               const ShaderCodeSegments& segments,
397                               CachedData* programData);
398
399    // Compiles a GL shader, returns shader ID or 0 if failed
400    // params have same meaning as glShaderSource
401    static GrGLuint CompileShader(const GrGLContextInfo& gl,
402                                  GrGLenum type, int stringCnt,
403                                  const char** strings,
404                                  int* stringLengths);
405
406    // Creates a GL program ID, binds shader attributes to GL vertex attrs, and
407    // links the program
408    bool bindOutputsAttribsAndLinkProgram(
409                const GrGLContextInfo& gl,
410                GrStringBuilder texCoordAttrNames[GrDrawState::kMaxTexCoords],
411                bool bindColorOut,
412                bool bindDualSrcOut,
413                CachedData* programData) const;
414
415    // Binds uniforms; initializes cache to invalid values.
416    void getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
417                                         CachedData* programData) const;
418
419    friend class GrGpuGLShaders;
420};
421
422#endif
423