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 "GrGLSLFragmentShaderBuilder.h" |
9 #include "GrRenderTarget.h" | 9 #include "GrRenderTarget.h" |
10 #include "glsl/GrGLSL.h" | 10 #include "glsl/GrGLSL.h" |
11 #include "glsl/GrGLSLCaps.h" | 11 #include "glsl/GrGLSLCaps.h" |
12 #include "glsl/GrGLSLProgramBuilder.h" | 12 #include "glsl/GrGLSLProgramBuilder.h" |
13 | 13 |
14 const char* GrGLFragmentShaderBuilder::kDstTextureColorName = "_dstColor"; | 14 const char* GrGLSLFragmentShaderBuilder::kDstTextureColorName = "_dstColor"; |
15 | 15 |
16 static const char* specific_layout_qualifier_name(GrBlendEquation equation) { | 16 static const char* specific_layout_qualifier_name(GrBlendEquation equation) { |
17 SkASSERT(GrBlendEquationIsAdvanced(equation)); | 17 SkASSERT(GrBlendEquationIsAdvanced(equation)); |
18 | 18 |
19 static const char* kLayoutQualifierNames[] = { | 19 static const char* kLayoutQualifierNames[] = { |
20 "blend_support_screen", | 20 "blend_support_screen", |
21 "blend_support_overlay", | 21 "blend_support_overlay", |
22 "blend_support_darken", | 22 "blend_support_darken", |
23 "blend_support_lighten", | 23 "blend_support_lighten", |
24 "blend_support_colordodge", | 24 "blend_support_colordodge", |
(...skipping 22 matching lines...) Expand all Loading... |
47 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); | 47 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); |
48 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); | 48 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); |
49 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquati
on); | 49 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquati
on); |
50 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); | 50 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); |
51 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); | 51 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEqua
tion); |
52 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); | 52 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlen
dEquation); |
53 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) == | 53 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) == |
54 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation); | 54 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation); |
55 } | 55 } |
56 | 56 |
57 GrGLFragmentShaderBuilder::FragPosKey | 57 GrGLSLFragmentShaderBuilder::FragPosKey |
58 GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) { | 58 GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) { |
59 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { | 59 if (kTopLeft_GrSurfaceOrigin == dst->origin()) { |
60 return kTopLeftFragPosRead_FragPosKey; | 60 return kTopLeftFragPosRead_FragPosKey; |
61 } else { | 61 } else { |
62 return kBottomLeftFragPosRead_FragPosKey; | 62 return kBottomLeftFragPosRead_FragPosKey; |
63 } | 63 } |
64 } | 64 } |
65 | 65 |
66 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLSLProgramBuilder* progr
am, | 66 GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* p
rogram, |
67 uint8_t fragPosKey) | 67 uint8_t fragPosKey) |
68 : INHERITED(program) | 68 : INHERITED(program) |
69 , fSetupFragPosition(false) | 69 , fSetupFragPosition(false) |
70 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) | 70 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey) |
71 , fCustomColorOutputIndex(-1) | 71 , fCustomColorOutputIndex(-1) |
72 , fHasReadDstColor(false) | 72 , fHasReadDstColor(false) |
73 , fHasReadFragmentPosition(false) { | 73 , fHasReadFragmentPosition(false) { |
74 } | 74 } |
75 | 75 |
76 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { | 76 bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { |
77 switch (feature) { | 77 switch (feature) { |
78 case kStandardDerivatives_GLSLFeature: { | 78 case kStandardDerivatives_GLSLFeature: { |
79 if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) { | 79 if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) { |
80 return false; | 80 return false; |
81 } | 81 } |
82 const char* extension = fProgramBuilder->glslCaps()->shaderDerivativ
eExtensionString(); | 82 const char* extension = fProgramBuilder->glslCaps()->shaderDerivativ
eExtensionString(); |
83 if (extension) { | 83 if (extension) { |
84 this->addFeature(1 << kStandardDerivatives_GLSLFeature, extensio
n); | 84 this->addFeature(1 << kStandardDerivatives_GLSLFeature, extensio
n); |
85 } | 85 } |
86 return true; | 86 return true; |
87 } | 87 } |
88 default: | 88 default: |
89 SkFAIL("Unexpected GLSLFeature requested."); | 89 SkFAIL("Unexpected GLSLFeature requested."); |
90 return false; | 90 return false; |
91 } | 91 } |
92 } | 92 } |
93 | 93 |
94 SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCoor
dsArray& coords, | 94 SkString GrGLSLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCo
ordsArray& coords, |
95 int index) { | 95 int index) { |
96 if (kVec3f_GrSLType != coords[index].getType()) { | 96 if (kVec3f_GrSLType != coords[index].getType()) { |
97 SkASSERT(kVec2f_GrSLType == coords[index].getType()); | 97 SkASSERT(kVec2f_GrSLType == coords[index].getType()); |
98 return coords[index].getName(); | 98 return coords[index].getName(); |
99 } | 99 } |
100 | 100 |
101 SkString coords2D("coords2D"); | 101 SkString coords2D("coords2D"); |
102 if (0 != index) { | 102 if (0 != index) { |
103 coords2D.appendf("_%i", index); | 103 coords2D.appendf("_%i", index); |
104 } | 104 } |
105 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", | 105 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;", |
106 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()); |
107 return coords2D; | 107 return coords2D; |
108 } | 108 } |
109 | 109 |
110 const char* GrGLFragmentShaderBuilder::fragmentPosition() { | 110 const char* GrGLSLFragmentShaderBuilder::fragmentPosition() { |
111 fHasReadFragmentPosition = true; | 111 fHasReadFragmentPosition = true; |
112 | 112 |
113 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); | 113 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); |
114 // 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 |
115 // 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 |
116 // 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. |
117 if (fTopLeftFragPosRead) { | 117 if (fTopLeftFragPosRead) { |
118 fSetupFragPosition = true; | 118 fSetupFragPosition = true; |
119 return "gl_FragCoord"; | 119 return "gl_FragCoord"; |
120 } else if (const char* extension = glslCaps->fragCoordConventionsExtensionSt
ring()) { | 120 } else if (const char* extension = glslCaps->fragCoordConventionsExtensionSt
ring()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 this->codePrependf("\tvec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n", | 153 this->codePrependf("\tvec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n", |
154 kCoordName, kTempName, rtHeightName, kTempName); | 154 kCoordName, kTempName, rtHeightName, kTempName); |
155 this->codePrependf("vec2 %s = gl_FragCoord.xy;", kTempName); | 155 this->codePrependf("vec2 %s = gl_FragCoord.xy;", kTempName); |
156 fSetupFragPosition = true; | 156 fSetupFragPosition = true; |
157 } | 157 } |
158 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); | 158 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); |
159 return kCoordName; | 159 return kCoordName; |
160 } | 160 } |
161 } | 161 } |
162 | 162 |
163 const char* GrGLFragmentShaderBuilder::dstColor() { | 163 const char* GrGLSLFragmentShaderBuilder::dstColor() { |
164 fHasReadDstColor = true; | 164 fHasReadDstColor = true; |
165 | 165 |
166 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); | 166 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps(); |
167 if (glslCaps->fbFetchSupport()) { | 167 if (glslCaps->fbFetchSupport()) { |
168 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeatur
e + 1), | 168 this->addFeature(1 << (GrGLSLFragmentShaderBuilder::kLastGLSLPrivateFeat
ure + 1), |
169 glslCaps->fbFetchExtensionString()); | 169 glslCaps->fbFetchExtensionString()); |
170 | 170 |
171 // 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+ |
172 const char* fbFetchColorName = glslCaps->fbFetchColorName(); | 172 const char* fbFetchColorName = glslCaps->fbFetchColorName(); |
173 if (glslCaps->fbFetchNeedsCustomOutput()) { | 173 if (glslCaps->fbFetchNeedsCustomOutput()) { |
174 this->enableCustomOutput(); | 174 this->enableCustomOutput(); |
175 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOu
t_TypeModifier); | 175 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOu
t_TypeModifier); |
176 fbFetchColorName = DeclaredColorOutputName(); | 176 fbFetchColorName = DeclaredColorOutputName(); |
177 } | 177 } |
178 return fbFetchColorName; | 178 return fbFetchColorName; |
179 } else { | 179 } else { |
180 return kDstTextureColorName; | 180 return kDstTextureColorName; |
181 } | 181 } |
182 } | 182 } |
183 | 183 |
184 void GrGLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquat
ion equation) { | 184 void GrGLSLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEqu
ation equation) { |
185 SkASSERT(GrBlendEquationIsAdvanced(equation)); | 185 SkASSERT(GrBlendEquationIsAdvanced(equation)); |
186 | 186 |
187 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); | 187 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); |
188 if (!caps.mustEnableAdvBlendEqs()) { | 188 if (!caps.mustEnableAdvBlendEqs()) { |
189 return; | 189 return; |
190 } | 190 } |
191 | 191 |
192 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature, | 192 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature, |
193 "GL_KHR_blend_equation_advanced"); | 193 "GL_KHR_blend_equation_advanced"); |
194 if (caps.mustEnableSpecificAdvBlendEqs()) { | 194 if (caps.mustEnableSpecificAdvBlendEqs()) { |
195 this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_
InterfaceQualifier); | 195 this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_
InterfaceQualifier); |
196 } else { | 196 } else { |
197 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQu
alifier); | 197 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQu
alifier); |
198 } | 198 } |
199 } | 199 } |
200 | 200 |
201 void GrGLFragmentShaderBuilder::enableCustomOutput() { | 201 void GrGLSLFragmentShaderBuilder::enableCustomOutput() { |
202 if (!fHasCustomColorOutput) { | 202 if (!fHasCustomColorOutput) { |
203 fHasCustomColorOutput = true; | 203 fHasCustomColorOutput = true; |
204 fCustomColorOutputIndex = fOutputs.count(); | 204 fCustomColorOutputIndex = fOutputs.count(); |
205 fOutputs.push_back().set(kVec4f_GrSLType, | 205 fOutputs.push_back().set(kVec4f_GrSLType, |
206 GrGLSLShaderVar::kOut_TypeModifier, | 206 GrGLSLShaderVar::kOut_TypeModifier, |
207 DeclaredColorOutputName()); | 207 DeclaredColorOutputName()); |
208 } | 208 } |
209 } | 209 } |
210 | 210 |
211 void GrGLFragmentShaderBuilder::enableSecondaryOutput() { | 211 void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() { |
212 SkASSERT(!fHasSecondaryOutput); | 212 SkASSERT(!fHasSecondaryOutput); |
213 fHasSecondaryOutput = true; | 213 fHasSecondaryOutput = true; |
214 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); | 214 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); |
215 if (const char* extension = caps.secondaryOutputExtensionString()) { | 215 if (const char* extension = caps.secondaryOutputExtensionString()) { |
216 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension); | 216 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension); |
217 } | 217 } |
218 | 218 |
219 // 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 |
220 // 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 |
221 // 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 |
222 // 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. |
223 if (caps.mustDeclareFragmentShaderOutput()) { | 223 if (caps.mustDeclareFragmentShaderOutput()) { |
224 fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModi
fier, | 224 fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModi
fier, |
225 DeclaredSecondaryColorOutputName()); | 225 DeclaredSecondaryColorOutputName()); |
226 } | 226 } |
227 } | 227 } |
228 | 228 |
229 const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const { | 229 const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const { |
230 return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor"; | 230 return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor"; |
231 } | 231 } |
232 | 232 |
233 const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const { | 233 const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const { |
234 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); | 234 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps(); |
235 return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutput
Name() | 235 return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutput
Name() |
236 : "gl_SecondaryFragColorEXT"; | 236 : "gl_SecondaryFragColorEXT"; |
237 } | 237 } |
238 | 238 |
239 void GrGLFragmentShaderBuilder::onFinalize() { | 239 void GrGLSLFragmentShaderBuilder::onFinalize() { |
240 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, | 240 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, |
241 *fProgramBuilder->glslCaps(), | 241 *fProgramBuilder->glslCaps(), |
242 &this->precisionQualifier()); | 242 &this->precisionQualifier()); |
243 } | 243 } |
244 | 244 |
245 void GrGLFragmentShaderBuilder::addVarying(GrGLSLVarying* v, GrSLPrecision fsPre
c) { | 245 void GrGLSLFragmentShaderBuilder::addVarying(GrGLSLVarying* v, GrSLPrecision fsP
rec) { |
246 v->fFsIn = v->fVsOut; | 246 v->fFsIn = v->fVsOut; |
247 if (v->fGsOut) { | 247 if (v->fGsOut) { |
248 v->fFsIn = v->fGsOut; | 248 v->fFsIn = v->fGsOut; |
249 } | 249 } |
250 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); |
251 } | 251 } |
252 | 252 |
253 void GrGLFragmentBuilder::onBeforeChildProcEmitCode() { | 253 void GrGLSLFragmentBuilder::onBeforeChildProcEmitCode() { |
254 SkASSERT(fSubstageIndices.count() >= 1); | 254 SkASSERT(fSubstageIndices.count() >= 1); |
255 fSubstageIndices.push_back(0); | 255 fSubstageIndices.push_back(0); |
256 // 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 |
257 // at that level which is currently emitting code. | 257 // at that level which is currently emitting code. |
258 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]
); | 258 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]
); |
259 } | 259 } |
260 | 260 |
261 void GrGLFragmentBuilder::onAfterChildProcEmitCode() { | 261 void GrGLSLFragmentBuilder::onAfterChildProcEmitCode() { |
262 SkASSERT(fSubstageIndices.count() >= 2); | 262 SkASSERT(fSubstageIndices.count() >= 2); |
263 fSubstageIndices.pop_back(); | 263 fSubstageIndices.pop_back(); |
264 fSubstageIndices.back()++; | 264 fSubstageIndices.back()++; |
265 int removeAt = fMangleString.findLastOf('_'); | 265 int removeAt = fMangleString.findLastOf('_'); |
266 fMangleString.remove(removeAt, fMangleString.size() - removeAt); | 266 fMangleString.remove(removeAt, fMangleString.size() - removeAt); |
267 } | 267 } |
268 | 268 |
OLD | NEW |