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 "GrGLContext.h"
     14 #include "GrGLProgramDesc.h"
     15 #include "GrGLShaderBuilder.h"
     16 #include "GrGLSL.h"
     17 #include "GrGLTexture.h"
     18 #include "GrGLUniformManager.h"
     19 
     20 #include "SkString.h"
     21 #include "SkXfermode.h"
     22 
     23 class GrBinHashKeyBuilder;
     24 class GrGLEffect;
     25 class GrGLProgramEffects;
     26 class GrGLShaderBuilder;
     27 
     28 /**
     29  * This class manages a GPU program and records per-program information.
     30  * We can specify the attribute locations so that they are constant
     31  * across our shaders. But the driver determines the uniform locations
     32  * at link time. We don't need to remember the sampler uniform location
     33  * because we will bind a texture slot to it and never change it
     34  * Uniforms are program-local so we can't rely on fHWState to hold the
     35  * previous uniform state after a program change.
     36  */
     37 class GrGLProgram : public SkRefCnt {
     38 public:
     39     SK_DECLARE_INST_COUNT(GrGLProgram)
     40 
     41     static GrGLProgram* Create(GrGpuGL* gpu,
     42                                const GrGLProgramDesc& desc,
     43                                const GrEffectStage* colorStages[],
     44                                const GrEffectStage* coverageStages[]);
     45 
     46     virtual ~GrGLProgram();
     47 
     48     /**
     49      * Call to abandon GL objects owned by this program.
     50      */
     51     void abandon();
     52 
     53     /**
     54      * The shader may modify the blend coefficients. Params are in/out.
     55      */
     56     void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
     57 
     58     const GrGLProgramDesc& getDesc() { return fDesc; }
     59 
     60     /**
     61      * Gets the GL program ID for this program.
     62      */
     63     GrGLuint programID() const { return fBuilderOutput.fProgramID; }
     64 
     65     bool hasVertexShader() const { return fBuilderOutput.fHasVertexShader; }
     66 
     67     /**
     68      * Some GL state that is relevant to programs is not stored per-program. In particular color
     69      * and coverage attributes can be global state. This struct is read and updated by
     70      * GrGLProgram::setColor and GrGLProgram::setCoverage to allow us to avoid setting this state
     71      * redundantly.
     72      */
     73     struct SharedGLState {
     74         GrColor fConstAttribColor;
     75         int     fConstAttribColorIndex;
     76         GrColor fConstAttribCoverage;
     77         int     fConstAttribCoverageIndex;
     78 
     79         SharedGLState() { this->invalidate(); }
     80         void invalidate() {
     81             fConstAttribColor = GrColor_ILLEGAL;
     82             fConstAttribColorIndex = -1;
     83             fConstAttribCoverage = GrColor_ILLEGAL;
     84             fConstAttribCoverageIndex = -1;
     85         }
     86     };
     87 
     88     /**
     89      * The GrDrawState's view matrix along with the aspects of the render target determine the
     90      * matrix sent to GL. The size of the render target affects the GL matrix because we must
     91      * convert from Skia device coords to GL's normalized coords. Also the origin of the render
     92      * target may require us to perform a mirror-flip.
     93      */
     94     struct MatrixState {
     95         SkMatrix        fViewMatrix;
     96         SkISize         fRenderTargetSize;
     97         GrSurfaceOrigin fRenderTargetOrigin;
     98 
     99         MatrixState() { this->invalidate(); }
    100         void invalidate() {
    101             fViewMatrix = SkMatrix::InvalidMatrix();
    102             fRenderTargetSize.fWidth = -1;
    103             fRenderTargetSize.fHeight = -1;
    104             fRenderTargetOrigin = (GrSurfaceOrigin) -1;
    105         }
    106 
    107         /**
    108          * Gets a matrix that goes from local coords to Skia's device coordinates.
    109          */
    110         template<int Size> void getGLMatrix(GrGLfloat* destMatrix) {
    111             GrGLGetMatrix<Size>(destMatrix, fViewMatrix);
    112         }
    113 
    114         /**
    115          * Gets a matrix that goes from local coordinates to GL normalized device coords.
    116          */
    117         template<int Size> void getRTAdjustedGLMatrix(GrGLfloat* destMatrix) {
    118             SkMatrix combined;
    119             if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
    120                 combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1,
    121                                 0, -SkIntToScalar(2) / fRenderTargetSize.fHeight, SK_Scalar1,
    122                                 0, 0, 1);
    123             } else {
    124                 combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1,
    125                                 0, SkIntToScalar(2) / fRenderTargetSize.fHeight, -SK_Scalar1,
    126                                 0, 0, 1);
    127             }
    128             combined.preConcat(fViewMatrix);
    129             GrGLGetMatrix<Size>(destMatrix, combined);
    130         }
    131 
    132         /**
    133          * Gets a vec4 that adjusts the position from Skia device coords to GL's normalized device
    134          * coords. Assuming the transformed position, pos, is a homogeneous vec3, the vec, v, is
    135          * applied as such:
    136          * pos.x = dot(v.xy, pos.xz)
    137          * pos.y = dot(v.zq, pos.yz)
    138          */
    139         void getRTAdjustmentVec(GrGLfloat* destVec) {
    140             destVec[0] = 2.f / fRenderTargetSize.fWidth;
    141             destVec[1] = -1.f;
    142             if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
    143                 destVec[2] = -2.f / fRenderTargetSize.fHeight;
    144                 destVec[3] = 1.f;
    145             } else {
    146                 destVec[2] = 2.f / fRenderTargetSize.fHeight;
    147                 destVec[3] = -1.f;
    148             }
    149         }
    150     };
    151 
    152     /**
    153      * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a
    154      * draw occurs using the program after the program has already been bound. It also uses the
    155      * GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage
    156      * stages come from GrGLProgramDesc::Build().
    157      */
    158     void setData(GrDrawState::BlendOptFlags,
    159                  const GrEffectStage* colorStages[],
    160                  const GrEffectStage* coverageStages[],
    161                  const GrDeviceCoordTexture* dstCopy, // can be NULL
    162                  SharedGLState*);
    163 
    164 private:
    165     typedef GrGLUniformManager::UniformHandle UniformHandle;
    166 
    167     GrGLProgram(GrGpuGL*,
    168                 const GrGLProgramDesc&,
    169                 GrGLUniformManager*,
    170                 const GrGLShaderBuilder::GenProgramOutput&);
    171 
    172     // Sets the texture units for samplers.
    173     void initSamplerUniforms();
    174 
    175     // Helper for setData(). Makes GL calls to specify the initial color when there is not
    176     // per-vertex colors.
    177     void setColor(const GrDrawState&, GrColor color, SharedGLState*);
    178 
    179     // Helper for setData(). Makes GL calls to specify the initial coverage when there is not
    180     // per-vertex coverages.
    181     void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*);
    182 
    183     // Helper for setData() that sets the view matrix and loads the render target height uniform
    184     void setMatrixAndRenderTargetHeight(const GrDrawState&);
    185 
    186     // these reflect the current values of uniforms (GL uniform values travel with program)
    187     MatrixState                         fMatrixState;
    188     GrColor                             fColor;
    189     GrColor                             fCoverage;
    190     int                                 fDstCopyTexUnit;
    191 
    192     GrGLShaderBuilder::GenProgramOutput fBuilderOutput;
    193 
    194     GrGLProgramDesc                     fDesc;
    195     GrGpuGL*                            fGpu;
    196 
    197     SkAutoTUnref<GrGLUniformManager>    fUniformManager;
    198 
    199     typedef SkRefCnt INHERITED;
    200 };
    201 
    202 #endif
    203