Home | History | Annotate | Download | only in gl
      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 "GrGLContextInfo.h"
     15 #include "GrGLSL.h"
     16 #include "GrGLTexture.h"
     17 #include "GrGLUniformManager.h"
     18 
     19 #include "SkString.h"
     20 #include "SkXfermode.h"
     21 
     22 class GrBinHashKeyBuilder;
     23 class GrGLEffect;
     24 class GrGLShaderBuilder;
     25 
     26 // optionally compile the experimental GS code. Set to GR_DEBUG
     27 // so that debug build bots will execute the code.
     28 #define GR_GL_EXPERIMENTAL_GS GR_DEBUG
     29 
     30 /**
     31  * This class manages a GPU program and records per-program information.
     32  * We can specify the attribute locations so that they are constant
     33  * across our shaders. But the driver determines the uniform locations
     34  * at link time. We don't need to remember the sampler uniform location
     35  * because we will bind a texture slot to it and never change it
     36  * Uniforms are program-local so we can't rely on fHWState to hold the
     37  * previous uniform state after a program change.
     38  */
     39 class GrGLProgram : public GrRefCnt {
     40 public:
     41     SK_DECLARE_INST_COUNT(GrGLProgram)
     42 
     43     struct Desc;
     44 
     45     static GrGLProgram* Create(const GrGLContextInfo& gl,
     46                                const Desc& desc,
     47                                const GrEffectStage* stages[]);
     48 
     49     virtual ~GrGLProgram();
     50 
     51     /**
     52      * Call to abandon GL objects owned by this program.
     53      */
     54     void abandon();
     55 
     56     /**
     57      * The shader may modify the blend coefficients. Params are in/out
     58      */
     59     void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
     60 
     61     const Desc& getDesc() { return fDesc; }
     62 
     63     /**
     64      * Attribute indices. These should not overlap.
     65      */
     66     static int PositionAttributeIdx() { return 0; }
     67     static int ColorAttributeIdx() { return 1; }
     68     static int CoverageAttributeIdx() { return 2; }
     69     static int EdgeAttributeIdx() { return 3; }
     70     static int TexCoordAttributeIdx(int tcIdx) { return 4 + tcIdx; }
     71 
     72     /**
     73      * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a
     74      * draw occurs using the program after the program has already been bound. It also uses the
     75      * GrGpuGL object to bind the textures required by the GrGLEffects.
     76      */
     77     void setData(GrGpuGL*);
     78 
     79     // Parameters that affect code generation
     80     // This structs should be kept compact; it is input to an expensive hash key generator.
     81     struct Desc {
     82         Desc() {
     83             // since we use this as part of a key we can't have any uninitialized
     84             // padding
     85             memset(this, 0, sizeof(Desc));
     86         }
     87 
     88         // returns this as a uint32_t array to be used as a key in the program cache
     89         const uint32_t* asKey() const {
     90             return reinterpret_cast<const uint32_t*>(this);
     91         }
     92 
     93         // Specifies where the initial color comes from before the stages are applied.
     94         enum ColorInput {
     95             kSolidWhite_ColorInput,
     96             kTransBlack_ColorInput,
     97             kAttribute_ColorInput,
     98             kUniform_ColorInput,
     99 
    100             kColorInputCnt
    101         };
    102         // Dual-src blending makes use of a secondary output color that can be
    103         // used as a per-pixel blend coefficient. This controls whether a
    104         // secondary source is output and what value it holds.
    105         enum DualSrcOutput {
    106             kNone_DualSrcOutput,
    107             kCoverage_DualSrcOutput,
    108             kCoverageISA_DualSrcOutput,
    109             kCoverageISC_DualSrcOutput,
    110 
    111             kDualSrcOutputCnt
    112         };
    113 
    114         // TODO: remove these two members when edge-aa can be rewritten as a GrEffect.
    115         GrDrawState::VertexEdgeType fVertexEdgeType;
    116         // should the FS discard if the edge-aa coverage is zero (to avoid stencil manipulation)
    117         bool                        fDiscardIfOutsideEdge;
    118 
    119         // stripped of bits that don't affect program generation
    120         GrVertexLayout              fVertexLayout;
    121 
    122         /** Non-zero if this stage has an effect */
    123         GrGLEffect::EffectKey       fEffectKeys[GrDrawState::kNumStages];
    124 
    125         // To enable experimental geometry shader code (not for use in
    126         // production)
    127 #if GR_GL_EXPERIMENTAL_GS
    128         bool                        fExperimentalGS;
    129 #endif
    130         uint8_t                     fColorInput;            // casts to enum ColorInput
    131         uint8_t                     fCoverageInput;         // casts to enum ColorInput
    132         uint8_t                     fDualSrcOutput;         // casts to enum DualSrcOutput
    133         int8_t                      fFirstCoverageStage;
    134         SkBool8                     fEmitsPointSize;
    135         uint8_t                     fColorFilterXfermode;   // casts to enum SkXfermode::Mode
    136     };
    137 private:
    138     GrGLProgram(const GrGLContextInfo& gl,
    139                 const Desc& desc,
    140                 const GrEffectStage* stages[]);
    141 
    142     bool succeeded() const { return 0 != fProgramID; }
    143 
    144     /**
    145      *  This is the heavy initialization routine for building a GLProgram.
    146      */
    147     bool genProgram(const GrEffectStage* stages[]);
    148 
    149     void genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
    150 
    151     void genGeometryShader(GrGLShaderBuilder* segments) const;
    152 
    153     typedef GrGLUniformManager::UniformHandle UniformHandle;
    154 
    155     void genUniformCoverage(GrGLShaderBuilder* segments, SkString* inOutCoverage);
    156 
    157     // generates code to compute coverage based on edge AA. Returns true if edge coverage was
    158     // inserted in which case coverageVar will be updated to refer to a scalar. Otherwise,
    159     // coverageVar is set to an empty string.
    160     bool genEdgeCoverage(SkString* coverageVar, GrGLShaderBuilder* builder) const;
    161 
    162     // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
    163     bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
    164                                           SkString texCoordAttrNames[GrDrawState::kMaxTexCoords],
    165                                           bool bindColorOut,
    166                                           bool bindDualSrcOut);
    167 
    168     // Sets the texture units for samplers
    169     void initSamplerUniforms();
    170 
    171     bool compileShaders(const GrGLShaderBuilder& builder);
    172 
    173     const char* adjustInColor(const SkString& inColor) const;
    174 
    175     typedef SkSTArray<4, UniformHandle, true> SamplerUniSArray;
    176 
    177     struct UniformHandles {
    178         UniformHandle       fViewMatrixUni;
    179         UniformHandle       fColorUni;
    180         UniformHandle       fCoverageUni;
    181         UniformHandle       fColorFilterUni;
    182         // We use the render target height to provide a y-down frag coord when specifying
    183         // origin_upper_left is not supported.
    184         UniformHandle       fRTHeightUni;
    185         // An array of sampler uniform handles for each effect.
    186         SamplerUniSArray    fSamplerUnis[GrDrawState::kNumStages];
    187 
    188         UniformHandles() {
    189             fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle;
    190             fColorUni = GrGLUniformManager::kInvalidUniformHandle;
    191             fCoverageUni = GrGLUniformManager::kInvalidUniformHandle;
    192             fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle;
    193             fRTHeightUni = GrGLUniformManager::kInvalidUniformHandle;
    194         }
    195     };
    196 
    197     // GL IDs
    198     GrGLuint                    fVShaderID;
    199     GrGLuint                    fGShaderID;
    200     GrGLuint                    fFShaderID;
    201     GrGLuint                    fProgramID;
    202     // The matrix sent to GL is determined by both the client's matrix and
    203     // the size of the viewport.
    204     SkMatrix                    fViewMatrix;
    205     SkISize                     fViewportSize;
    206 
    207     // these reflect the current values of uniforms (GL uniform values travel with program)
    208     GrColor                     fColor;
    209     GrColor                     fCoverage;
    210     GrColor                     fColorFilterColor;
    211     int                         fRTHeight;
    212 
    213     GrGLEffect*                 fEffects[GrDrawState::kNumStages];
    214 
    215     Desc                        fDesc;
    216     const GrGLContextInfo&      fContextInfo;
    217 
    218     GrGLUniformManager          fUniformManager;
    219     UniformHandles              fUniformHandles;
    220 
    221     friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality.
    222 
    223     typedef GrRefCnt INHERITED;
    224 };
    225 
    226 #endif
    227