blob: eea8850f8ff334efc8b275247f5ff3aac0b1918e [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
8#include "GrGLFragmentShaderBuilder.h"
egdaniel574a4c12015-11-02 06:22:44 -08009#include "GrRenderTarget.h"
joshualitt30ba4362014-08-21 20:18:45 -070010#include "GrGLProgramBuilder.h"
jvanverthcba99b82015-06-24 06:59:57 -070011#include "gl/GrGLGpu.h"
egdanielcb7ba1e2015-10-26 08:38:25 -070012#include "glsl/GrGLSL.h"
jvanverthcba99b82015-06-24 06:59:57 -070013#include "glsl/GrGLSLCaps.h"
joshualitt30ba4362014-08-21 20:18:45 -070014
joshualitt47bb3822014-10-07 16:43:25 -070015#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
bsalomon6a44c6a2015-05-26 09:49:05 -070018const char* GrGLFragmentShaderBuilder::kDstTextureColorName = "_dstColor";
joshualitt47bb3822014-10-07 16:43:25 -070019static const char* declared_color_output_name() { return "fsColorOut"; }
kkinnunend94708e2015-07-30 22:47:04 -070020static const char* declared_secondary_color_output_name() { return "fsSecondaryColorOut"; }
joshualitt30ba4362014-08-21 20:18:45 -070021
cdalton8917d622015-05-06 13:40:21 -070022static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
23 SkASSERT(GrBlendEquationIsAdvanced(equation));
24
25 static const char* kLayoutQualifierNames[] = {
26 "blend_support_screen",
27 "blend_support_overlay",
28 "blend_support_darken",
29 "blend_support_lighten",
30 "blend_support_colordodge",
31 "blend_support_colorburn",
32 "blend_support_hardlight",
33 "blend_support_softlight",
34 "blend_support_difference",
35 "blend_support_exclusion",
36 "blend_support_multiply",
37 "blend_support_hsl_hue",
38 "blend_support_hsl_saturation",
39 "blend_support_hsl_color",
40 "blend_support_hsl_luminosity"
41 };
42 return kLayoutQualifierNames[equation - kFirstAdvancedGrBlendEquation];
43
44 GR_STATIC_ASSERT(0 == kScreen_GrBlendEquation - kFirstAdvancedGrBlendEquation);
45 GR_STATIC_ASSERT(1 == kOverlay_GrBlendEquation - kFirstAdvancedGrBlendEquation);
46 GR_STATIC_ASSERT(2 == kDarken_GrBlendEquation - kFirstAdvancedGrBlendEquation);
47 GR_STATIC_ASSERT(3 == kLighten_GrBlendEquation - kFirstAdvancedGrBlendEquation);
48 GR_STATIC_ASSERT(4 == kColorDodge_GrBlendEquation - kFirstAdvancedGrBlendEquation);
49 GR_STATIC_ASSERT(5 == kColorBurn_GrBlendEquation - kFirstAdvancedGrBlendEquation);
50 GR_STATIC_ASSERT(6 == kHardLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
51 GR_STATIC_ASSERT(7 == kSoftLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
52 GR_STATIC_ASSERT(8 == kDifference_GrBlendEquation - kFirstAdvancedGrBlendEquation);
53 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEquation);
54 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEquation);
55 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquation);
56 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlendEquation);
57 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEquation);
58 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlendEquation);
59 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) ==
bsalomonf7cc8772015-05-11 11:21:14 -070060 kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
cdalton8917d622015-05-06 13:40:21 -070061}
62
joshualitt47bb3822014-10-07 16:43:25 -070063GrGLFragmentShaderBuilder::FragPosKey
egdaniel574a4c12015-11-02 06:22:44 -080064GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst) {
joshualitt30ba4362014-08-21 20:18:45 -070065 if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
66 return kTopLeftFragPosRead_FragPosKey;
67 } else {
68 return kBottomLeftFragPosRead_FragPosKey;
69 }
70}
71
72GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program,
joshualitt79f8fae2014-10-28 17:59:26 -070073 uint8_t fragPosKey)
joshualitt30ba4362014-08-21 20:18:45 -070074 : INHERITED(program)
75 , fHasCustomColorOutput(false)
76 , fHasSecondaryOutput(false)
77 , fSetupFragPosition(false)
joshualitt79f8fae2014-10-28 17:59:26 -070078 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey)
joshualittb4384b92014-10-21 12:53:15 -070079 , fCustomColorOutputIndex(-1)
joshualitt47bb3822014-10-07 16:43:25 -070080 , fHasReadDstColor(false)
81 , fHasReadFragmentPosition(false) {
joshualitt30ba4362014-08-21 20:18:45 -070082}
83
84bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
85 switch (feature) {
86 case kStandardDerivatives_GLSLFeature: {
egdaniel574a4c12015-11-02 06:22:44 -080087 if (!fProgramBuilder->glslCaps()->shaderDerivativeSupport()) {
joshualitt30ba4362014-08-21 20:18:45 -070088 return false;
89 }
egdaniel574a4c12015-11-02 06:22:44 -080090 const char* extension = fProgramBuilder->glslCaps()->shaderDerivativeExtensionString();
91 if (extension) {
92 this->addFeature(1 << kStandardDerivatives_GLSLFeature, extension);
joshualitt30ba4362014-08-21 20:18:45 -070093 }
94 return true;
95 }
96 default:
97 SkFAIL("Unexpected GLSLFeature requested.");
98 return false;
99 }
100}
101
egdaniel7dc4bd02015-10-29 07:57:01 -0700102SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(const GrGLSLTransformedCoordsArray& coords,
103 int index) {
joshualitt23e280d2014-09-18 12:26:38 -0700104 if (kVec3f_GrSLType != coords[index].getType()) {
105 SkASSERT(kVec2f_GrSLType == coords[index].getType());
joshualitt30ba4362014-08-21 20:18:45 -0700106 return coords[index].getName();
107 }
108
109 SkString coords2D("coords2D");
110 if (0 != index) {
111 coords2D.appendf("_%i", index);
112 }
113 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;",
114 coords2D.c_str(), coords[index].c_str(), coords[index].c_str());
115 return coords2D;
116}
117
118const char* GrGLFragmentShaderBuilder::fragmentPosition() {
joshualitt47bb3822014-10-07 16:43:25 -0700119 fHasReadFragmentPosition = true;
joshualitt30ba4362014-08-21 20:18:45 -0700120
bsalomon861e1032014-12-16 07:33:49 -0800121 GrGLGpu* gpu = fProgramBuilder->gpu();
joshualitt30ba4362014-08-21 20:18:45 -0700122 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
123 // 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.
125 if (fTopLeftFragPosRead) {
126 fSetupFragPosition = true;
127 return "gl_FragCoord";
128 } else if (gpu->glCaps().fragCoordConventionsSupport()) {
129 if (!fSetupFragPosition) {
130 if (gpu->glslGeneration() < k150_GrGLSLGeneration) {
131 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
132 "GL_ARB_fragment_coord_conventions");
133 }
134 fInputs.push_back().set(kVec4f_GrSLType,
egdaniel0d3f0612015-10-21 10:45:48 -0700135 GrGLSLShaderVar::kIn_TypeModifier,
joshualitt30ba4362014-08-21 20:18:45 -0700136 "gl_FragCoord",
bsalomonc0bd6482014-12-09 10:04:14 -0800137 kDefault_GrSLPrecision,
egdaniel0d3f0612015-10-21 10:45:48 -0700138 GrGLSLShaderVar::kUpperLeft_Origin);
joshualitt30ba4362014-08-21 20:18:45 -0700139 fSetupFragPosition = true;
140 }
141 return "gl_FragCoord";
142 } else {
robertphillips18c58c72015-07-21 12:06:52 -0700143 static const char* kTempName = "tmpXYFragCoord";
joshualitt30ba4362014-08-21 20:18:45 -0700144 static const char* kCoordName = "fragCoordYDown";
145 if (!fSetupFragPosition) {
146 // temporarily change the stage index because we're inserting non-stage code.
joshualitt47bb3822014-10-07 16:43:25 -0700147 GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder);
joshualitt30ba4362014-08-21 20:18:45 -0700148 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
149 const char* rtHeightName;
150
151 fProgramBuilder->fUniformHandles.fRTHeightUni =
152 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
joshualitt47bb3822014-10-07 16:43:25 -0700153 kFloat_GrSLType,
bsalomon422f56f2014-12-09 10:18:12 -0800154 kDefault_GrSLPrecision,
joshualitt47bb3822014-10-07 16:43:25 -0700155 "RTHeight",
156 &rtHeightName);
joshualitt30ba4362014-08-21 20:18:45 -0700157
robertphillips18c58c72015-07-21 12:06:52 -0700158 // The Adreno compiler seems to be very touchy about access to "gl_FragCoord".
159 // Accessing glFragCoord.zw can cause a program to fail to link. Additionally,
160 // depending on the surrounding code, accessing .xy with a uniform involved can
161 // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand
162 // (and only accessing .xy) seems to "fix" things.
163 this->codePrependf("\tvec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n",
164 kCoordName, kTempName, rtHeightName, kTempName);
165 this->codePrependf("vec2 %s = gl_FragCoord.xy;", kTempName);
joshualitt30ba4362014-08-21 20:18:45 -0700166 fSetupFragPosition = true;
167 }
168 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
169 return kCoordName;
170 }
171}
172
joshualitt47bb3822014-10-07 16:43:25 -0700173const char* GrGLFragmentShaderBuilder::dstColor() {
174 fHasReadDstColor = true;
175
egdaniel472d44e2015-10-22 08:20:00 -0700176 const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
177 if (glslCaps->fbFetchSupport()) {
joshualitt47bb3822014-10-07 16:43:25 -0700178 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
egdaniel472d44e2015-10-22 08:20:00 -0700179 glslCaps->fbFetchExtensionString());
joshualittb4384b92014-10-21 12:53:15 -0700180
joshualitt3c1096f2015-01-13 13:13:59 -0800181 // Some versions of this extension string require declaring custom color output on ES 3.0+
egdaniel472d44e2015-10-22 08:20:00 -0700182 const char* fbFetchColorName = glslCaps->fbFetchColorName();
183 if (glslCaps->fbFetchNeedsCustomOutput()) {
joshualittb4384b92014-10-21 12:53:15 -0700184 this->enableCustomOutput();
185 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
186 fbFetchColorName = declared_color_output_name();
187 }
188 return fbFetchColorName;
bsalomon50785a32015-02-06 07:02:37 -0800189 } else {
bsalomon6a44c6a2015-05-26 09:49:05 -0700190 return kDstTextureColorName;
bsalomon50785a32015-02-06 07:02:37 -0800191 }
joshualitt47bb3822014-10-07 16:43:25 -0700192}
193
cdalton8917d622015-05-06 13:40:21 -0700194void GrGLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) {
195 SkASSERT(GrBlendEquationIsAdvanced(equation));
196
egdaniel472d44e2015-10-22 08:20:00 -0700197 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
cdalton8917d622015-05-06 13:40:21 -0700198 if (!caps.mustEnableAdvBlendEqs()) {
199 return;
200 }
201
202 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature,
203 "GL_KHR_blend_equation_advanced");
204 if (caps.mustEnableSpecificAdvBlendEqs()) {
205 this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_InterfaceQualifier);
206 } else {
207 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier);
208 }
209}
210
joshualitt47bb3822014-10-07 16:43:25 -0700211void GrGLFragmentShaderBuilder::enableCustomOutput() {
joshualittb4384b92014-10-21 12:53:15 -0700212 if (!fHasCustomColorOutput) {
213 fHasCustomColorOutput = true;
214 fCustomColorOutputIndex = fOutputs.count();
215 fOutputs.push_back().set(kVec4f_GrSLType,
egdaniel0d3f0612015-10-21 10:45:48 -0700216 GrGLSLShaderVar::kOut_TypeModifier,
joshualittb4384b92014-10-21 12:53:15 -0700217 declared_color_output_name());
218 }
joshualitt47bb3822014-10-07 16:43:25 -0700219}
220
221void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
222 SkASSERT(!fHasSecondaryOutput);
223 fHasSecondaryOutput = true;
kkinnunend94708e2015-07-30 22:47:04 -0700224 if (kGLES_GrGLStandard == fProgramBuilder->gpu()->ctxInfo().standard()) {
225 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, "GL_EXT_blend_func_extended");
226 }
227
228 // If the primary output is declared, we must declare also the secondary output
229 // and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
230 // output. The condition also co-incides with the condition in whici GLES SL 2.0
231 // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
egdaniel574a4c12015-11-02 06:22:44 -0800232 const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
kkinnunend94708e2015-07-30 22:47:04 -0700233 if (caps.mustDeclareFragmentShaderOutput()) {
egdaniel0d3f0612015-10-21 10:45:48 -0700234 fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModifier,
kkinnunend94708e2015-07-30 22:47:04 -0700235 declared_secondary_color_output_name());
236 }
joshualitt47bb3822014-10-07 16:43:25 -0700237}
238
239const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
240 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
241}
242
243const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const {
kkinnunend94708e2015-07-30 22:47:04 -0700244 const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps();
245 return caps.mustDeclareFragmentShaderOutput() ? declared_secondary_color_output_name()
246 : "gl_SecondaryFragColorEXT";
joshualitt47bb3822014-10-07 16:43:25 -0700247}
248
egdaniel574a4c12015-11-02 06:22:44 -0800249void GrGLFragmentShaderBuilder::onFinalize() {
egdanielcb7ba1e2015-10-26 08:38:25 -0700250 GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
251 *fProgramBuilder->glslCaps(),
252 &this->precisionQualifier());
joshualitt30ba4362014-08-21 20:18:45 -0700253}
254
joshualitt47bb3822014-10-07 16:43:25 -0700255void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
kkinnunend94708e2015-07-30 22:47:04 -0700256 const GrGLCaps& caps = fProgramBuilder->gpu()->glCaps();
257 if (fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
joshualitt47bb3822014-10-07 16:43:25 -0700258 GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
joshualitt30ba4362014-08-21 20:18:45 -0700259 }
kkinnunend94708e2015-07-30 22:47:04 -0700260 if (fHasSecondaryOutput && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
261 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
262 declared_secondary_color_output_name()));
joshualitt30ba4362014-08-21 20:18:45 -0700263 }
264}
265
bsalomonc0bd6482014-12-09 10:04:14 -0800266void GrGLFragmentShaderBuilder::addVarying(GrGLVarying* v, GrSLPrecision fsPrec) {
joshualitt74077b92014-10-24 11:26:03 -0700267 v->fFsIn = v->fVsOut;
268 if (v->fGsOut) {
269 v->fFsIn = v->fGsOut;
joshualitt30ba4362014-08-21 20:18:45 -0700270 }
egdaniel0d3f0612015-10-21 10:45:48 -0700271 fInputs.push_back().set(v->fType, GrGLSLShaderVar::kVaryingIn_TypeModifier, v->fFsIn, fsPrec);
joshualitt30ba4362014-08-21 20:18:45 -0700272}
wangyix7ef45a12015-08-13 06:51:35 -0700273
274void GrGLFragmentBuilder::onBeforeChildProcEmitCode() {
wangyix54a6b1a2015-09-08 08:41:51 -0700275 SkASSERT(fSubstageIndices.count() >= 1);
wangyix7ef45a12015-08-13 06:51:35 -0700276 fSubstageIndices.push_back(0);
wangyix54a6b1a2015-09-08 08:41:51 -0700277 // second-to-last value in the fSubstageIndices stack is the index of the child proc
278 // at that level which is currently emitting code.
279 fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]);
wangyix7ef45a12015-08-13 06:51:35 -0700280}
281
282void GrGLFragmentBuilder::onAfterChildProcEmitCode() {
wangyix54a6b1a2015-09-08 08:41:51 -0700283 SkASSERT(fSubstageIndices.count() >= 2);
wangyix7ef45a12015-08-13 06:51:35 -0700284 fSubstageIndices.pop_back();
wangyix54a6b1a2015-09-08 08:41:51 -0700285 fSubstageIndices.back()++;
wangyix7ef45a12015-08-13 06:51:35 -0700286 int removeAt = fMangleString.findLastOf('_');
287 fMangleString.remove(removeAt, fMangleString.size() - removeAt);
288}