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 "GrGLSLFragmentShaderBuilder.h" 9 #include "GrRenderTarget.h" 10 #include "gl/GrGLGpu.h" 11 #include "glsl/GrGLSL.h" 12 #include "glsl/GrGLSLCaps.h" 13 #include "glsl/GrGLSLProgramBuilder.h" 14 #include "glsl/GrGLSLUniformHandler.h" 15 #include "glsl/GrGLSLVarying.h" 16 17 const char* GrGLSLFragmentShaderBuilder::kDstTextureColorName = "_dstColor"; 18 19 static const char* specific_layout_qualifier_name(GrBlendEquation equation) { 20 SkASSERT(GrBlendEquationIsAdvanced(equation)); 21 22 static const char* kLayoutQualifierNames[] = { 23 "blend_support_screen", 24 "blend_support_overlay", 25 "blend_support_darken", 26 "blend_support_lighten", 27 "blend_support_colordodge", 28 "blend_support_colorburn", 29 "blend_support_hardlight", 30 "blend_support_softlight", 31 "blend_support_difference", 32 "blend_support_exclusion", 33 "blend_support_multiply", 34 "blend_support_hsl_hue", 35 "blend_support_hsl_saturation", 36 "blend_support_hsl_color", 37 "blend_support_hsl_luminosity" 38 }; 39 return kLayoutQualifierNames[equation - kFirstAdvancedGrBlendEquation]; 40 41 GR_STATIC_ASSERT(0 == kScreen_GrBlendEquation - kFirstAdvancedGrBlendEquation); 42 GR_STATIC_ASSERT(1 == kOverlay_GrBlendEquation - kFirstAdvancedGrBlendEquation); 43 GR_STATIC_ASSERT(2 == kDarken_GrBlendEquation - kFirstAdvancedGrBlendEquation); 44 GR_STATIC_ASSERT(3 == kLighten_GrBlendEquation - kFirstAdvancedGrBlendEquation); 45 GR_STATIC_ASSERT(4 == kColorDodge_GrBlendEquation - kFirstAdvancedGrBlendEquation); 46 GR_STATIC_ASSERT(5 == kColorBurn_GrBlendEquation - kFirstAdvancedGrBlendEquation); 47 GR_STATIC_ASSERT(6 == kHardLight_GrBlendEquation - kFirstAdvancedGrBlendEquation); 48 GR_STATIC_ASSERT(7 == kSoftLight_GrBlendEquation - kFirstAdvancedGrBlendEquation); 49 GR_STATIC_ASSERT(8 == kDifference_GrBlendEquation - kFirstAdvancedGrBlendEquation); 50 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEquation); 51 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEquation); 52 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquation); 53 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlendEquation); 54 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEquation); 55 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlendEquation); 56 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) == 57 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation); 58 } 59 60 GrGLSLFragmentShaderBuilder::FragPosKey 61 GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) { 62 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { 63 return kTopLeftFragPosRead_FragPosKey; 64 } else { 65 return kBottomLeftFragPosRead_FragPosKey; 66 } 67 } 68 69 GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program, 70 uint8_t fragPosKey) 71 : GrGLSLFragmentBuilder(program) 72 , fSetupFragPosition(false) 73 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) 74 , fHasCustomColorOutput(false) 75 , fCustomColorOutputIndex(-1) 76 , fHasSecondaryOutput(false) 77 , fHasInitializedSampleMask(false) 78 , fHasReadDstColor(false) 79 , fHasReadFragmentPosition(false) { 80 fSubstageIndices.push_back(0); 81 } 82 83 bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { 84 switch (feature) { 85 case kStandardDerivatives_GLSLFeature: { 86 if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) { 87 return false; 88 } 89 const char* extension = fProgramBuilder->glslCaps()->shaderDerivativeExtensionString(); 90 if (extension) { 91 this->addFeature(1 << kStandardDerivatives_GLSLFeature, extension); 92 } 93 return true; 94 } 95 case kPixelLocalStorage_GLSLFeature: { 96 if (fProgramBuilder->glslCaps()->pixelLocalStorageSize() <= 0) { 97 return false; 98 } 99 this->addFeature(1 << kPixelLocalStorage_GLSLFeature, 100 "GL_EXT_shader_pixel_local_storage"); 101 return true; 102 } 103 default: 104 SkFAIL("Unexpected GLSLFeature requested."); 105 return false; 106 } 107 } 108 109 SkString GrGLSLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCoordsArray& coords, 110 int index) { 111 if (kVec3f_GrSLType != coords[index].getType()) { 112 SkASSERT(kVec2f_GrSLType == coords[index].getType()); 113 return coords[index].getName(); 114 } 115 116 SkString coords2D("coords2D"); 117 if (0 != index) { 118 coords2D.appendf("_%i", index); 119 } 120 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", 121 coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); 122 return coords2D; 123 } 124 125 const char* GrGLSLFragmentShaderBuilder::fragmentPosition() { 126 fHasReadFragmentPosition = true; 127 128 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); 129 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 130 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 131 // declaration varies in earlier GLSL specs. So it is simpler to omit it. 132 if (fTopLeftFragPosRead) { 133 fSetupFragPosition = true; 134 return "gl_FragCoord"; 135 } else if (const char* extension = glslCaps->fragCoordConventionsExtensionString()) { 136 if (!fSetupFragPosition) { 137 if (glslCaps->generation() < k150_GrGLSLGeneration) { 138 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, 139 extension); 140 } 141 fInputs.push_back().set(kVec4f_GrSLType, 142 GrGLSLShaderVar::kIn_TypeModifier, 143 "gl_FragCoord", 144 kDefault_GrSLPrecision, 145 "origin_upper_left"); 146 fSetupFragPosition = true; 147 } 148 return "gl_FragCoord"; 149 } else { 150 static const char* kTempName = "tmpXYFragCoord"; 151 static const char* kCoordName = "fragCoordYDown"; 152 if (!fSetupFragPosition) { 153 const char* rtHeightName; 154 155 fProgramBuilder->addRTHeightUniform("RTHeight", &rtHeightName); 156 157 // The Adreno compiler seems to be very touchy about access to "gl_FragCoord". 158 // Accessing glFragCoord.zw can cause a program to fail to link. Additionally, 159 // depending on the surrounding code, accessing .xy with a uniform involved can 160 // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand 161 // (and only accessing .xy) seems to "fix" things. 162 const char* precision = glslCaps->usesPrecisionModifiers() ? "highp " : ""; 163 this->codePrependf("\t%svec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n", 164 precision, kCoordName, kTempName, rtHeightName, kTempName); 165 this->codePrependf("%svec2 %s = gl_FragCoord.xy;", precision, kTempName); 166 fSetupFragPosition = true; 167 } 168 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); 169 return kCoordName; 170 } 171 } 172 173 void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) { 174 const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps(); 175 if (!glslCaps.sampleVariablesSupport()) { 176 SkDEBUGFAIL("Attempted to mask sample coverage without support."); 177 return; 178 } 179 if (const char* extension = glslCaps.sampleVariablesExtensionString()) { 180 this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension); 181 } 182 if (!fHasInitializedSampleMask) { 183 this->codePrependf("gl_SampleMask[0] = -1;"); 184 fHasInitializedSampleMask = true; 185 } 186 if (invert) { 187 this->codeAppendf("gl_SampleMask[0] &= ~(%s);", mask); 188 } else { 189 this->codeAppendf("gl_SampleMask[0] &= %s;", mask); 190 } 191 } 192 193 void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) { 194 const GrGLSLCaps& glslCaps = *fProgramBuilder->glslCaps(); 195 if (!glslCaps.sampleMaskOverrideCoverageSupport()) { 196 SkDEBUGFAIL("Attempted to override sample coverage without support."); 197 return; 198 } 199 SkASSERT(glslCaps.sampleVariablesSupport()); 200 if (const char* extension = glslCaps.sampleVariablesExtensionString()) { 201 this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension); 202 } 203 if (this->addFeature(1 << kSampleMaskOverrideCoverage_GLSLPrivateFeature, 204 "GL_NV_sample_mask_override_coverage")) { 205 // Redeclare gl_SampleMask with layout(override_coverage) if we haven't already. 206 fOutputs.push_back().set(kInt_GrSLType, GrShaderVar::kOut_TypeModifier, 207 "gl_SampleMask", 1, kHigh_GrSLPrecision, 208 "override_coverage"); 209 } 210 this->codeAppendf("gl_SampleMask[0] = %s;", mask); 211 fHasInitializedSampleMask = true; 212 } 213 214 const char* GrGLSLFragmentShaderBuilder::dstColor() { 215 fHasReadDstColor = true; 216 217 const char* override = fProgramBuilder->primitiveProcessor().getDestColorOverride(); 218 if (override != nullptr) { 219 return override; 220 } 221 222 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); 223 if (glslCaps->fbFetchSupport()) { 224 this->addFeature(1 << kFramebufferFetch_GLSLPrivateFeature, 225 glslCaps->fbFetchExtensionString()); 226 227 // Some versions of this extension string require declaring custom color output on ES 3.0+ 228 const char* fbFetchColorName = glslCaps->fbFetchColorName(); 229 if (glslCaps->fbFetchNeedsCustomOutput()) { 230 this->enableCustomOutput(); 231 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier); 232 fbFetchColorName = DeclaredColorOutputName(); 233 } 234 return fbFetchColorName; 235 } else { 236 return kDstTextureColorName; 237 } 238 } 239 240 void GrGLSLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) { 241 SkASSERT(GrBlendEquationIsAdvanced(equation)); 242 243 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); 244 if (!caps.mustEnableAdvBlendEqs()) { 245 return; 246 } 247 248 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature, 249 "GL_KHR_blend_equation_advanced"); 250 if (caps.mustEnableSpecificAdvBlendEqs()) { 251 this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_InterfaceQualifier); 252 } else { 253 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier); 254 } 255 } 256 257 void GrGLSLFragmentShaderBuilder::enableCustomOutput() { 258 if (!fHasCustomColorOutput) { 259 fHasCustomColorOutput = true; 260 fCustomColorOutputIndex = fOutputs.count(); 261 fOutputs.push_back().set(kVec4f_GrSLType, 262 GrGLSLShaderVar::kOut_TypeModifier, 263 DeclaredColorOutputName()); 264 fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back()); 265 } 266 } 267 268 void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() { 269 SkASSERT(!fHasSecondaryOutput); 270 fHasSecondaryOutput = true; 271 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); 272 if (const char* extension = caps.secondaryOutputExtensionString()) { 273 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension); 274 } 275 276 // If the primary output is declared, we must declare also the secondary output 277 // and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom 278 // output. The condition also co-incides with the condition in whici GLES SL 2.0 279 // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output. 280 if (caps.mustDeclareFragmentShaderOutput()) { 281 fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModifier, 282 DeclaredSecondaryColorOutputName()); 283 fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back()); 284 } 285 } 286 287 const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const { 288 return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor"; 289 } 290 291 void GrGLSLFragmentBuilder::declAppendf(const char* fmt, ...) { 292 va_list argp; 293 va_start(argp, fmt); 294 inputs().appendVAList(fmt, argp); 295 va_end(argp); 296 } 297 298 const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const { 299 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); 300 return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutputName() 301 : "gl_SecondaryFragColorEXT"; 302 } 303 304 void GrGLSLFragmentShaderBuilder::onFinalize() { 305 fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs()); 306 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, 307 *fProgramBuilder->glslCaps(), 308 &this->precisionQualifier()); 309 } 310 311 void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() { 312 SkASSERT(fSubstageIndices.count() >= 1); 313 fSubstageIndices.push_back(0); 314 // second-to-last value in the fSubstageIndices stack is the index of the child proc 315 // at that level which is currently emitting code. 316 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]); 317 } 318 319 void GrGLSLFragmentShaderBuilder::onAfterChildProcEmitCode() { 320 SkASSERT(fSubstageIndices.count() >= 2); 321 fSubstageIndices.pop_back(); 322 fSubstageIndices.back()++; 323 int removeAt = fMangleString.findLastOf('_'); 324 fMangleString.remove(removeAt, fMangleString.size() - removeAt); 325 } 326 327