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 "GrGLProgramBuilder.h" 10#include "../GrGLGpu.h" 11 12#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X) 13#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X) 14 15const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor"; 16static const char* declared_color_output_name() { return "fsColorOut"; } 17static const char* dual_source_output_name() { return "dualSourceOut"; } 18static void append_default_precision_qualifier(GrSLPrecision p, 19 GrGLStandard standard, 20 SkString* str) { 21 // Desktop GLSL has added precision qualifiers but they don't do anything. 22 if (kGLES_GrGLStandard == standard) { 23 switch (p) { 24 case kHigh_GrSLPrecision: 25 str->append("precision highp float;\n"); 26 break; 27 case kMedium_GrSLPrecision: 28 str->append("precision mediump float;\n"); 29 break; 30 case kLow_GrSLPrecision: 31 str->append("precision lowp float;\n"); 32 break; 33 default: 34 SkFAIL("Unknown precision value."); 35 } 36 } 37} 38 39static const char* specific_layout_qualifier_name(GrBlendEquation equation) { 40 SkASSERT(GrBlendEquationIsAdvanced(equation)); 41 42 static const char* kLayoutQualifierNames[] = { 43 "blend_support_screen", 44 "blend_support_overlay", 45 "blend_support_darken", 46 "blend_support_lighten", 47 "blend_support_colordodge", 48 "blend_support_colorburn", 49 "blend_support_hardlight", 50 "blend_support_softlight", 51 "blend_support_difference", 52 "blend_support_exclusion", 53 "blend_support_multiply", 54 "blend_support_hsl_hue", 55 "blend_support_hsl_saturation", 56 "blend_support_hsl_color", 57 "blend_support_hsl_luminosity" 58 }; 59 return kLayoutQualifierNames[equation - kFirstAdvancedGrBlendEquation]; 60 61 GR_STATIC_ASSERT(0 == kScreen_GrBlendEquation - kFirstAdvancedGrBlendEquation); 62 GR_STATIC_ASSERT(1 == kOverlay_GrBlendEquation - kFirstAdvancedGrBlendEquation); 63 GR_STATIC_ASSERT(2 == kDarken_GrBlendEquation - kFirstAdvancedGrBlendEquation); 64 GR_STATIC_ASSERT(3 == kLighten_GrBlendEquation - kFirstAdvancedGrBlendEquation); 65 GR_STATIC_ASSERT(4 == kColorDodge_GrBlendEquation - kFirstAdvancedGrBlendEquation); 66 GR_STATIC_ASSERT(5 == kColorBurn_GrBlendEquation - kFirstAdvancedGrBlendEquation); 67 GR_STATIC_ASSERT(6 == kHardLight_GrBlendEquation - kFirstAdvancedGrBlendEquation); 68 GR_STATIC_ASSERT(7 == kSoftLight_GrBlendEquation - kFirstAdvancedGrBlendEquation); 69 GR_STATIC_ASSERT(8 == kDifference_GrBlendEquation - kFirstAdvancedGrBlendEquation); 70 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEquation); 71 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEquation); 72 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquation); 73 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlendEquation); 74 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEquation); 75 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlendEquation); 76 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) == 77 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation); 78} 79 80GrGLFragmentShaderBuilder::DstReadKey 81GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps& caps) { 82 uint32_t key = kYesDstRead_DstReadKeyBit; 83 if (caps.glslCaps()->fbFetchSupport()) { 84 return key; 85 } 86 SkASSERT(dstCopy); 87 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) { 88 // The fact that the config is alpha-only must be considered when generating code. 89 key |= kUseAlphaConfig_DstReadKeyBit; 90 } 91 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) { 92 key |= kTopLeftOrigin_DstReadKeyBit; 93 } 94 SkASSERT(static_cast<DstReadKey>(key) == key); 95 return static_cast<DstReadKey>(key); 96} 97 98GrGLFragmentShaderBuilder::FragPosKey 99GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&) { 100 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { 101 return kTopLeftFragPosRead_FragPosKey; 102 } else { 103 return kBottomLeftFragPosRead_FragPosKey; 104 } 105} 106 107GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, 108 uint8_t fragPosKey) 109 : INHERITED(program) 110 , fHasCustomColorOutput(false) 111 , fHasSecondaryOutput(false) 112 , fSetupFragPosition(false) 113 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) 114 , fCustomColorOutputIndex(-1) 115 , fHasReadDstColor(false) 116 , fHasReadFragmentPosition(false) { 117} 118 119bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { 120 switch (feature) { 121 case kStandardDerivatives_GLSLFeature: { 122 GrGLGpu* gpu = fProgramBuilder->gpu(); 123 if (!gpu->glCaps().shaderCaps()->shaderDerivativeSupport()) { 124 return false; 125 } 126 if (kGLES_GrGLStandard == gpu->glStandard() && 127 k110_GrGLSLGeneration == gpu->glslGeneration()) { 128 this->addFeature(1 << kStandardDerivatives_GLSLFeature, 129 "GL_OES_standard_derivatives"); 130 } 131 return true; 132 } 133 default: 134 SkFAIL("Unexpected GLSLFeature requested."); 135 return false; 136 } 137} 138 139SkString GrGLFragmentShaderBuilder::ensureFSCoords2D( 140 const GrGLProcessor::TransformedCoordsArray& coords, int index) { 141 if (kVec3f_GrSLType != coords[index].getType()) { 142 SkASSERT(kVec2f_GrSLType == coords[index].getType()); 143 return coords[index].getName(); 144 } 145 146 SkString coords2D("coords2D"); 147 if (0 != index) { 148 coords2D.appendf("_%i", index); 149 } 150 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", 151 coords2D.c_str(), coords[index].c_str(), coords[index].c_str()); 152 return coords2D; 153} 154 155const char* GrGLFragmentShaderBuilder::fragmentPosition() { 156 fHasReadFragmentPosition = true; 157 158 GrGLGpu* gpu = fProgramBuilder->gpu(); 159 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 160 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 161 // declaration varies in earlier GLSL specs. So it is simpler to omit it. 162 if (fTopLeftFragPosRead) { 163 fSetupFragPosition = true; 164 return "gl_FragCoord"; 165 } else if (gpu->glCaps().fragCoordConventionsSupport()) { 166 if (!fSetupFragPosition) { 167 if (gpu->glslGeneration() < k150_GrGLSLGeneration) { 168 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, 169 "GL_ARB_fragment_coord_conventions"); 170 } 171 fInputs.push_back().set(kVec4f_GrSLType, 172 GrGLShaderVar::kIn_TypeModifier, 173 "gl_FragCoord", 174 kDefault_GrSLPrecision, 175 GrGLShaderVar::kUpperLeft_Origin); 176 fSetupFragPosition = true; 177 } 178 return "gl_FragCoord"; 179 } else { 180 static const char* kCoordName = "fragCoordYDown"; 181 if (!fSetupFragPosition) { 182 // temporarily change the stage index because we're inserting non-stage code. 183 GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder); 184 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); 185 const char* rtHeightName; 186 187 fProgramBuilder->fUniformHandles.fRTHeightUni = 188 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, 189 kFloat_GrSLType, 190 kDefault_GrSLPrecision, 191 "RTHeight", 192 &rtHeightName); 193 194 // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that 195 // causes programs to fail to link. Making this function return a vec2() didn't fix the 196 // problem but using 1.0 for the last two components does. 197 this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, " 198 "1.0);\n", kCoordName, rtHeightName); 199 fSetupFragPosition = true; 200 } 201 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); 202 return kCoordName; 203 } 204} 205 206const char* GrGLFragmentShaderBuilder::dstColor() { 207 fHasReadDstColor = true; 208 209 GrGLGpu* gpu = fProgramBuilder->gpu(); 210 if (gpu->glCaps().glslCaps()->fbFetchSupport()) { 211 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), 212 gpu->glCaps().glslCaps()->fbFetchExtensionString()); 213 214 // Some versions of this extension string require declaring custom color output on ES 3.0+ 215 const char* fbFetchColorName = gpu->glCaps().glslCaps()->fbFetchColorName(); 216 if (gpu->glCaps().glslCaps()->fbFetchNeedsCustomOutput()) { 217 this->enableCustomOutput(); 218 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier); 219 fbFetchColorName = declared_color_output_name(); 220 } 221 return fbFetchColorName; 222 } else { 223 return kDstCopyColorName; 224 } 225} 226 227void GrGLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) { 228 SkASSERT(GrBlendEquationIsAdvanced(equation)); 229 230 const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps(); 231 if (!caps.mustEnableAdvBlendEqs()) { 232 return; 233 } 234 235 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature, 236 "GL_KHR_blend_equation_advanced"); 237 if (caps.mustEnableSpecificAdvBlendEqs()) { 238 this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_InterfaceQualifier); 239 } else { 240 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier); 241 } 242} 243 244void GrGLFragmentShaderBuilder::enableCustomOutput() { 245 if (!fHasCustomColorOutput) { 246 fHasCustomColorOutput = true; 247 fCustomColorOutputIndex = fOutputs.count(); 248 fOutputs.push_back().set(kVec4f_GrSLType, 249 GrGLShaderVar::kOut_TypeModifier, 250 declared_color_output_name()); 251 } 252} 253 254void GrGLFragmentShaderBuilder::enableSecondaryOutput() { 255 SkASSERT(!fHasSecondaryOutput); 256 fHasSecondaryOutput = true; 257 fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier, 258 dual_source_output_name()); 259} 260 261const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const { 262 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"; 263} 264 265const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { 266 return dual_source_output_name(); 267} 268 269bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, 270 SkTDArray<GrGLuint>* shaderIds) { 271 GrGLGpu* gpu = fProgramBuilder->gpu(); 272 this->versionDecl() = GrGetGLSLVersionDecl(gpu->ctxInfo()); 273 append_default_precision_qualifier(kDefault_GrSLPrecision, 274 gpu->glStandard(), 275 &this->precisionQualifier()); 276 this->compileAndAppendLayoutQualifiers(); 277 fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, 278 &this->uniforms()); 279 this->appendDecls(fInputs, &this->inputs()); 280 // We shouldn't have declared outputs on 1.10 281 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); 282 this->appendDecls(fOutputs, &this->outputs()); 283 return this->finalize(programId, GR_GL_FRAGMENT_SHADER, shaderIds); 284} 285 286void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) { 287 // ES 3.00 requires custom color output but doesn't support bindFragDataLocation 288 if (fHasCustomColorOutput && 289 kGLES_GrGLStandard != fProgramBuilder->gpu()->ctxInfo().standard()) { 290 GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name())); 291 } 292 if (fHasSecondaryOutput) { 293 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name())); 294 } 295} 296 297void GrGLFragmentShaderBuilder::addVarying(GrGLVarying* v, GrSLPrecision fsPrec) { 298 v->fFsIn = v->fVsOut; 299 if (v->fGsOut) { 300 v->fFsIn = v->fGsOut; 301 } 302 fInputs.push_back().set(v->fType, GrGLShaderVar::kVaryingIn_TypeModifier, v->fFsIn, fsPrec); 303} 304