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