1 /* 2 * Copyright 2015 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/GrGLUniformHandler.h" 9 10 #include "gl/GrGLCaps.h" 11 #include "gl/GrGLGpu.h" 12 #include "gl/builders/GrGLProgramBuilder.h" 13 #include "SkSLCompiler.h" 14 15 #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X) 16 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X) 17 18 bool valid_name(const char* name) { 19 // disallow unknown names that start with "sk_" 20 if (!strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) { 21 return !strcmp(name, SkSL::Compiler::RTADJUST_NAME); 22 } 23 return true; 24 } 25 26 GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray( 27 uint32_t visibility, 28 GrSLType type, 29 GrSLPrecision precision, 30 const char* name, 31 bool mangleName, 32 int arrayCount, 33 const char** outName) { 34 SkASSERT(name && strlen(name)); 35 SkASSERT(valid_name(name)); 36 SkASSERT(0 != visibility); 37 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type)); 38 39 UniformInfo& uni = fUniforms.push_back(); 40 uni.fVariable.setType(type); 41 uni.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 42 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use 43 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB 44 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then 45 // the names will mismatch. I think the correct solution is to have all GPs which need the 46 // uniform view matrix, they should upload the view matrix in their setData along with regular 47 // uniforms. 48 char prefix = 'u'; 49 if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) { 50 prefix = '\0'; 51 } 52 fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName); 53 uni.fVariable.setArrayCount(arrayCount); 54 uni.fVisibility = visibility; 55 uni.fVariable.setPrecision(precision); 56 uni.fLocation = -1; 57 58 if (outName) { 59 *outName = uni.fVariable.c_str(); 60 } 61 return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1); 62 } 63 64 GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(uint32_t visibility, 65 GrSwizzle swizzle, 66 GrSLType type, 67 GrSLPrecision precision, 68 const char* name) { 69 SkASSERT(name && strlen(name)); 70 SkASSERT(0 != visibility); 71 72 SkString mangleName; 73 char prefix = 'u'; 74 fProgramBuilder->nameVariable(&mangleName, prefix, name, true); 75 76 UniformInfo& sampler = fSamplers.push_back(); 77 SkASSERT(GrSLTypeIsCombinedSamplerType(type)); 78 sampler.fVariable.setType(type); 79 sampler.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 80 sampler.fVariable.setPrecision(precision); 81 sampler.fVariable.setName(mangleName); 82 sampler.fLocation = -1; 83 sampler.fVisibility = visibility; 84 fSamplerSwizzles.push_back(swizzle); 85 SkASSERT(fSamplers.count() == fSamplerSwizzles.count()); 86 return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1); 87 } 88 89 GrGLSLUniformHandler::TexelBufferHandle GrGLUniformHandler::addTexelBuffer(uint32_t visibility, 90 GrSLPrecision precision, 91 const char* name) { 92 SkASSERT(name && strlen(name)); 93 SkASSERT(0 != visibility); 94 95 SkString mangleName; 96 char prefix = 'u'; 97 fProgramBuilder->nameVariable(&mangleName, prefix, name, true); 98 99 UniformInfo& texelBuffer = fTexelBuffers.push_back(); 100 texelBuffer.fVariable.setType(kBufferSampler_GrSLType); 101 texelBuffer.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 102 texelBuffer.fVariable.setPrecision(precision); 103 texelBuffer.fVariable.setName(mangleName); 104 texelBuffer.fLocation = -1; 105 texelBuffer.fVisibility = visibility; 106 return GrGLSLUniformHandler::TexelBufferHandle(fTexelBuffers.count() - 1); 107 } 108 109 void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { 110 for (int i = 0; i < fUniforms.count(); ++i) { 111 if (fUniforms[i].fVisibility & visibility) { 112 fUniforms[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 113 out->append(";"); 114 } 115 } 116 for (int i = 0; i < fSamplers.count(); ++i) { 117 if (fSamplers[i].fVisibility & visibility) { 118 fSamplers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 119 out->append(";\n"); 120 } 121 } 122 for (int i = 0; i < fTexelBuffers.count(); ++i) { 123 if (fTexelBuffers[i].fVisibility & visibility) { 124 fTexelBuffers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 125 out->append(";\n"); 126 } 127 } 128 } 129 130 void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) { 131 if (caps.bindUniformLocationSupport()) { 132 int currUniform = 0; 133 for (int i = 0; i < fUniforms.count(); ++i, ++currUniform) { 134 GL_CALL(BindUniformLocation(programID, currUniform, fUniforms[i].fVariable.c_str())); 135 fUniforms[i].fLocation = currUniform; 136 } 137 for (int i = 0; i < fSamplers.count(); ++i, ++currUniform) { 138 GL_CALL(BindUniformLocation(programID, currUniform, fSamplers[i].fVariable.c_str())); 139 fSamplers[i].fLocation = currUniform; 140 } 141 for (int i = 0; i < fTexelBuffers.count(); ++i, ++currUniform) { 142 GL_CALL(BindUniformLocation(programID, currUniform, 143 fTexelBuffers[i].fVariable.c_str())); 144 fTexelBuffers[i].fLocation = currUniform; 145 } 146 } 147 } 148 149 void GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps) { 150 if (!caps.bindUniformLocationSupport()) { 151 int count = fUniforms.count(); 152 for (int i = 0; i < count; ++i) { 153 GrGLint location; 154 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str())); 155 fUniforms[i].fLocation = location; 156 } 157 for (int i = 0; i < fSamplers.count(); ++i) { 158 GrGLint location; 159 GL_CALL_RET(location, GetUniformLocation(programID, fSamplers[i].fVariable.c_str())); 160 fSamplers[i].fLocation = location; 161 } 162 for (int i = 0; i < fTexelBuffers.count(); ++i) { 163 GrGLint location; 164 GL_CALL_RET(location, GetUniformLocation(programID, 165 fTexelBuffers[i].fVariable.c_str())); 166 fTexelBuffers[i].fLocation = location; 167 } 168 } 169 } 170 171 const GrGLGpu* GrGLUniformHandler::glGpu() const { 172 GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder; 173 return glPB->gpu(); 174 } 175