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