GrGLShaderBuilder.cpp revision a1bf0fffff821d9c11809c89bd98d4ced480421a
1f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com/* 2f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * Copyright 2012 Google Inc. 3f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * 4f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be 5f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * found in the LICENSE file. 6f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com */ 7f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com 8f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com#include "gl/GrGLShaderBuilder.h" 95259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com#include "gl/GrGLProgram.h" 10dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com#include "gl/GrGLUniformHandle.h" 11a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com#include "GrTexture.h" 12f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com 13f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com// number of each input/output type in a single allocation block 14eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.comstatic const int kVarsPerBlock = 8; 15f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com 16f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com// except FS outputs where we expect 2 at most. 17eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.comstatic const int kMaxFSOutputs = 2; 18f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com 19d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com// ES2 FS only guarantees mediump and lowp support 20d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.comstatic const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 21d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com 22dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comtypedef GrGLUniformManager::UniformHandle UniformHandle; 23dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com/////////////////////////////////////////////////////////////////////////////// 24dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com 25a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comstatic SkString build_sampler_string(GrGLShaderBuilder::SamplerMode samplerMode) { 26a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com SkString sampler("texture2D"); 27a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com switch (samplerMode) { 28a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com case GrGLShaderBuilder::kDefault_SamplerMode: 29a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com break; 30a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com case GrGLShaderBuilder::kProj_SamplerMode: 31a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com sampler.append("Proj"); 32a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com break; 33a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com case GrGLShaderBuilder::kExplicitDivide_SamplerMode: 34a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com break; 35a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com } 36a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 37a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com return sampler; 38a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com} 39a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 40a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comstatic bool texture_requires_alpha_to_red_swizzle(const GrGLCaps& caps, 41a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com const GrTextureAccess& access) { 42a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com return GrPixelConfigIsAlphaOnly(access.getTexture()->config()) && caps.textureRedSupport() && 43a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com access.referencesAlpha(); 44a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com} 45a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 46a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comstatic SkString build_swizzle_string(const GrTextureAccess& textureAccess, 47a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com const GrGLCaps& caps) { 48a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com const GrTextureAccess::Swizzle& swizzle = textureAccess.getSwizzle(); 49a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com if (0 == swizzle[0]) { 50a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com return SkString(""); 51a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com } 52a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 53a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com SkString swizzleOut("."); 54a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com bool alphaIsRed = texture_requires_alpha_to_red_swizzle(caps, textureAccess); 55a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com for (int offset = 0; offset < 4 && swizzle[offset]; ++offset) { 56a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com if (alphaIsRed && 'a' == swizzle[offset]) { 57a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com swizzleOut.appendf("r"); 58a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com } else { 59a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com swizzleOut.appendf("%c", swizzle[offset]); 60a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com } 61a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com } 62a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 63a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com return swizzleOut; 64a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com} 65a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 66a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com/////////////////////////////////////////////////////////////////////////////// 67a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 689c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// Architectural assumption: always 2-d input coords. 699c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// Likely to become non-constant and non-static, perhaps even 709c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com// varying by stage, if we use 1D textures for gradients! 719c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com//const int GrGLShaderBuilder::fCoordDims = 2; 729c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com 73dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comGrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctx, GrGLUniformManager& uniformManager) 74032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com : fUniforms(kVarsPerBlock) 75eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com , fVSAttrs(kVarsPerBlock) 76eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com , fVSOutputs(kVarsPerBlock) 77eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com , fGSInputs(kVarsPerBlock) 78eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com , fGSOutputs(kVarsPerBlock) 79eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com , fFSInputs(kVarsPerBlock) 80eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com , fFSOutputs(kMaxFSOutputs) 81040c41a97c58b069015be3f5062eeb6ffe5adbfdtomhudson@google.com , fUsesGS(false) 829c639a406eec42c8f5169bd78ad93e58f00ea9f6tomhudson@google.com , fVaryingDims(0) 83ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com , fComplexCoord(false) 84dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com , fContext(ctx) 85777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com , fUniformManager(uniformManager) 86777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com , fCurrentStage(kNonStageIdx) { 87f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com} 88f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com 895259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) { 905259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com static const uint32_t kMulByAlphaMask = 915259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com (GrGLProgram::StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag | 925259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLProgram::StageDesc::kMulRGBByAlpha_RoundDown_InConfigFlag); 935259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com 945259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fSwizzle = ""; 955259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com if (configFlags & GrGLProgram::StageDesc::kSwapRAndB_InConfigFlag) { 965259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrAssert(!(configFlags & 975259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag)); 985259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrAssert(!(configFlags & 995259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLProgram::StageDesc::kSmearRed_InConfigFlag)); 1005259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fSwizzle = ".bgra"; 1015259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com } else if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) { 1025259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrAssert(!(configFlags & kMulByAlphaMask)); 1035259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrAssert(!(configFlags & 1045259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLProgram::StageDesc::kSmearRed_InConfigFlag)); 1055259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fSwizzle = ".aaaa"; 1065259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) { 1075259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrAssert(!(configFlags & kMulByAlphaMask)); 1085259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrAssert(!(configFlags & 1095259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag)); 1105259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fSwizzle = ".rrrr"; 1115259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com } 1125259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com} 1135259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com 1145259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::computeModulate(const char* fsInColor) { 1155259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com if (NULL != fsInColor) { 1165259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fModulate.printf(" * %s", fsInColor); 117e9b3f7dba0d721c60d296b09a578fbc6adaa7c63robertphillips@google.com } else { 118e9b3f7dba0d721c60d296b09a578fbc6adaa7c63robertphillips@google.com fModulate.reset(); 1195259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com } 1205259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com} 1215259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com 122de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.comvoid GrGLShaderBuilder::setupTextureAccess(int stageNum) { 123f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com SkString retval; 1245259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com 125de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com SamplerMode mode = kDefault_SamplerMode; 126de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com // FIXME: we aren't currently using Proj. 127de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com if (fVaryingDims != fCoordDims) { 128de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com mode = kExplicitDivide_SamplerMode; 129de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com } 130de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com 131de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com switch (mode) { 1325259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com case kDefault_SamplerMode: 1335440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com GrAssert(fVaryingDims == fCoordDims); 1345259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com // Do nothing 1355259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com break; 1365440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com case kProj_SamplerMode: 137de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com // Do nothing 1385440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com break; 1395259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com case kExplicitDivide_SamplerMode: 1405259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com retval = "inCoord"; 1415440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com retval.appendS32(stageNum); 1425440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com fFSCode.appendf("\t%s %s = %s%s / %s%s;\n", 1435259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLShaderVar::TypeString 1445259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com (GrSLFloatVectorType(fCoordDims)), 1455259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com retval.c_str(), 1465259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fSampleCoords.c_str(), 1475259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLSLVectorNonhomogCoords(fVaryingDims), 1485259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fSampleCoords.c_str(), 1495259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com GrGLSLVectorHomogCoord(fVaryingDims)); 1505259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fSampleCoords = retval; 1515259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com break; 1525259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com } 153de788237c2ecf64fcc71ffb1a2355eb1e0fb5e0ctomhudson@google.com fTexFunc = build_sampler_string(mode); 1545440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com fComplexCoord = false; 1555259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com} 1565259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com 1575259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::emitTextureLookup(const char* samplerName, 1585259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com const char* coordName) { 1595259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com if (NULL == coordName) { 1605259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com coordName = fSampleCoords.c_str(); 1615259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com } 1625440f06331b46d3f132a7247a4e414d9d4bc66e7tomhudson@google.com fFSCode.appendf("%s(%s, %s)", fTexFunc.c_str(), samplerName, coordName); 1635259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com} 1645259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com 1655259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.comvoid GrGLShaderBuilder::emitDefaultFetch(const char* outColor, 1665259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com const char* samplerName) { 1675259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fFSCode.appendf("\t%s = ", outColor); 1685259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com this->emitTextureLookup(samplerName); 1695259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str()); 1705259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com} 1715259814305e3290dea3b197301f7824a14c5fa6ftomhudson@google.com 172a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comvoid GrGLShaderBuilder::emitCustomTextureLookup(SamplerMode samplerMode, 173a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com const GrTextureAccess& textureAccess, 174a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com const char* samplerName, 175a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com const char* coordName) { 176a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com GrAssert(samplerName && coordName); 177a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com SkString sampler = build_sampler_string(samplerMode); 178a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com SkString swizzle = build_swizzle_string(textureAccess, fContext.caps()); 179a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 180a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com fFSCode.appendf("%s( %s, %s)%s;\n", sampler.c_str(), samplerName, 181a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com coordName, swizzle.c_str()); 182a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com} 183a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 184a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.comGrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access, 185a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com const GrGLCaps& caps) { 186a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com GrCustomStage::StageKey key = 0; 187d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com 188a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com // Assume that swizzle support implies that we never have to modify a shader to adjust 189a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com // for texture format/swizzle settings. 190a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com if (caps.textureSwizzleSupport()) { 191a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com return key; 192a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com } 193a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 194a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com if (texture_requires_alpha_to_red_swizzle(caps, access)) { 195a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com key = 1; 196a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com } 197a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 198a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com return key; 199a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com} 200a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 201777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.comGrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility, 202777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com GrSLType type, 203777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com const char* name, 204777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com int count, 205777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com const char** outName) { 206242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com GrAssert(name && strlen(name)); 207eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com static const uint32_t kVisibilityMask = kVertex_ShaderType | kFragment_ShaderType; 208eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com GrAssert(0 == (~kVisibilityMask & visibility)); 209eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com GrAssert(0 != visibility); 210242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com 211dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com BuilderUniform& uni = fUniforms.push_back(); 212032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com UniformHandle h = index_to_handle(fUniforms.count() - 1); 213dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com GR_DEBUGCODE(UniformHandle h2 =) 214dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com fUniformManager.appendUniform(type, count); 215dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com // We expect the uniform manager to initially have no uniforms and that all uniforms are added 216dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com // by this function. Therefore, the handles should match. 217dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com GrAssert(h2 == h); 218032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com uni.fVariable.setType(type); 219032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier); 220777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com SkString* uniName = uni.fVariable.accessName(); 221777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com if (kNonStageIdx == fCurrentStage) { 222777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com uniName->printf("u%s", name); 223777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com } else { 224777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com uniName->printf("u%s%d", name, fCurrentStage); 225242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com } 226032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com uni.fVariable.setArrayCount(count); 227032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com uni.fVisibility = visibility; 228242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com 229032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com // If it is visible in both the VS and FS, the precision must match. 230032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com // We declare a default FS precision, but not a default VS. So set the var 231032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com // to use the default FS precision. 232eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com if ((kVertex_ShaderType | kFragment_ShaderType) == visibility) { 233d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com // the fragment and vertex precisions must match 234032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com uni.fVariable.setPrecision(kDefaultFragmentPrecision); 235242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com } 236242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com 237777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com if (NULL != outName) { 238777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com *outName = uni.fVariable.c_str(); 239777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com } 240777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com 241032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com return h; 242032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com} 243032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com 244032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comconst GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) const { 245032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com return fUniforms[handle_to_index(u)].fVariable; 246242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com} 24723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com 24823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.comvoid GrGLShaderBuilder::addVarying(GrSLType type, 24923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com const char* name, 25023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com const char** vsOutName, 25123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com const char** fsInName) { 25223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fVSOutputs.push_back(); 25323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fVSOutputs.back().setType(type); 25423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); 255777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com if (kNonStageIdx == fCurrentStage) { 256777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com fVSOutputs.back().accessName()->printf("v%s", name); 257777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com } else { 258777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com fVSOutputs.back().accessName()->printf("v%s%d", name, fCurrentStage); 259777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com } 26023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com if (vsOutName) { 26123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com *vsOutName = fVSOutputs.back().getName().c_str(); 26223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com } 26323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com // input to FS comes either from VS or GS 264f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com const SkString* fsName; 26523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com if (fUsesGS) { 26623cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com // if we have a GS take each varying in as an array 26723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com // and output as non-array. 26823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fGSInputs.push_back(); 26923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fGSInputs.back().setType(type); 27023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); 27123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fGSInputs.back().setUnsizedArray(); 27223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com *fGSInputs.back().accessName() = fVSOutputs.back().getName(); 27323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fGSOutputs.push_back(); 27423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fGSOutputs.back().setType(type); 27523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier); 276d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com if (kNonStageIdx == fCurrentStage) { 277d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com fGSOutputs.back().accessName()->printf("g%s", name); 278d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com } else { 279d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com fGSOutputs.back().accessName()->printf("g%s%d", name, fCurrentStage); 280d472620458e2383e6dd949f4e1aaf61160717ffebsalomon@google.com } 28123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fsName = fGSOutputs.back().accessName(); 28223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com } else { 28323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fsName = fVSOutputs.back().accessName(); 28423cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com } 28523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fFSInputs.push_back(); 28623cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fFSInputs.back().setType(type); 28723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier); 28823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com fFSInputs.back().setName(*fsName); 28923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com if (fsInName) { 29023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com *fsInName = fsName->c_str(); 29123cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com } 29223cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com} 29323cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com 294a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.comvoid GrGLShaderBuilder::emitFunction(ShaderType shader, 295a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com GrSLType returnType, 296a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com const char* name, 297a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com int argCnt, 298a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com const GrGLShaderVar* args, 299a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com const char* body, 300a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com SkString* outName) { 301a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com GrAssert(kFragment_ShaderType == shader); 302a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com fFSFunctions.append(GrGLShaderVar::TypeString(returnType)); 303a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com if (kNonStageIdx != fCurrentStage) { 304a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com outName->printf(" %s_%d", name, fCurrentStage); 305a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com } else { 306a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com *outName = name; 307a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com } 308a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com fFSFunctions.append(*outName); 309a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com fFSFunctions.append("("); 310a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com for (int i = 0; i < argCnt; ++i) { 311a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com args[i].appendDecl(fContext, &fFSFunctions); 312a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com if (i < argCnt - 1) { 313a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com fFSFunctions.append(", "); 314a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com } 315a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com } 316a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com fFSFunctions.append(") {\n"); 317a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com fFSFunctions.append(body); 318a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com fFSFunctions.append("}\n\n"); 319a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com} 32023cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com 321ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comnamespace { 322d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com 323d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.cominline void append_default_precision_qualifier(GrGLShaderVar::Precision p, 324d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com GrGLBinding binding, 325d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com SkString* str) { 326d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com // Desktop GLSL has added precision qualifiers but they don't do anything. 327d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com if (kES2_GrGLBinding == binding) { 328d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com switch (p) { 329d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com case GrGLShaderVar::kHigh_Precision: 330d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com str->append("precision highp float;\n"); 331d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com break; 332d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com case GrGLShaderVar::kMedium_Precision: 333d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com str->append("precision mediump float;\n"); 334d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com break; 335d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com case GrGLShaderVar::kLow_Precision: 336d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com str->append("precision lowp float;\n"); 337d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com break; 338d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com case GrGLShaderVar::kDefault_Precision: 339d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com GrCrash("Default precision now allowed."); 340d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com default: 341d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com GrCrash("Unknown precision value."); 342d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com } 343d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com } 344d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com} 345032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com} 346d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com 347032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comvoid GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const { 348ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com for (int i = 0; i < vars.count(); ++i) { 349032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com vars[i].appendDecl(fContext, out); 350a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com out->append(";\n"); 351ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com } 352ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com} 353032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com 354032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comvoid GrGLShaderBuilder::appendUniformDecls(ShaderType stype, SkString* out) const { 355032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com for (int i = 0; i < fUniforms.count(); ++i) { 356032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com if (fUniforms[i].fVisibility & stype) { 357032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com fUniforms[i].fVariable.appendDecl(fContext, out); 358a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com out->append(";\n"); 359032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com } 360032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com } 361ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com} 362ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com 363ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comvoid GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const { 364ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com switch (type) { 365ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com case kVertex_ShaderType: 366ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com *shaderStr = fHeader; 367032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendUniformDecls(kVertex_ShaderType, shaderStr); 368032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendDecls(fVSAttrs, shaderStr); 369032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendDecls(fVSOutputs, shaderStr); 370ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com shaderStr->append(fVSCode); 371ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com break; 372ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com case kGeometry_ShaderType: 373ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com if (fUsesGS) { 374ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com *shaderStr = fHeader; 375ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com shaderStr->append(fGSHeader); 376032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendDecls(fGSInputs, shaderStr); 377032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendDecls(fGSOutputs, shaderStr); 378ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com shaderStr->append(fGSCode); 379ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com } else { 380ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com shaderStr->reset(); 381ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com } 382ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com break; 383ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com case kFragment_ShaderType: 384ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com *shaderStr = fHeader; 385d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com append_default_precision_qualifier(kDefaultFragmentPrecision, 386d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com fContext.binding(), 387d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com shaderStr); 388032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendUniformDecls(kFragment_ShaderType, shaderStr); 389032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendDecls(fFSInputs, shaderStr); 390ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com // We shouldn't have declared outputs on 1.10 391ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com GrAssert(k110_GrGLSLGeneration != fContext.glslGeneration() || fFSOutputs.empty()); 392032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com this->appendDecls(fFSOutputs, shaderStr); 393ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com shaderStr->append(fFSFunctions); 394ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com shaderStr->append(fFSCode); 395ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com break; 396ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com } 397ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.com } 398d7727ceb82e271f8b5580c51571c57b09c5e3cedbsalomon@google.com 399dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.comvoid GrGLShaderBuilder::finished(GrGLuint programID) { 400dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com fUniformManager.getUniformLocations(programID, fUniforms); 401dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com} 402