| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrGLFragmentShaderBuilder.h" | 8 #include "GrGLFragmentShaderBuilder.h" |
| 9 #include "GrRenderTarget.h" | 9 #include "GrRenderTarget.h" |
| 10 #include "GrGLProgramBuilder.h" | |
| 11 #include "gl/GrGLGpu.h" | |
| 12 #include "glsl/GrGLSL.h" | 10 #include "glsl/GrGLSL.h" |
| 13 #include "glsl/GrGLSLCaps.h" | 11 #include "glsl/GrGLSLCaps.h" |
| 14 | 12 #include "glsl/GrGLSLProgramBuilder.h" |
| 15 #define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X) | |
| 16 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(),
R, X) | |
| 17 | 13 |
| 18 const char* GrGLFragmentShaderBuilder::kDstTextureColorName = "_dstColor"; | 14 const char* GrGLFragmentShaderBuilder::kDstTextureColorName = "_dstColor"; |
| 19 static const char* declared_color_output_name() { return "fsColorOut"; } | |
| 20 static const char* declared_secondary_color_output_name() { return "fsSecondaryC
olorOut"; } | |
| 21 | 15 |
| 22 static const char* specific_layout_qualifier_name(GrBlendEquation equation) { | 16 static const char* specific_layout_qualifier_name(GrBlendEquation equation) { |
| 23 SkASSERT(GrBlendEquationIsAdvanced(equation)); | 17 SkASSERT(GrBlendEquationIsAdvanced(equation)); |
| 24 | 18 |
| 25 static const char* kLayoutQualifierNames[] = { | 19 static const char* kLayoutQualifierNames[] = { |
| 26 "blend_support_screen", | 20 "blend_support_screen", |
| 27 "blend_support_overlay", | 21 "blend_support_overlay", |
| 28 "blend_support_darken", | 22 "blend_support_darken", |
| 29 "blend_support_lighten", | 23 "blend_support_lighten", |
| 30 "blend_support_colordodge", | 24 "blend_support_colordodge", |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 | 56 |
| 63 GrGLFragmentShaderBuilder::FragPosKey | 57 GrGLFragmentShaderBuilder::FragPosKey |
| 64 GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) { | 58 GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) { |
| 65 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { | 59 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { |
| 66 return kTopLeftFragPosRead_FragPosKey; | 60 return kTopLeftFragPosRead_FragPosKey; |
| 67 } else { | 61 } else { |
| 68 return kBottomLeftFragPosRead_FragPosKey; | 62 return kBottomLeftFragPosRead_FragPosKey; |
| 69 } | 63 } |
| 70 } | 64 } |
| 71 | 65 |
| 72 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program
, | 66 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLSLProgramBuilder* progr
am, |
| 73 uint8_t fragPosKey) | 67 uint8_t fragPosKey) |
| 74 : INHERITED(program) | 68 : INHERITED(program) |
| 75 , fHasCustomColorOutput(false) | |
| 76 , fHasSecondaryOutput(false) | |
| 77 , fSetupFragPosition(false) | 69 , fSetupFragPosition(false) |
| 78 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) | 70 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) |
| 79 , fCustomColorOutputIndex(-1) | 71 , fCustomColorOutputIndex(-1) |
| 80 , fHasReadDstColor(false) | 72 , fHasReadDstColor(false) |
| 81 , fHasReadFragmentPosition(false) { | 73 , fHasReadFragmentPosition(false) { |
| 82 } | 74 } |
| 83 | 75 |
| 84 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { | 76 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { |
| 85 switch (feature) { | 77 switch (feature) { |
| 86 case kStandardDerivatives_GLSLFeature: { | 78 case kStandardDerivatives_GLSLFeature: { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 111 coords2D.appendf("_%i", index); | 103 coords2D.appendf("_%i", index); |
| 112 } | 104 } |
| 113 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", | 105 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", |
| 114 coords2D.c_str(), coords[index].c_str(), coords[index].c_s
tr()); | 106 coords2D.c_str(), coords[index].c_str(), coords[index].c_s
tr()); |
| 115 return coords2D; | 107 return coords2D; |
| 116 } | 108 } |
| 117 | 109 |
| 118 const char* GrGLFragmentShaderBuilder::fragmentPosition() { | 110 const char* GrGLFragmentShaderBuilder::fragmentPosition() { |
| 119 fHasReadFragmentPosition = true; | 111 fHasReadFragmentPosition = true; |
| 120 | 112 |
| 121 GrGLGpu* gpu = fProgramBuilder->gpu(); | 113 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); |
| 122 // We only declare "gl_FragCoord" when we're in the case where we want to us
e layout qualifiers | 114 // We only declare "gl_FragCoord" when we're in the case where we want to us
e layout qualifiers |
| 123 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier
appears in the | 115 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier
appears in the |
| 124 // declaration varies in earlier GLSL specs. So it is simpler to omit it. | 116 // declaration varies in earlier GLSL specs. So it is simpler to omit it. |
| 125 if (fTopLeftFragPosRead) { | 117 if (fTopLeftFragPosRead) { |
| 126 fSetupFragPosition = true; | 118 fSetupFragPosition = true; |
| 127 return "gl_FragCoord"; | 119 return "gl_FragCoord"; |
| 128 } else if (gpu->glCaps().fragCoordConventionsSupport()) { | 120 } else if (const char* extension = glslCaps->fragCoordConventionsExtensionSt
ring()) { |
| 129 if (!fSetupFragPosition) { | 121 if (!fSetupFragPosition) { |
| 130 if (gpu->glslGeneration() < k150_GrGLSLGeneration) { | 122 if (glslCaps->generation() < k150_GrGLSLGeneration) { |
| 131 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, | 123 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, |
| 132 "GL_ARB_fragment_coord_conventions"); | 124 extension); |
| 133 } | 125 } |
| 134 fInputs.push_back().set(kVec4f_GrSLType, | 126 fInputs.push_back().set(kVec4f_GrSLType, |
| 135 GrGLSLShaderVar::kIn_TypeModifier, | 127 GrGLSLShaderVar::kIn_TypeModifier, |
| 136 "gl_FragCoord", | 128 "gl_FragCoord", |
| 137 kDefault_GrSLPrecision, | 129 kDefault_GrSLPrecision, |
| 138 GrGLSLShaderVar::kUpperLeft_Origin); | 130 GrGLSLShaderVar::kUpperLeft_Origin); |
| 139 fSetupFragPosition = true; | 131 fSetupFragPosition = true; |
| 140 } | 132 } |
| 141 return "gl_FragCoord"; | 133 return "gl_FragCoord"; |
| 142 } else { | 134 } else { |
| 143 static const char* kTempName = "tmpXYFragCoord"; | 135 static const char* kTempName = "tmpXYFragCoord"; |
| 144 static const char* kCoordName = "fragCoordYDown"; | 136 static const char* kCoordName = "fragCoordYDown"; |
| 145 if (!fSetupFragPosition) { | 137 if (!fSetupFragPosition) { |
| 146 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); | 138 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); |
| 147 const char* rtHeightName; | 139 const char* rtHeightName; |
| 148 | 140 |
| 149 fProgramBuilder->fUniformHandles.fRTHeightUni = | 141 fProgramBuilder->fUniformHandles.fRTHeightUni = |
| 150 fProgramBuilder->addFragPosUniform(GrGLProgramBuilder::kFrag
ment_Visibility, | 142 fProgramBuilder->addFragPosUniform(GrGLSLProgramBuilder::kFr
agment_Visibility, |
| 151 kFloat_GrSLType, | 143 kFloat_GrSLType, |
| 152 kDefault_GrSLPrecision, | 144 kDefault_GrSLPrecision, |
| 153 "RTHeight", | 145 "RTHeight", |
| 154 &rtHeightName); | 146 &rtHeightName); |
| 155 | 147 |
| 156 // The Adreno compiler seems to be very touchy about access to "gl_F
ragCoord". | 148 // The Adreno compiler seems to be very touchy about access to "gl_F
ragCoord". |
| 157 // Accessing glFragCoord.zw can cause a program to fail to link. Add
itionally, | 149 // Accessing glFragCoord.zw can cause a program to fail to link. Add
itionally, |
| 158 // depending on the surrounding code, accessing .xy with a uniform i
nvolved can | 150 // depending on the surrounding code, accessing .xy with a uniform i
nvolved can |
| 159 // do the same thing. Copying gl_FragCoord.xy into a temp vec2 befor
ehand | 151 // do the same thing. Copying gl_FragCoord.xy into a temp vec2 befor
ehand |
| 160 // (and only accessing .xy) seems to "fix" things. | 152 // (and only accessing .xy) seems to "fix" things. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 174 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); | 166 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); |
| 175 if (glslCaps->fbFetchSupport()) { | 167 if (glslCaps->fbFetchSupport()) { |
| 176 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeatur
e + 1), | 168 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeatur
e + 1), |
| 177 glslCaps->fbFetchExtensionString()); | 169 glslCaps->fbFetchExtensionString()); |
| 178 | 170 |
| 179 // Some versions of this extension string require declaring custom color
output on ES 3.0+ | 171 // Some versions of this extension string require declaring custom color
output on ES 3.0+ |
| 180 const char* fbFetchColorName = glslCaps->fbFetchColorName(); | 172 const char* fbFetchColorName = glslCaps->fbFetchColorName(); |
| 181 if (glslCaps->fbFetchNeedsCustomOutput()) { | 173 if (glslCaps->fbFetchNeedsCustomOutput()) { |
| 182 this->enableCustomOutput(); | 174 this->enableCustomOutput(); |
| 183 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOu
t_TypeModifier); | 175 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOu
t_TypeModifier); |
| 184 fbFetchColorName = declared_color_output_name(); | 176 fbFetchColorName = DeclaredColorOutputName(); |
| 185 } | 177 } |
| 186 return fbFetchColorName; | 178 return fbFetchColorName; |
| 187 } else { | 179 } else { |
| 188 return kDstTextureColorName; | 180 return kDstTextureColorName; |
| 189 } | 181 } |
| 190 } | 182 } |
| 191 | 183 |
| 192 void GrGLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquat
ion equation) { | 184 void GrGLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquat
ion equation) { |
| 193 SkASSERT(GrBlendEquationIsAdvanced(equation)); | 185 SkASSERT(GrBlendEquationIsAdvanced(equation)); |
| 194 | 186 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 205 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQu
alifier); | 197 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQu
alifier); |
| 206 } | 198 } |
| 207 } | 199 } |
| 208 | 200 |
| 209 void GrGLFragmentShaderBuilder::enableCustomOutput() { | 201 void GrGLFragmentShaderBuilder::enableCustomOutput() { |
| 210 if (!fHasCustomColorOutput) { | 202 if (!fHasCustomColorOutput) { |
| 211 fHasCustomColorOutput = true; | 203 fHasCustomColorOutput = true; |
| 212 fCustomColorOutputIndex = fOutputs.count(); | 204 fCustomColorOutputIndex = fOutputs.count(); |
| 213 fOutputs.push_back().set(kVec4f_GrSLType, | 205 fOutputs.push_back().set(kVec4f_GrSLType, |
| 214 GrGLSLShaderVar::kOut_TypeModifier, | 206 GrGLSLShaderVar::kOut_TypeModifier, |
| 215 declared_color_output_name()); | 207 DeclaredColorOutputName()); |
| 216 } | 208 } |
| 217 } | 209 } |
| 218 | 210 |
| 219 void GrGLFragmentShaderBuilder::enableSecondaryOutput() { | 211 void GrGLFragmentShaderBuilder::enableSecondaryOutput() { |
| 220 SkASSERT(!fHasSecondaryOutput); | 212 SkASSERT(!fHasSecondaryOutput); |
| 221 fHasSecondaryOutput = true; | 213 fHasSecondaryOutput = true; |
| 222 if (kGLES_GrGLStandard == fProgramBuilder->gpu()->ctxInfo().standard()) { | 214 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); |
| 223 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, "GL_EXT_ble
nd_func_extended"); | 215 if (const char* extension = caps.secondaryOutputExtensionString()) { |
| 216 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension); |
| 224 } | 217 } |
| 225 | 218 |
| 226 // If the primary output is declared, we must declare also the secondary out
put | 219 // If the primary output is declared, we must declare also the secondary out
put |
| 227 // and vice versa, since it is not allowed to use a built-in gl_FragColor an
d a custom | 220 // and vice versa, since it is not allowed to use a built-in gl_FragColor an
d a custom |
| 228 // output. The condition also co-incides with the condition in whici GLES SL
2.0 | 221 // output. The condition also co-incides with the condition in whici GLES SL
2.0 |
| 229 // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a c
ustom output. | 222 // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a c
ustom output. |
| 230 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); | |
| 231 if (caps.mustDeclareFragmentShaderOutput()) { | 223 if (caps.mustDeclareFragmentShaderOutput()) { |
| 232 fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModi
fier, | 224 fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModi
fier, |
| 233 declared_secondary_color_output_name()); | 225 DeclaredSecondaryColorOutputName()); |
| 234 } | 226 } |
| 235 } | 227 } |
| 236 | 228 |
| 237 const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const { | 229 const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const { |
| 238 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor"
; | 230 return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor"; |
| 239 } | 231 } |
| 240 | 232 |
| 241 const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { | 233 const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { |
| 242 const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps(); | 234 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); |
| 243 return caps.mustDeclareFragmentShaderOutput() ? declared_secondary_color_out
put_name() | 235 return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutput
Name() |
| 244 : "gl_SecondaryFragColorEXT"; | 236 : "gl_SecondaryFragColorEXT"; |
| 245 } | 237 } |
| 246 | 238 |
| 247 void GrGLFragmentShaderBuilder::onFinalize() { | 239 void GrGLFragmentShaderBuilder::onFinalize() { |
| 248 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, | 240 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, |
| 249 *fProgramBuilder->glslCaps(), | 241 *fProgramBuilder->glslCaps(), |
| 250 &this->precisionQualifier()); | 242 &this->precisionQualifier()); |
| 251 } | 243 } |
| 252 | 244 |
| 253 void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID)
{ | 245 void GrGLFragmentShaderBuilder::addVarying(GrGLSLVarying* v, GrSLPrecision fsPre
c) { |
| 254 const GrGLCaps& caps = fProgramBuilder->gpu()->glCaps(); | |
| 255 if (fHasCustomColorOutput && caps.bindFragDataLocationSupport()) { | |
| 256 GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name())
); | |
| 257 } | |
| 258 if (fHasSecondaryOutput && caps.glslCaps()->mustDeclareFragmentShaderOutput(
)) { | |
| 259 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, | |
| 260 declared_secondary_color_output_name
())); | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 void GrGLFragmentShaderBuilder::addVarying(GrGLVarying* v, GrSLPrecision fsPrec)
{ | |
| 265 v->fFsIn = v->fVsOut; | 246 v->fFsIn = v->fVsOut; |
| 266 if (v->fGsOut) { | 247 if (v->fGsOut) { |
| 267 v->fFsIn = v->fGsOut; | 248 v->fFsIn = v->fGsOut; |
| 268 } | 249 } |
| 269 fInputs.push_back().set(v->fType, GrGLSLShaderVar::kVaryingIn_TypeModifier,
v->fFsIn, fsPrec); | 250 fInputs.push_back().set(v->fType, GrGLSLShaderVar::kVaryingIn_TypeModifier,
v->fFsIn, fsPrec); |
| 270 } | 251 } |
| 271 | 252 |
| 272 void GrGLFragmentBuilder::onBeforeChildProcEmitCode() { | 253 void GrGLFragmentBuilder::onBeforeChildProcEmitCode() { |
| 273 SkASSERT(fSubstageIndices.count() >= 1); | 254 SkASSERT(fSubstageIndices.count() >= 1); |
| 274 fSubstageIndices.push_back(0); | 255 fSubstageIndices.push_back(0); |
| 275 // second-to-last value in the fSubstageIndices stack is the index of the ch
ild proc | 256 // second-to-last value in the fSubstageIndices stack is the index of the ch
ild proc |
| 276 // at that level which is currently emitting code. | 257 // at that level which is currently emitting code. |
| 277 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]
); | 258 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]
); |
| 278 } | 259 } |
| 279 | 260 |
| 280 void GrGLFragmentBuilder::onAfterChildProcEmitCode() { | 261 void GrGLFragmentBuilder::onAfterChildProcEmitCode() { |
| 281 SkASSERT(fSubstageIndices.count() >= 2); | 262 SkASSERT(fSubstageIndices.count() >= 2); |
| 282 fSubstageIndices.pop_back(); | 263 fSubstageIndices.pop_back(); |
| 283 fSubstageIndices.back()++; | 264 fSubstageIndices.back()++; |
| 284 int removeAt = fMangleString.findLastOf('_'); | 265 int removeAt = fMangleString.findLastOf('_'); |
| 285 fMangleString.remove(removeAt, fMangleString.size() - removeAt); | 266 fMangleString.remove(removeAt, fMangleString.size() - removeAt); |
| 286 } | 267 } |
| 268 |
| OLD | NEW |