1 /* 2 * Copyright 2014 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 "GrGLShaderBuilder.h" 9 #include "GrGLFullProgramBuilder.h" 10 #include "GrGLProgramBuilder.h" 11 #include "../GrGpuGL.h" 12 #include "../GrGLShaderVar.h" 13 14 namespace { 15 inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) { 16 if (kVec2f_GrSLType == type) { 17 return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D"; 18 } else { 19 SkASSERT(kVec3f_GrSLType == type); 20 return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj"; 21 } 22 } 23 void append_texture_lookup(SkString* out, 24 GrGpuGL* gpu, 25 const char* samplerName, 26 const char* coordName, 27 uint32_t configComponentMask, 28 const char* swizzle, 29 GrSLType varyingType = kVec2f_GrSLType) { 30 SkASSERT(coordName); 31 32 out->appendf("%s(%s, %s)", 33 sample_function_name(varyingType, gpu->glslGeneration()), 34 samplerName, 35 coordName); 36 37 char mangledSwizzle[5]; 38 39 // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle 40 // is available. 41 if (!gpu->glCaps().textureSwizzleSupport() && 42 (kA_GrColorComponentFlag == configComponentMask)) { 43 char alphaChar = gpu->glCaps().textureRedSupport() ? 'r' : 'a'; 44 int i; 45 for (i = 0; '\0' != swizzle[i]; ++i) { 46 mangledSwizzle[i] = alphaChar; 47 } 48 mangledSwizzle[i] ='\0'; 49 swizzle = mangledSwizzle; 50 } 51 // For shader prettiness we omit the swizzle rather than appending ".rgba". 52 if (memcmp(swizzle, "rgba", 4)) { 53 out->appendf(".%s", swizzle); 54 } 55 } 56 static const int kVarsPerBlock = 8; 57 } 58 59 GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program) 60 : fProgramBuilder(program) 61 , fInputs(kVarsPerBlock) 62 , fOutputs(kVarsPerBlock) 63 , fFeaturesAddedMask(0) { 64 } 65 66 void GrGLShaderBuilder::declAppend(const GrGLShaderVar& var) { 67 SkString tempDecl; 68 var.appendDecl(fProgramBuilder->ctxInfo(), &tempDecl); 69 this->codeAppendf("%s;", tempDecl.c_str()); 70 } 71 72 void GrGLShaderBuilder::emitFunction(GrSLType returnType, 73 const char* name, 74 int argCnt, 75 const GrGLShaderVar* args, 76 const char* body, 77 SkString* outName) { 78 fFunctions.append(GrGLSLTypeString(returnType)); 79 fProgramBuilder->nameVariable(outName, '\0', name); 80 fFunctions.appendf(" %s", outName->c_str()); 81 fFunctions.append("("); 82 const GrGLContextInfo& ctxInfo = fProgramBuilder->gpu()->ctxInfo(); 83 for (int i = 0; i < argCnt; ++i) { 84 args[i].appendDecl(ctxInfo, &fFunctions); 85 if (i < argCnt - 1) { 86 fFunctions.append(", "); 87 } 88 } 89 fFunctions.append(") {\n"); 90 fFunctions.append(body); 91 fFunctions.append("}\n\n"); 92 } 93 94 void GrGLShaderBuilder::appendTextureLookup(SkString* out, 95 const TextureSampler& sampler, 96 const char* coordName, 97 GrSLType varyingType) const { 98 append_texture_lookup(out, 99 fProgramBuilder->gpu(), 100 fProgramBuilder->getUniformCStr(sampler.fSamplerUniform), 101 coordName, 102 sampler.configComponentMask(), 103 sampler.swizzle(), 104 varyingType); 105 } 106 107 void GrGLShaderBuilder::appendTextureLookup(const TextureSampler& sampler, 108 const char* coordName, 109 GrSLType varyingType) { 110 this->appendTextureLookup(&fCode, sampler, coordName, varyingType); 111 } 112 113 void GrGLShaderBuilder::appendTextureLookupAndModulate(const char* modulation, 114 const TextureSampler& sampler, 115 const char* coordName, 116 GrSLType varyingType) { 117 SkString lookup; 118 this->appendTextureLookup(&lookup, sampler, coordName, varyingType); 119 this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); 120 } 121 122 123 const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) { 124 if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) { 125 if (caps.textureRedSupport()) { 126 static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED }; 127 return gRedSmear; 128 } else { 129 static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA, 130 GR_GL_ALPHA, GR_GL_ALPHA }; 131 return gAlphaSmear; 132 } 133 } else { 134 static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA }; 135 return gStraight; 136 } 137 } 138 139 void GrGLShaderBuilder::addFeature(uint32_t featureBit, const char* extensionName) { 140 if (!(featureBit & fFeaturesAddedMask)) { 141 fExtensions.appendf("#extension %s: require\n", extensionName); 142 fFeaturesAddedMask |= featureBit; 143 } 144 } 145 146 void GrGLShaderBuilder::appendTextureLookup(const char* samplerName, 147 const char* coordName, 148 uint32_t configComponentMask, 149 const char* swizzle) { 150 append_texture_lookup(&fCode, 151 fProgramBuilder->gpu(), 152 samplerName, 153 coordName, 154 configComponentMask, 155 swizzle, 156 kVec2f_GrSLType); 157 } 158 159 /////////////////////////////////////////////////////////////////////////////////////////////////// 160 GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGLFullProgramBuilder* program) 161 : INHERITED(program) 162 , fFullProgramBuilder(program) {} 163