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