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