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