1/*
2 * Copyright 2013 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#ifndef GrGLProgramEffects_DEFINED
9#define GrGLProgramEffects_DEFINED
10
11#include "GrBackendProcessorFactory.h"
12#include "GrGLProgramDataManager.h"
13#include "GrGpu.h"
14#include "GrTexture.h"
15#include "GrTextureAccess.h"
16
17class GrProcessor;
18class GrProcessorStage;
19class GrGLVertexProgramEffectsBuilder;
20class GrGLProgramBuilder;
21class GrGLFullProgramBuilder;
22class GrGLFragmentOnlyProgramBuilder;
23
24/**
25 * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
26 * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
27 * state and shader uniforms.
28 */
29class GrGLProgramEffects : public SkRefCnt {
30public:
31    typedef GrGLProgramDataManager::UniformHandle UniformHandle;
32    typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
33    virtual ~GrGLProgramEffects();
34
35    /**
36     * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
37     * available unit to *texUnitIdx when it returns.
38     */
39    void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx);
40
41    /**
42     * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
43     */
44    virtual void setData(GrGpuGL*,
45                         GrGpu::DrawType,
46                         const GrGLProgramDataManager&,
47                         const GrGeometryStage* effectStages) {
48        SkFAIL("For geometry processor only");
49    }
50
51    virtual void setData(GrGpuGL*,
52                         GrGpu::DrawType,
53                         const GrGLProgramDataManager&,
54                         const GrFragmentStage* effectStages[]) = 0;
55
56protected:
57    GrGLProgramEffects(int reserveCount)
58        : fGLProcessors(reserveCount)
59        , fSamplers(reserveCount) {
60    }
61
62    /**
63     * Helper for setData(). Binds all the textures for an effect.
64     */
65    void bindTextures(GrGpuGL*, const GrProcessor&, int effectIdx);
66
67    struct Sampler {
68        SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
69        UniformHandle fUniform;
70        int           fTextureUnit;
71    };
72
73    /*
74     * Helpers for shader builders to build up program effects objects alongside shader code
75     */
76    void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
77    SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
78
79    SkTArray<GrGLProcessor*>               fGLProcessors;
80    SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
81
82private:
83    friend class GrGLProgramBuilder;
84    friend class GrGLFullProgramBuilder;
85    friend class GrGLFragmentOnlyShaderBuilder;
86
87    typedef SkRefCnt INHERITED;
88};
89
90////////////////////////////////////////////////////////////////////////////////
91
92/**
93 * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
94 */
95class GrGLVertexProgramEffects : public GrGLProgramEffects {
96public:
97    virtual void setData(GrGpuGL*,
98                         GrGpu::DrawType,
99                         const GrGLProgramDataManager&,
100                         const GrGeometryStage* effectStages) SK_OVERRIDE;
101
102    virtual void setData(GrGpuGL*,
103                         GrGpu::DrawType,
104                         const GrGLProgramDataManager&,
105                         const GrFragmentStage* effectStages[]) SK_OVERRIDE;
106
107private:
108    GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
109        : INHERITED(reserveCount)
110        , fTransforms(reserveCount)
111        , fHasExplicitLocalCoords(explicitLocalCoords) {
112    }
113
114    struct Transform {
115        Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
116        UniformHandle fHandle;
117        SkMatrix      fCurrentValue;
118    };
119
120    struct PathTransform {
121        PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
122        VaryingHandle fHandle;
123        SkMatrix fCurrentValue;
124        GrSLType fType;
125    };
126
127    /*
128     * These functions are used by the builders to build up program effects along side the shader
129     * code itself
130     */
131    SkSTArray<2, Transform, true>& addTransforms() { return fTransforms.push_back(); }
132    SkTArray<PathTransform, true>& addPathTransforms() { return fPathTransforms.push_back(); }
133
134    /**
135     * Helper for setData(). Sets all the transform matrices for an effect.
136     */
137    void setDataInternal(GrGpuGL* gpu,
138                         GrGpu::DrawType drawType,
139                         const GrGLProgramDataManager& programDataManager,
140                         const GrProcessorStage& effectStage,
141                         int index);
142    void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrProcessorStage&,
143                          int effectIdx);
144    void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&,
145                              const GrProcessorStage&, int effectIdx);
146
147
148    SkTArray<SkSTArray<2, Transform, true> > fTransforms;
149    SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
150    bool                                     fHasExplicitLocalCoords;
151
152    friend class GrGLFullProgramBuilder;
153
154    typedef GrGLProgramEffects INHERITED;
155};
156
157////////////////////////////////////////////////////////////////////////////////
158
159/**
160 * This is a GrGLProgramEffects implementation that does coord transforms with
161 * the the  NV_path_rendering PathTexGen functionality.
162 */
163class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
164public:
165    virtual void setData(GrGpuGL*,
166                         GrGpu::DrawType,
167                         const GrGLProgramDataManager&,
168                         const GrFragmentStage* effectStages[]) SK_OVERRIDE;
169
170private:
171    GrGLPathTexGenProgramEffects(int reserveCount)
172        : INHERITED(reserveCount)
173        , fTransforms(reserveCount) {
174    }
175
176    /**
177     * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
178     */
179    void setPathTexGenState(GrGpuGL*, const GrProcessorStage&, int effectIdx);
180
181    struct Transforms {
182        Transforms(int texCoordIndex)
183            : fTexCoordIndex(texCoordIndex) {}
184        int fTexCoordIndex;
185    };
186
187    /*
188     * Helper for fragment only shader builder to build up the program effects alongside the shader
189     */
190    void addTransforms(int coordIndex) {
191        fTransforms.push_back(Transforms(coordIndex));
192    }
193
194    SkTArray<Transforms> fTransforms;
195
196    friend class GrGLFragmentOnlyProgramBuilder;
197
198    typedef GrGLProgramEffects INHERITED;
199};
200
201#endif
202