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