Home | History | Annotate | Download | only in gl
      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 
     21 class GrBinHashKeyBuilder;
     22 
     23 struct 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  */
     38 class GrGLProgram {
     39 public:
     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 
     77 public:
     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 
    243 private:
    244 
    245     const ProgramDesc& getDesc() { return fProgramDesc; }
    246     const char* adjustInColor(const GrStringBuilder& inColor) const;
    247 
    248 public:
    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 
    350 private:
    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