1/*
2 * Copyright 2012 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#include "include/core/SkMatrix.h"
9#include "src/gpu/gl/GrGLGpu.h"
10#include "src/gpu/gl/GrGLProgramDataManager.h"
11#include "src/gpu/glsl/GrGLSLUniformHandler.h"
12
13#define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, COUNT) \
14         SkASSERT((COUNT) <= (UNI).fArrayCount || \
15                  (1 == (COUNT) && GrShaderVar::kNonArray == (UNI).fArrayCount))
16
17GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, const UniformInfoArray& uniforms)
18        : fGpu(gpu) {
19    fUniforms.push_back_n(uniforms.count());
20    int i = 0;
21    for (const GLUniformInfo& builderUniform : uniforms.items()) {
22        Uniform& uniform = fUniforms[i++];
23        SkASSERT(GrShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
24                 builderUniform.fVariable.getArrayCount() > 0);
25        SkDEBUGCODE(
26            uniform.fArrayCount = builderUniform.fVariable.getArrayCount();
27            uniform.fType = builderUniform.fVariable.getType();
28        )
29        uniform.fLocation = builderUniform.fLocation;
30    }
31}
32
33void GrGLProgramDataManager::setSamplerUniforms(const UniformInfoArray& samplers,
34                                                int startUnit) const {
35    int i = 0;
36    for (const GLUniformInfo& sampler : samplers.items()) {
37        SkASSERT(sampler.fVisibility);
38        if (kUnusedUniform != sampler.fLocation) {
39            GR_GL_CALL(fGpu->glInterface(), Uniform1i(sampler.fLocation, i + startUnit));
40        }
41        ++i;
42    }
43}
44
45void GrGLProgramDataManager::set1i(UniformHandle u, int32_t i) const {
46    const Uniform& uni = fUniforms[u.toIndex()];
47    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
48    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
49    if (kUnusedUniform != uni.fLocation) {
50        GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fLocation, i));
51    }
52}
53
54void GrGLProgramDataManager::set1iv(UniformHandle u,
55                                    int arrayCount,
56                                    const int32_t v[]) const {
57    const Uniform& uni = fUniforms[u.toIndex()];
58    SkASSERT(uni.fType == kInt_GrSLType || uni.fType == kShort_GrSLType);
59    SkASSERT(arrayCount > 0);
60    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
61    if (kUnusedUniform != uni.fLocation) {
62        GR_GL_CALL(fGpu->glInterface(), Uniform1iv(uni.fLocation, arrayCount, v));
63    }
64}
65
66void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const {
67    const Uniform& uni = fUniforms[u.toIndex()];
68    SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
69    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
70    if (kUnusedUniform != uni.fLocation) {
71        GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fLocation, v0));
72    }
73}
74
75void GrGLProgramDataManager::set1fv(UniformHandle u,
76                                    int arrayCount,
77                                    const float v[]) const {
78    const Uniform& uni = fUniforms[u.toIndex()];
79    SkASSERT(uni.fType == kFloat_GrSLType || uni.fType == kHalf_GrSLType);
80    SkASSERT(arrayCount > 0);
81    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
82    // This assert fires in some instances of the two-pt gradient for its VSParams.
83    // Once the uniform manager is responsible for inserting the duplicate uniform
84    // arrays in VS and FS driver bug workaround, this can be enabled.
85    // this->printUni(uni);
86    if (kUnusedUniform != uni.fLocation) {
87        GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fLocation, arrayCount, v));
88    }
89}
90
91void GrGLProgramDataManager::set2i(UniformHandle u, int32_t i0, int32_t i1) const {
92    const Uniform& uni = fUniforms[u.toIndex()];
93    SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType);
94    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
95    if (kUnusedUniform != uni.fLocation) {
96        GR_GL_CALL(fGpu->glInterface(), Uniform2i(uni.fLocation, i0, i1));
97    }
98}
99
100void GrGLProgramDataManager::set2iv(UniformHandle u,
101                                    int arrayCount,
102                                    const int32_t v[]) const {
103    const Uniform& uni = fUniforms[u.toIndex()];
104    SkASSERT(uni.fType == kInt2_GrSLType || uni.fType == kShort2_GrSLType);
105    SkASSERT(arrayCount > 0);
106    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
107    if (kUnusedUniform != uni.fLocation) {
108        GR_GL_CALL(fGpu->glInterface(), Uniform2iv(uni.fLocation, arrayCount, v));
109    }
110}
111
112void GrGLProgramDataManager::set2f(UniformHandle u, float v0, float v1) const {
113    const Uniform& uni = fUniforms[u.toIndex()];
114    SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
115    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
116    if (kUnusedUniform != uni.fLocation) {
117        GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fLocation, v0, v1));
118    }
119}
120
121void GrGLProgramDataManager::set2fv(UniformHandle u,
122                                    int arrayCount,
123                                    const float v[]) const {
124    const Uniform& uni = fUniforms[u.toIndex()];
125    SkASSERT(uni.fType == kFloat2_GrSLType || uni.fType == kHalf2_GrSLType);
126    SkASSERT(arrayCount > 0);
127    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
128    if (kUnusedUniform != uni.fLocation) {
129        GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fLocation, arrayCount, v));
130    }
131}
132
133void GrGLProgramDataManager::set3i(UniformHandle u, int32_t i0, int32_t i1, int32_t i2) const {
134    const Uniform& uni = fUniforms[u.toIndex()];
135    SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType);
136    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
137    if (kUnusedUniform != uni.fLocation) {
138        GR_GL_CALL(fGpu->glInterface(), Uniform3i(uni.fLocation, i0, i1, i2));
139    }
140}
141
142void GrGLProgramDataManager::set3iv(UniformHandle u,
143                                    int arrayCount,
144                                    const int32_t v[]) const {
145    const Uniform& uni = fUniforms[u.toIndex()];
146    SkASSERT(uni.fType == kInt3_GrSLType || uni.fType == kShort3_GrSLType);
147    SkASSERT(arrayCount > 0);
148    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
149    if (kUnusedUniform != uni.fLocation) {
150        GR_GL_CALL(fGpu->glInterface(), Uniform3iv(uni.fLocation, arrayCount, v));
151    }
152}
153
154void GrGLProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const {
155    const Uniform& uni = fUniforms[u.toIndex()];
156    SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
157    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
158    if (kUnusedUniform != uni.fLocation) {
159        GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fLocation, v0, v1, v2));
160    }
161}
162
163void GrGLProgramDataManager::set3fv(UniformHandle u,
164                                    int arrayCount,
165                                    const float v[]) const {
166    const Uniform& uni = fUniforms[u.toIndex()];
167    SkASSERT(uni.fType == kFloat3_GrSLType || uni.fType == kHalf3_GrSLType);
168    SkASSERT(arrayCount > 0);
169    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
170    if (kUnusedUniform != uni.fLocation) {
171        GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fLocation, arrayCount, v));
172    }
173}
174
175void GrGLProgramDataManager::set4i(UniformHandle u,
176                                   int32_t i0,
177                                   int32_t i1,
178                                   int32_t i2,
179                                   int32_t i3) const {
180    const Uniform& uni = fUniforms[u.toIndex()];
181    SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType);
182    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
183    if (kUnusedUniform != uni.fLocation) {
184        GR_GL_CALL(fGpu->glInterface(), Uniform4i(uni.fLocation, i0, i1, i2, i3));
185    }
186}
187
188void GrGLProgramDataManager::set4iv(UniformHandle u,
189                                    int arrayCount,
190                                    const int32_t v[]) const {
191    const Uniform& uni = fUniforms[u.toIndex()];
192    SkASSERT(uni.fType == kInt4_GrSLType || uni.fType == kShort4_GrSLType);
193    SkASSERT(arrayCount > 0);
194    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
195    if (kUnusedUniform != uni.fLocation) {
196        GR_GL_CALL(fGpu->glInterface(), Uniform4iv(uni.fLocation, arrayCount, v));
197    }
198}
199
200void GrGLProgramDataManager::set4f(UniformHandle u,
201                                   float v0,
202                                   float v1,
203                                   float v2,
204                                   float v3) const {
205    const Uniform& uni = fUniforms[u.toIndex()];
206    SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
207    SkASSERT(GrShaderVar::kNonArray == uni.fArrayCount);
208    if (kUnusedUniform != uni.fLocation) {
209        GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fLocation, v0, v1, v2, v3));
210    }
211}
212
213void GrGLProgramDataManager::set4fv(UniformHandle u,
214                                    int arrayCount,
215                                    const float v[]) const {
216    const Uniform& uni = fUniforms[u.toIndex()];
217    SkASSERT(uni.fType == kFloat4_GrSLType || uni.fType == kHalf4_GrSLType);
218    SkASSERT(arrayCount > 0);
219    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
220    if (kUnusedUniform != uni.fLocation) {
221        GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fLocation, arrayCount, v));
222    }
223}
224
225void GrGLProgramDataManager::setMatrix2f(UniformHandle u, const float matrix[]) const {
226    this->setMatrices<2>(u, 1, matrix);
227}
228
229void GrGLProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const {
230    this->setMatrices<3>(u, 1, matrix);
231}
232
233void GrGLProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const {
234    this->setMatrices<4>(u, 1, matrix);
235}
236
237void GrGLProgramDataManager::setMatrix2fv(UniformHandle u, int arrayCount, const float m[]) const {
238    this->setMatrices<2>(u, arrayCount, m);
239}
240
241void GrGLProgramDataManager::setMatrix3fv(UniformHandle u, int arrayCount, const float m[]) const {
242    this->setMatrices<3>(u, arrayCount, m);
243}
244
245void GrGLProgramDataManager::setMatrix4fv(UniformHandle u, int arrayCount, const float m[]) const {
246    this->setMatrices<4>(u, arrayCount, m);
247}
248
249template<int N> struct set_uniform_matrix;
250
251template<int N> inline void GrGLProgramDataManager::setMatrices(UniformHandle u,
252                                                                int arrayCount,
253                                                                const float matrices[]) const {
254    const Uniform& uni = fUniforms[u.toIndex()];
255    SkASSERT(uni.fType == kFloat2x2_GrSLType + (N - 2) ||
256             uni.fType == kHalf2x2_GrSLType + (N - 2));
257    SkASSERT(arrayCount > 0);
258    ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount);
259    if (kUnusedUniform != uni.fLocation) {
260        set_uniform_matrix<N>::set(fGpu->glInterface(), uni.fLocation, arrayCount, matrices);
261    }
262}
263
264template<> struct set_uniform_matrix<2> {
265    inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
266        GR_GL_CALL(gli, UniformMatrix2fv(loc, cnt, false, m));
267    }
268};
269
270template<> struct set_uniform_matrix<3> {
271    inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
272        GR_GL_CALL(gli, UniformMatrix3fv(loc, cnt, false, m));
273    }
274};
275
276template<> struct set_uniform_matrix<4> {
277    inline static void set(const GrGLInterface* gli, const GrGLint loc, int cnt, const float m[]) {
278        GR_GL_CALL(gli, UniformMatrix4fv(loc, cnt, false, m));
279    }
280};
281