blob: 122db10ec99ba0d4a8aa4cd6cf0cd4199d93c55a [file] [log] [blame]
joshualitt30ba4362014-08-21 20:18:45 -07001/*
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
egdaniel2d721d32015-11-11 13:06:05 -08008#include "GrGLSLFragmentShaderBuilder.h"
egdaniel574a4c12015-11-02 06:22:44 -08009#include "GrRenderTarget.h"
egdanielcb7ba1e2015-10-26 08:38:25 -070010#include "glsl/GrGLSL.h"
jvanverthcba99b82015-06-24 06:59:57 -070011#include "glsl/GrGLSLCaps.h"
egdaniel8dcdedc2015-11-11 06:27:20 -080012#include "glsl/GrGLSLProgramBuilder.h"
egdaniel0eafe792015-11-20 14:01:22 -080013#include "glsl/GrGLSLVarying.h"
joshualitt47bb3822014-10-07 16:43:25 -070014
egdaniel2d721d32015-11-11 13:06:05 -080015const char* GrGLSLFragmentShaderBuilder::kDstTextureColorName = "_dstColor";
joshualitt30ba4362014-08-21 20:18:45 -070016
cdalton8917d622015-05-06 13:40:21 -070017static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
18 SkASSERT(GrBlendEquationIsAdvanced(equation));
19
20 static const char* kLayoutQualifierNames[] = {
21 "blend_support_screen",
22 "blend_support_overlay",
23 "blend_support_darken",
24 "blend_support_lighten",
25 "blend_support_colordodge",
26 "blend_support_colorburn",
27 "blend_support_hardlight",
28 "blend_support_softlight",
29 "blend_support_difference",
30 "blend_support_exclusion",
31 "blend_support_multiply",
32 "blend_support_hsl_hue",
33 "blend_support_hsl_saturation",
34 "blend_support_hsl_color",
35 "blend_support_hsl_luminosity"
36 };
37 return kLayoutQualifierNames[equation - kFirstAdvancedGrBlendEquation];
38
39 GR_STATIC_ASSERT(0 == kScreen_GrBlendEquation - kFirstAdvancedGrBlendEquation);
40 GR_STATIC_ASSERT(1 == kOverlay_GrBlendEquation - kFirstAdvancedGrBlendEquation);
41 GR_STATIC_ASSERT(2 == kDarken_GrBlendEquation - kFirstAdvancedGrBlendEquation);
42 GR_STATIC_ASSERT(3 == kLighten_GrBlendEquation - kFirstAdvancedGrBlendEquation);
43 GR_STATIC_ASSERT(4 == kColorDodge_GrBlendEquation - kFirstAdvancedGrBlendEquation);
44 GR_STATIC_ASSERT(5 == kColorBurn_GrBlendEquation - kFirstAdvancedGrBlendEquation);
45 GR_STATIC_ASSERT(6 == kHardLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
46 GR_STATIC_ASSERT(7 == kSoftLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
47 GR_STATIC_ASSERT(8 == kDifference_GrBlendEquation - kFirstAdvancedGrBlendEquation);
48 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEquation);
49 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEquation);
50 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquation);
51 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlendEquation);
52 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEquation);
53 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlendEquation);
54 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) ==
bsalomonf7cc8772015-05-11 11:21:14 -070055 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
cdalton8917d622015-05-06 13:40:21 -070056}
57
egdaniel2d721d32015-11-11 13:06:05 -080058GrGLSLFragmentShaderBuilder::FragPosKey
59GrGLSLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) {
joshualitt30ba4362014-08-21 20:18:45 -070060 if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
61 return kTopLeftFragPosRead_FragPosKey;
62 } else {
63 return kBottomLeftFragPosRead_FragPosKey;
64 }
65}
66
egdaniel2d721d32015-11-11 13:06:05 -080067GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program,
68 uint8_t fragPosKey)
joshualitt30ba4362014-08-21 20:18:45 -070069 : INHERITED(program)
joshualitt30ba4362014-08-21 20:18:45 -070070 , fSetupFragPosition(false)
joshualitt79f8fae2014-10-28 17:59:26 -070071 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey)
joshualittb4384b92014-10-21 12:53:15 -070072 , fCustomColorOutputIndex(-1)
joshualitt47bb3822014-10-07 16:43:25 -070073 , fHasReadDstColor(false)
74 , fHasReadFragmentPosition(false) {
joshualitt30ba4362014-08-21 20:18:45 -070075}
76
egdaniel2d721d32015-11-11 13:06:05 -080077bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
joshualitt30ba4362014-08-21 20:18:45 -070078 switch (feature) {
79 case kStandardDerivatives_GLSLFeature: {
egdaniel574a4c12015-11-02 06:22:44 -080080 if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) {
joshualitt30ba4362014-08-21 20:18:45 -070081 return false;
82 }
egdaniel574a4c12015-11-02 06:22:44 -080083 const char* extension = fProgramBuilder->glslCaps()->shaderDerivativeExtensionString();
84 if (extension) {
85 this->addFeature(1 << kStandardDerivatives_GLSLFeature, extension);
joshualitt30ba4362014-08-21 20:18:45 -070086 }
87 return true;
88 }
89 default:
90 SkFAIL("Unexpected GLSLFeature requested.");
91 return false;
92 }
93}
94
egdaniel2d721d32015-11-11 13:06:05 -080095SkString GrGLSLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCoordsArray& coords,
96 int index) {
joshualitt23e280d2014-09-18 12:26:38 -070097 if (kVec3f_GrSLType != coords[index].getType()) {
98 SkASSERT(kVec2f_GrSLType == coords[index].getType());
joshualitt30ba4362014-08-21 20:18:45 -070099 return coords[index].getName();
100 }
101
102 SkString coords2D("coords2D");
103 if (0 != index) {
104 coords2D.appendf("_%i", index);
105 }
106 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;",
107 coords2D.c_str(), coords[index].c_str(), coords[index].c_str());
108 return coords2D;
109}
110
egdaniel2d721d32015-11-11 13:06:05 -0800111const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
joshualitt47bb3822014-10-07 16:43:25 -0700112 fHasReadFragmentPosition = true;
joshualitt30ba4362014-08-21 20:18:45 -0700113
egdaniel8dcdedc2015-11-11 06:27:20 -0800114 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
joshualitt30ba4362014-08-21 20:18:45 -0700115 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
116 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
117 // declaration varies in earlier GLSL specs. So it is simpler to omit it.
118 if (fTopLeftFragPosRead) {
119 fSetupFragPosition = true;
120 return "gl_FragCoord";
egdaniel8dcdedc2015-11-11 06:27:20 -0800121 } else if (const char* extension = glslCaps->fragCoordConventionsExtensionString()) {
joshualitt30ba4362014-08-21 20:18:45 -0700122 if (!fSetupFragPosition) {
egdaniel8dcdedc2015-11-11 06:27:20 -0800123 if (glslCaps->generation() < k150_GrGLSLGeneration) {
joshualitt30ba4362014-08-21 20:18:45 -0700124 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
egdaniel8dcdedc2015-11-11 06:27:20 -0800125 extension);
joshualitt30ba4362014-08-21 20:18:45 -0700126 }
127 fInputs.push_back().set(kVec4f_GrSLType,
egdaniel0d3f0612015-10-21 10:45:48 -0700128 GrGLSLShaderVar::kIn_TypeModifier,
joshualitt30ba4362014-08-21 20:18:45 -0700129 "gl_FragCoord",
bsalomonc0bd6482014-12-09 10:04:14 -0800130 kDefault_GrSLPrecision,
egdaniel0d3f0612015-10-21 10:45:48 -0700131 GrGLSLShaderVar::kUpperLeft_Origin);
joshualitt30ba4362014-08-21 20:18:45 -0700132 fSetupFragPosition = true;
133 }
134 return "gl_FragCoord";
135 } else {
robertphillips18c58c72015-07-21 12:06:52 -0700136 static const char* kTempName = "tmpXYFragCoord";
joshualitt30ba4362014-08-21 20:18:45 -0700137 static const char* kCoordName = "fragCoordYDown";
138 if (!fSetupFragPosition) {
joshualitt30ba4362014-08-21 20:18:45 -0700139 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
140 const char* rtHeightName;
141
142 fProgramBuilder->fUniformHandles.fRTHeightUni =
egdaniel8dcdedc2015-11-11 06:27:20 -0800143 fProgramBuilder->addFragPosUniform(GrGLSLProgramBuilder::kFragment_Visibility,
egdanielf3bace92015-11-06 06:57:12 -0800144 kFloat_GrSLType,
145 kDefault_GrSLPrecision,
146 "RTHeight",
147 &rtHeightName);
joshualitt30ba4362014-08-21 20:18:45 -0700148
robertphillips18c58c72015-07-21 12:06:52 -0700149 // The Adreno compiler seems to be very touchy about access to "gl_FragCoord".
150 // Accessing glFragCoord.zw can cause a program to fail to link. Additionally,
151 // depending on the surrounding code, accessing .xy with a uniform involved can
152 // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand
153 // (and only accessing .xy) seems to "fix" things.
154 this->codePrependf("\tvec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n",
155 kCoordName, kTempName, rtHeightName, kTempName);
156 this->codePrependf("vec2 %s = gl_FragCoord.xy;", kTempName);
joshualitt30ba4362014-08-21 20:18:45 -0700157 fSetupFragPosition = true;
158 }
159 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
160 return kCoordName;
161 }
162}
163
egdaniel2d721d32015-11-11 13:06:05 -0800164const char* GrGLSLFragmentShaderBuilder::dstColor() {
joshualitt47bb3822014-10-07 16:43:25 -0700165 fHasReadDstColor = true;
166
egdaniel472d44e2015-10-22 08:20:00 -0700167 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
168 if (glslCaps->fbFetchSupport()) {
egdaniel2d721d32015-11-11 13:06:05 -0800169 this->addFeature(1 << (GrGLSLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
egdaniel472d44e2015-10-22 08:20:00 -0700170 glslCaps->fbFetchExtensionString());
joshualittb4384b92014-10-21 12:53:15 -0700171
joshualitt3c1096f2015-01-13 13:13:59 -0800172 // Some versions of this extension string require declaring custom color output on ES 3.0+
egdaniel472d44e2015-10-22 08:20:00 -0700173 const char* fbFetchColorName = glslCaps->fbFetchColorName();
174 if (glslCaps->fbFetchNeedsCustomOutput()) {
joshualittb4384b92014-10-21 12:53:15 -0700175 this->enableCustomOutput();
176 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
egdaniel8dcdedc2015-11-11 06:27:20 -0800177 fbFetchColorName = DeclaredColorOutputName();
joshualittb4384b92014-10-21 12:53:15 -0700178 }
179 return fbFetchColorName;
bsalomon50785a32015-02-06 07:02:37 -0800180 } else {
bsalomon6a44c6a2015-05-26 09:49:05 -0700181 return kDstTextureColorName;
bsalomon50785a32015-02-06 07:02:37 -0800182 }
joshualitt47bb3822014-10-07 16:43:25 -0700183}
184
egdaniel2d721d32015-11-11 13:06:05 -0800185void GrGLSLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) {
cdalton8917d622015-05-06 13:40:21 -0700186 SkASSERT(GrBlendEquationIsAdvanced(equation));
187
egdaniel472d44e2015-10-22 08:20:00 -0700188 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
cdalton8917d622015-05-06 13:40:21 -0700189 if (!caps.mustEnableAdvBlendEqs()) {
190 return;
191 }
192
193 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature,
194 "GL_KHR_blend_equation_advanced");
195 if (caps.mustEnableSpecificAdvBlendEqs()) {
196 this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_InterfaceQualifier);
197 } else {
198 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier);
199 }
200}
201
egdaniel2d721d32015-11-11 13:06:05 -0800202void GrGLSLFragmentShaderBuilder::enableCustomOutput() {
joshualittb4384b92014-10-21 12:53:15 -0700203 if (!fHasCustomColorOutput) {
204 fHasCustomColorOutput = true;
205 fCustomColorOutputIndex = fOutputs.count();
206 fOutputs.push_back().set(kVec4f_GrSLType,
egdaniel0d3f0612015-10-21 10:45:48 -0700207 GrGLSLShaderVar::kOut_TypeModifier,
egdaniel8dcdedc2015-11-11 06:27:20 -0800208 DeclaredColorOutputName());
joshualittb4384b92014-10-21 12:53:15 -0700209 }
joshualitt47bb3822014-10-07 16:43:25 -0700210}
211
egdaniel2d721d32015-11-11 13:06:05 -0800212void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() {
joshualitt47bb3822014-10-07 16:43:25 -0700213 SkASSERT(!fHasSecondaryOutput);
214 fHasSecondaryOutput = true;
egdaniel8dcdedc2015-11-11 06:27:20 -0800215 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
216 if (const char* extension = caps.secondaryOutputExtensionString()) {
217 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension);
kkinnunend94708e2015-07-30 22:47:04 -0700218 }
219
220 // If the primary output is declared, we must declare also the secondary output
221 // and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
222 // output. The condition also co-incides with the condition in whici GLES SL 2.0
223 // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
kkinnunend94708e2015-07-30 22:47:04 -0700224 if (caps.mustDeclareFragmentShaderOutput()) {
egdaniel0d3f0612015-10-21 10:45:48 -0700225 fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModifier,
egdaniel8dcdedc2015-11-11 06:27:20 -0800226 DeclaredSecondaryColorOutputName());
kkinnunend94708e2015-07-30 22:47:04 -0700227 }
joshualitt47bb3822014-10-07 16:43:25 -0700228}
229
egdaniel2d721d32015-11-11 13:06:05 -0800230const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const {
egdaniel8dcdedc2015-11-11 06:27:20 -0800231 return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor";
joshualitt47bb3822014-10-07 16:43:25 -0700232}
233
egdaniel2d721d32015-11-11 13:06:05 -0800234const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const {
egdaniel8dcdedc2015-11-11 06:27:20 -0800235 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
236 return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutputName()
kkinnunend94708e2015-07-30 22:47:04 -0700237 : "gl_SecondaryFragColorEXT";
joshualitt47bb3822014-10-07 16:43:25 -0700238}
239
egdaniel2d721d32015-11-11 13:06:05 -0800240void GrGLSLFragmentShaderBuilder::onFinalize() {
egdaniel0eafe792015-11-20 14:01:22 -0800241 fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
egdanielcb7ba1e2015-10-26 08:38:25 -0700242 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
243 *fProgramBuilder->glslCaps(),
244 &this->precisionQualifier());
joshualitt30ba4362014-08-21 20:18:45 -0700245}
246
egdaniel2d721d32015-11-11 13:06:05 -0800247void GrGLSLFragmentBuilder::onBeforeChildProcEmitCode() {
wangyix54a6b1a2015-09-08 08:41:51 -0700248 SkASSERT(fSubstageIndices.count() >= 1);
wangyix7ef45a12015-08-13 06:51:35 -0700249 fSubstageIndices.push_back(0);
wangyix54a6b1a2015-09-08 08:41:51 -0700250 // second-to-last value in the fSubstageIndices stack is the index of the child proc
251 // at that level which is currently emitting code.
252 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]);
wangyix7ef45a12015-08-13 06:51:35 -0700253}
254
egdaniel2d721d32015-11-11 13:06:05 -0800255void GrGLSLFragmentBuilder::onAfterChildProcEmitCode() {
wangyix54a6b1a2015-09-08 08:41:51 -0700256 SkASSERT(fSubstageIndices.count() >= 2);
wangyix7ef45a12015-08-13 06:51:35 -0700257 fSubstageIndices.pop_back();
wangyix54a6b1a2015-09-08 08:41:51 -0700258 fSubstageIndices.back()++;
wangyix7ef45a12015-08-13 06:51:35 -0700259 int removeAt = fMangleString.findLastOf('_');
260 fMangleString.remove(removeAt, fMangleString.size() - removeAt);
261}
egdaniel8dcdedc2015-11-11 06:27:20 -0800262