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