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 "GrGLFragmentShaderBuilder.h" 9 #include "GrGLShaderStringBuilder.h" 10 #include "GrGLProgramBuilder.h" 11 #include "../GrGpuGL.h" 12 13 namespace { 14 #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) 15 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) 16 // ES2 FS only guarantees mediump and lowp support 17 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision; 18 static const char kDstCopyColorName[] = "_dstColor"; 19 inline const char* declared_color_output_name() { return "fsColorOut"; } 20 inline const char* dual_source_output_name() { return "dualSourceOut"; } 21 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p, 22 GrGLStandard standard, 23 SkString* str) { 24 // Desktop GLSL has added precision qualifiers but they don't do anything. 25 if (kGLES_GrGLStandard == standard) { 26 switch (p) { 27 case GrGLShaderVar::kHigh_Precision: 28 str->append("precision highp float;\n"); 29 break; 30 case GrGLShaderVar::kMedium_Precision: 31 str->append("precision mediump float;\n"); 32 break; 33 case GrGLShaderVar::kLow_Precision: 34 str->append("precision lowp float;\n"); 35 break; 36 case GrGLShaderVar::kDefault_Precision: 37 SkFAIL("Default precision now allowed."); 38 default: 39 SkFAIL("Unknown precision value."); 40 } 41 } 42 } 43 } 44 45 GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead( 46 const GrTexture* dstCopy, const GrGLCaps& caps) { 47 uint32_t key = kYesDstRead_DstReadKeyBit; 48 if (caps.fbFetchSupport()) { 49 return key; 50 } 51 SkASSERT(dstCopy); 52 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { 53 // The fact that the config is alpha-only must be considered when generating code. 54 key |= kUseAlphaConfig_DstReadKeyBit; 55 } 56 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { 57 key |= kTopLeftOrigin_DstReadKeyBit; 58 } 59 SkASSERT(static_cast<DstReadKey>(key) == key); 60 return static_cast<DstReadKey>(key); 61 } 62 63 GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition( 64 const GrRenderTarget* dst, const GrGLCaps&) { 65 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { 66 return kTopLeftFragPosRead_FragPosKey; 67 } else { 68 return kBottomLeftFragPosRead_FragPosKey; 69 } 70 } 71 72 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, 73 const GrGLProgramDesc& desc) 74 : INHERITED(program) 75 , fHasCustomColorOutput(false) 76 , fHasSecondaryOutput(false) 77 , fSetupFragPosition(false) 78 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){ 79 } 80 81 const char* GrGLFragmentShaderBuilder::dstColor() { 82 if (fProgramBuilder->fCodeStage.inStageCode()) { 83 const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->getProcessor(); 84 // TODO GPs can't read dst color, and full program builder only returns a pointer to the 85 // base fragment shader builder which does not have this function. Unfortunately, 86 // the code stage class only has a GrProcessor pointer so this is required for the time 87 // being 88 if (!static_cast<const GrFragmentProcessor*>(effect)->willReadDstColor()) { 89 SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating GrProcessor " 90 "did not request access."); 91 return ""; 92 } 93 } 94 95 GrGpuGL* gpu = fProgramBuilder->gpu(); 96 if (gpu->glCaps().fbFetchSupport()) { 97 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), 98 gpu->glCaps().fbFetchExtensionString()); 99 return gpu->glCaps().fbFetchColorName(); 100 } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { 101 return kDstCopyColorName; 102 } else { 103 return ""; 104 } 105 } 106 107 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { 108 switch (feature) { 109 case kStandardDerivatives_GLSLFeature: { 110 GrGpuGL* gpu = fProgramBuilder->gpu(); 111 if (!gpu->glCaps().shaderDerivativeSupport()) { 112 return false; 113 } 114 if (kGLES_GrGLStandard == gpu->glStandard()) { 115 this->addFeature(1 << kStandardDerivatives_GLSLFeature, 116 "GL_OES_standard_derivatives"); 117 } 118 return true; 119 } 120 default: 121 SkFAIL("Unexpected GLSLFeature requested."); 122 return false; 123 } 124 } 125 126 SkString GrGLFragmentShaderBuilder::ensureFSCoords2D( 127 const GrGLProcessor::TransformedCoordsArray& coords, int index) { 128 if (kVec3f_GrSLType != coords[index].getType()) { 129 SkASSERT(kVec2f_GrSLType == coords[index].getType()); 130 return coords[index].getName(); 131 } 132 133 SkString coords2D("coords2D"); 134 if (0 != index) { 135 coords2D.appendf("_%i", index); 136 } 137 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", 138 coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); 139 return coords2D; 140 } 141 142 const char* GrGLFragmentShaderBuilder::fragmentPosition() { 143 GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage; 144 if (cs->inStageCode()) { 145 const GrProcessor* effect = cs->effectStage()->getProcessor(); 146 if (!effect->willReadFragmentPosition()) { 147 SkDEBUGFAIL("GrGLProcessor asked for frag position but its generating GrProcessor " 148 "did not request access."); 149 return ""; 150 } 151 } 152 153 GrGpuGL* gpu = fProgramBuilder->gpu(); 154 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 155 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 156 // declaration varies in earlier GLSL specs. So it is simpler to omit it. 157 if (fTopLeftFragPosRead) { 158 fSetupFragPosition = true; 159 return "gl_FragCoord"; 160 } else if (gpu->glCaps().fragCoordConventionsSupport()) { 161 if (!fSetupFragPosition) { 162 if (gpu->glslGeneration() < k150_GrGLSLGeneration) { 163 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, 164 "GL_ARB_fragment_coord_conventions"); 165 } 166 fInputs.push_back().set(kVec4f_GrSLType, 167 GrGLShaderVar::kIn_TypeModifier, 168 "gl_FragCoord", 169 GrGLShaderVar::kDefault_Precision, 170 GrGLShaderVar::kUpperLeft_Origin); 171 fSetupFragPosition = true; 172 } 173 return "gl_FragCoord"; 174 } else { 175 static const char* kCoordName = "fragCoordYDown"; 176 if (!fSetupFragPosition) { 177 // temporarily change the stage index because we're inserting non-stage code. 178 GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL); 179 180 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); 181 const char* rtHeightName; 182 183 fProgramBuilder->fUniformHandles.fRTHeightUni = 184 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 185 kFloat_GrSLType, 186 "RTHeight", 187 &rtHeightName); 188 189 // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that 190 // causes programs to fail to link. Making this function return a vec2() didn't fix the 191 // problem but using 1.0 for the last two components does. 192 this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, " 193 "1.0);\n", kCoordName, rtHeightName); 194 fSetupFragPosition = true; 195 } 196 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); 197 return kCoordName; 198 } 199 } 200 201 void GrGLFragmentShaderBuilder::addVarying(GrSLType type, 202 const char* name, 203 const char** fsInName, 204 GrGLShaderVar::Precision fsPrecision) { 205 fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision); 206 if (fsInName) { 207 *fsInName = name; 208 } 209 } 210 211 void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) { 212 GrGpuGL* gpu = fProgramBuilder->gpu(); 213 if (fHasCustomColorOutput) { 214 GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name())); 215 } 216 if (fHasSecondaryOutput) { 217 GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name())); 218 } 219 } 220 221 bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, 222 SkTDArray<GrGLuint>* shaderIds) const { 223 GrGpuGL* gpu = fProgramBuilder->gpu(); 224 SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo())); 225 fragShaderSrc.append(fExtensions); 226 append_default_precision_qualifier(kDefaultFragmentPrecision, 227 gpu->glStandard(), 228 &fragShaderSrc); 229 fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc); 230 fProgramBuilder->appendDecls(fInputs, &fragShaderSrc); 231 // We shouldn't have declared outputs on 1.10 232 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); 233 fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc); 234 fragShaderSrc.append(fFunctions); 235 fragShaderSrc.append("void main() {\n"); 236 fragShaderSrc.append(fCode); 237 fragShaderSrc.append("}\n"); 238 239 GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId, 240 GR_GL_FRAGMENT_SHADER, fragShaderSrc, 241 gpu->gpuStats()); 242 if (!fragShaderId) { 243 return false; 244 } 245 246 *shaderIds->append() = fragShaderId; 247 248 return true; 249 } 250 251 void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() { 252 const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); 253 GrGpuGL* gpu = fProgramBuilder->gpu(); 254 255 /////////////////////////////////////////////////////////////////////////// 256 // emit code to read the dst copy texture, if necessary 257 if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) { 258 bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey); 259 const char* dstCopyTopLeftName; 260 const char* dstCopyCoordScaleName; 261 const char* dstCopySamplerName; 262 uint32_t configMask; 263 if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) { 264 configMask = kA_GrColorComponentFlag; 265 } else { 266 configMask = kRGBA_GrColorComponentFlags; 267 } 268 fProgramBuilder->fUniformHandles.fDstCopySamplerUni = 269 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 270 kSampler2D_GrSLType, 271 "DstCopySampler", 272 &dstCopySamplerName); 273 fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni = 274 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 275 kVec2f_GrSLType, 276 "DstCopyUpperLeft", 277 &dstCopyTopLeftName); 278 fProgramBuilder->fUniformHandles.fDstCopyScaleUni = 279 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 280 kVec2f_GrSLType, 281 "DstCopyCoordScale", 282 &dstCopyCoordScaleName); 283 const char* fragPos = fragmentPosition(); 284 285 this->codeAppend("// Read color from copy of the destination.\n"); 286 this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;", 287 fragPos, dstCopyTopLeftName, dstCopyCoordScaleName); 288 if (!topDown) { 289 this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;"); 290 } 291 this->codeAppendf("vec4 %s = ", kDstCopyColorName); 292 this->appendTextureLookup(dstCopySamplerName, 293 "_dstTexCoord", 294 configMask, 295 "rgba"); 296 this->codeAppend(";"); 297 } 298 299 if (k110_GrGLSLGeneration != gpu->glslGeneration()) { 300 fOutputs.push_back().set(kVec4f_GrSLType, 301 GrGLShaderVar::kOut_TypeModifier, 302 declared_color_output_name()); 303 fHasCustomColorOutput = true; 304 } 305 } 306 307 void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) { 308 const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader(); 309 310 /////////////////////////////////////////////////////////////////////////// 311 // write the secondary color output if necessary 312 if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) { 313 const char* secondaryOutputName = this->enableSecondaryOutput(); 314 GrGLSLExpr4 coeff(1); 315 switch (header.fSecondaryOutputType) { 316 case GrOptDrawState::kCoverage_SecondaryOutputType: 317 break; 318 case GrOptDrawState::kCoverageISA_SecondaryOutputType: 319 // Get (1-A) into coeff 320 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a()); 321 break; 322 case GrOptDrawState::kCoverageISC_SecondaryOutputType: 323 // Get (1-RGBA) into coeff 324 coeff = GrGLSLExpr4(1) - inputColor; 325 break; 326 default: 327 SkFAIL("Unexpected Secondary Output"); 328 } 329 // Get coeff * coverage into modulate and then write that to the dual source output. 330 codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str()); 331 } 332 333 /////////////////////////////////////////////////////////////////////////// 334 // combine color and coverage as frag color 335 336 // Get "color * coverage" into fragColor 337 GrGLSLExpr4 fragColor = inputColor * inputCoverage; 338 switch (header.fPrimaryOutputType) { 339 case GrOptDrawState::kModulate_PrimaryOutputType: 340 break; 341 case GrOptDrawState::kCombineWithDst_PrimaryOutputType: 342 { 343 // Tack on "+(1-coverage)dst onto the frag color. 344 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage; 345 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor()); 346 fragColor = fragColor + dstContribution; 347 } 348 break; 349 default: 350 SkFAIL("Unknown Primary Output"); 351 } 352 codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str()); 353 } 354 355 const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() { 356 if (!fHasSecondaryOutput) { 357 fOutputs.push_back().set(kVec4f_GrSLType, 358 GrGLShaderVar::kOut_TypeModifier, 359 dual_source_output_name()); 360 fHasSecondaryOutput = true; 361 } 362 return dual_source_output_name(); 363 } 364 365 const char* GrGLFragmentShaderBuilder::getColorOutputName() const { 366 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; 367 } 368 369