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 "SkMatrix.h" 9#include "gl/GrGLProgramDataManager.h" 10#include "gl/GrGLGpu.h" 11#include "glsl/GrGLSLUniformHandler.h" 12 13#define ASSERT_ARRAY_UPLOAD_IN_BOUNDS(UNI, COUNT) \ 14 SkASSERT(arrayCount <= uni.fArrayCount || \ 15 (1 == arrayCount && GrGLSLShaderVar::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 int count = uniforms.count(); 23 fUniforms.push_back_n(count); 24 for (int i = 0; i < count; i++) { 25 Uniform& uniform = fUniforms[i]; 26 const UniformInfo& builderUniform = uniforms[i]; 27 SkASSERT(GrGLSLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() || 28 builderUniform.fVariable.getArrayCount() > 0); 29 SkDEBUGCODE( 30 uniform.fArrayCount = builderUniform.fVariable.getArrayCount(); 31 uniform.fType = builderUniform.fVariable.getType(); 32 ); 33 // TODO: Move the Xoom uniform array in both FS and VS bug workaround here. 34 35 if (kVertex_GrShaderFlag & builderUniform.fVisibility) { 36 uniform.fVSLocation = builderUniform.fLocation; 37 } else { 38 uniform.fVSLocation = kUnusedUniform; 39 } 40 if (kFragment_GrShaderFlag & builderUniform.fVisibility) { 41 uniform.fFSLocation = builderUniform.fLocation; 42 } else { 43 uniform.fFSLocation = kUnusedUniform; 44 } 45 } 46 47 // NVPR programs have separable varyings 48 count = pathProcVaryings.count(); 49 fPathProcVaryings.push_back_n(count); 50 for (int i = 0; i < count; i++) { 51 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport()); 52 PathProcVarying& pathProcVarying = fPathProcVaryings[i]; 53 const VaryingInfo& builderPathProcVarying = pathProcVaryings[i]; 54 SkASSERT(GrGLSLShaderVar::kNonArray == builderPathProcVarying.fVariable.getArrayCount() || 55 builderPathProcVarying.fVariable.getArrayCount() > 0); 56 SkDEBUGCODE( 57 pathProcVarying.fArrayCount = builderPathProcVarying.fVariable.getArrayCount(); 58 pathProcVarying.fType = builderPathProcVarying.fVariable.getType(); 59 ); 60 pathProcVarying.fLocation = builderPathProcVarying.fLocation; 61 } 62} 63 64void GrGLProgramDataManager::setSampler(UniformHandle u, int texUnit) const { 65 const Uniform& uni = fUniforms[u.toIndex()]; 66 SkASSERT(uni.fType == kSampler2D_GrSLType || uni.fType == kSamplerExternal_GrSLType || 67 uni.fType == kSampler2DRect_GrSLType); 68 SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount); 69 // FIXME: We still insert a single sampler uniform for every stage. If the shader does not 70 // reference the sampler then the compiler may have optimized it out. Uncomment this assert 71 // once stages insert their own samplers. 72 // this->printUnused(uni); 73 if (kUnusedUniform != uni.fFSLocation) { 74 GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fFSLocation, texUnit)); 75 } 76 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 77 GR_GL_CALL(fGpu->glInterface(), Uniform1i(uni.fVSLocation, texUnit)); 78 } 79} 80 81void GrGLProgramDataManager::set1f(UniformHandle u, float v0) const { 82 const Uniform& uni = fUniforms[u.toIndex()]; 83 SkASSERT(uni.fType == kFloat_GrSLType); 84 SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount); 85 SkDEBUGCODE(this->printUnused(uni);) 86 if (kUnusedUniform != uni.fFSLocation) { 87 GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fFSLocation, v0)); 88 } 89 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 90 GR_GL_CALL(fGpu->glInterface(), Uniform1f(uni.fVSLocation, v0)); 91 } 92} 93 94void GrGLProgramDataManager::set1fv(UniformHandle u, 95 int arrayCount, 96 const float v[]) const { 97 const Uniform& uni = fUniforms[u.toIndex()]; 98 SkASSERT(uni.fType == kFloat_GrSLType); 99 SkASSERT(arrayCount > 0); 100 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); 101 // This assert fires in some instances of the two-pt gradient for its VSParams. 102 // Once the uniform manager is responsible for inserting the duplicate uniform 103 // arrays in VS and FS driver bug workaround, this can be enabled. 104 // this->printUni(uni); 105 if (kUnusedUniform != uni.fFSLocation) { 106 GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fFSLocation, arrayCount, v)); 107 } 108 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 109 GR_GL_CALL(fGpu->glInterface(), Uniform1fv(uni.fVSLocation, arrayCount, v)); 110 } 111} 112 113void GrGLProgramDataManager::set2f(UniformHandle u, float v0, float v1) const { 114 const Uniform& uni = fUniforms[u.toIndex()]; 115 SkASSERT(uni.fType == kVec2f_GrSLType); 116 SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount); 117 SkDEBUGCODE(this->printUnused(uni);) 118 if (kUnusedUniform != uni.fFSLocation) { 119 GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fFSLocation, v0, v1)); 120 } 121 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 122 GR_GL_CALL(fGpu->glInterface(), Uniform2f(uni.fVSLocation, v0, v1)); 123 } 124} 125 126void GrGLProgramDataManager::set2fv(UniformHandle u, 127 int arrayCount, 128 const float v[]) const { 129 const Uniform& uni = fUniforms[u.toIndex()]; 130 SkASSERT(uni.fType == kVec2f_GrSLType); 131 SkASSERT(arrayCount > 0); 132 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); 133 SkDEBUGCODE(this->printUnused(uni);) 134 if (kUnusedUniform != uni.fFSLocation) { 135 GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fFSLocation, arrayCount, v)); 136 } 137 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 138 GR_GL_CALL(fGpu->glInterface(), Uniform2fv(uni.fVSLocation, arrayCount, v)); 139 } 140} 141 142void GrGLProgramDataManager::set3f(UniformHandle u, float v0, float v1, float v2) const { 143 const Uniform& uni = fUniforms[u.toIndex()]; 144 SkASSERT(uni.fType == kVec3f_GrSLType); 145 SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount); 146 SkDEBUGCODE(this->printUnused(uni);) 147 if (kUnusedUniform != uni.fFSLocation) { 148 GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fFSLocation, v0, v1, v2)); 149 } 150 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 151 GR_GL_CALL(fGpu->glInterface(), Uniform3f(uni.fVSLocation, v0, v1, v2)); 152 } 153} 154 155void GrGLProgramDataManager::set3fv(UniformHandle u, 156 int arrayCount, 157 const float v[]) const { 158 const Uniform& uni = fUniforms[u.toIndex()]; 159 SkASSERT(uni.fType == kVec3f_GrSLType); 160 SkASSERT(arrayCount > 0); 161 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); 162 SkDEBUGCODE(this->printUnused(uni);) 163 if (kUnusedUniform != uni.fFSLocation) { 164 GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fFSLocation, arrayCount, v)); 165 } 166 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 167 GR_GL_CALL(fGpu->glInterface(), Uniform3fv(uni.fVSLocation, arrayCount, v)); 168 } 169} 170 171void GrGLProgramDataManager::set4f(UniformHandle u, 172 float v0, 173 float v1, 174 float v2, 175 float v3) const { 176 const Uniform& uni = fUniforms[u.toIndex()]; 177 SkASSERT(uni.fType == kVec4f_GrSLType); 178 SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount); 179 SkDEBUGCODE(this->printUnused(uni);) 180 if (kUnusedUniform != uni.fFSLocation) { 181 GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fFSLocation, v0, v1, v2, v3)); 182 } 183 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 184 GR_GL_CALL(fGpu->glInterface(), Uniform4f(uni.fVSLocation, v0, v1, v2, v3)); 185 } 186} 187 188void GrGLProgramDataManager::set4fv(UniformHandle u, 189 int arrayCount, 190 const float v[]) const { 191 const Uniform& uni = fUniforms[u.toIndex()]; 192 SkASSERT(uni.fType == kVec4f_GrSLType); 193 SkASSERT(arrayCount > 0); 194 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); 195 SkDEBUGCODE(this->printUnused(uni);) 196 if (kUnusedUniform != uni.fFSLocation) { 197 GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fFSLocation, arrayCount, v)); 198 } 199 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 200 GR_GL_CALL(fGpu->glInterface(), Uniform4fv(uni.fVSLocation, arrayCount, v)); 201 } 202} 203 204void GrGLProgramDataManager::setMatrix3f(UniformHandle u, const float matrix[]) const { 205 const Uniform& uni = fUniforms[u.toIndex()]; 206 SkASSERT(uni.fType == kMat33f_GrSLType); 207 SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount); 208 SkDEBUGCODE(this->printUnused(uni);) 209 if (kUnusedUniform != uni.fFSLocation) { 210 GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fFSLocation, 1, false, matrix)); 211 } 212 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 213 GR_GL_CALL(fGpu->glInterface(), UniformMatrix3fv(uni.fVSLocation, 1, false, matrix)); 214 } 215} 216 217void GrGLProgramDataManager::setMatrix4f(UniformHandle u, const float matrix[]) const { 218 const Uniform& uni = fUniforms[u.toIndex()]; 219 SkASSERT(uni.fType == kMat44f_GrSLType); 220 SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount); 221 SkDEBUGCODE(this->printUnused(uni);) 222 if (kUnusedUniform != uni.fFSLocation) { 223 GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fFSLocation, 1, false, matrix)); 224 } 225 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 226 GR_GL_CALL(fGpu->glInterface(), UniformMatrix4fv(uni.fVSLocation, 1, false, matrix)); 227 } 228} 229 230void GrGLProgramDataManager::setMatrix3fv(UniformHandle u, 231 int arrayCount, 232 const float matrices[]) const { 233 const Uniform& uni = fUniforms[u.toIndex()]; 234 SkASSERT(uni.fType == kMat33f_GrSLType); 235 SkASSERT(arrayCount > 0); 236 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); 237 SkDEBUGCODE(this->printUnused(uni);) 238 if (kUnusedUniform != uni.fFSLocation) { 239 GR_GL_CALL(fGpu->glInterface(), 240 UniformMatrix3fv(uni.fFSLocation, arrayCount, false, matrices)); 241 } 242 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 243 GR_GL_CALL(fGpu->glInterface(), 244 UniformMatrix3fv(uni.fVSLocation, arrayCount, false, matrices)); 245 } 246} 247 248void GrGLProgramDataManager::setMatrix4fv(UniformHandle u, 249 int arrayCount, 250 const float matrices[]) const { 251 const Uniform& uni = fUniforms[u.toIndex()]; 252 SkASSERT(uni.fType == kMat44f_GrSLType); 253 SkASSERT(arrayCount > 0); 254 ASSERT_ARRAY_UPLOAD_IN_BOUNDS(uni, arrayCount); 255 SkDEBUGCODE(this->printUnused(uni);) 256 if (kUnusedUniform != uni.fFSLocation) { 257 GR_GL_CALL(fGpu->glInterface(), 258 UniformMatrix4fv(uni.fFSLocation, arrayCount, false, matrices)); 259 } 260 if (kUnusedUniform != uni.fVSLocation && uni.fVSLocation != uni.fFSLocation) { 261 GR_GL_CALL(fGpu->glInterface(), 262 UniformMatrix4fv(uni.fVSLocation, arrayCount, false, matrices)); 263 } 264} 265 266void GrGLProgramDataManager::setPathFragmentInputTransform(VaryingHandle u, 267 int components, 268 const SkMatrix& matrix) const { 269 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport()); 270 const PathProcVarying& fragmentInput = fPathProcVaryings[u.toIndex()]; 271 272 SkASSERT((components == 2 && fragmentInput.fType == kVec2f_GrSLType) || 273 (components == 3 && fragmentInput.fType == kVec3f_GrSLType)); 274 275 fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID, 276 fragmentInput.fLocation, 277 GR_GL_OBJECT_LINEAR, 278 components, 279 matrix); 280} 281 282#ifdef SK_DEBUG 283void GrGLProgramDataManager::printUnused(const Uniform& uni) const { 284 if (kUnusedUniform == uni.fFSLocation && kUnusedUniform == uni.fVSLocation) { 285 GrCapsDebugf(fGpu->caps(), "Unused uniform in shader\n"); 286 } 287} 288#endif 289