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 |