blob: 8fcb0b972e583b8508fe9eaf41ff5623678fe045 [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"
joshualitt30ba4362014-08-21 20:18:45 -07009#include "GrGLProgramBuilder.h"
jvanverth39edf762014-12-22 11:44:19 -080010#include "../GrGLGpu.h"
joshualitt30ba4362014-08-21 20:18:45 -070011
joshualitt47bb3822014-10-07 16:43:25 -070012#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
13#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
14
joshualitt47bb3822014-10-07 16:43:25 -070015const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor";
16static const char* declared_color_output_name() { return "fsColorOut"; }
17static const char* dual_source_output_name() { return "dualSourceOut"; }
bsalomonc0bd6482014-12-09 10:04:14 -080018static void append_default_precision_qualifier(GrSLPrecision p,
joshualitt30ba4362014-08-21 20:18:45 -070019 GrGLStandard standard,
20 SkString* str) {
21 // Desktop GLSL has added precision qualifiers but they don't do anything.
22 if (kGLES_GrGLStandard == standard) {
23 switch (p) {
bsalomonc0bd6482014-12-09 10:04:14 -080024 case kHigh_GrSLPrecision:
joshualitt30ba4362014-08-21 20:18:45 -070025 str->append("precision highp float;\n");
26 break;
bsalomonc0bd6482014-12-09 10:04:14 -080027 case kMedium_GrSLPrecision:
joshualitt30ba4362014-08-21 20:18:45 -070028 str->append("precision mediump float;\n");
29 break;
bsalomonc0bd6482014-12-09 10:04:14 -080030 case kLow_GrSLPrecision:
joshualitt30ba4362014-08-21 20:18:45 -070031 str->append("precision lowp float;\n");
32 break;
joshualitt30ba4362014-08-21 20:18:45 -070033 default:
34 SkFAIL("Unknown precision value.");
35 }
36 }
37}
joshualitt30ba4362014-08-21 20:18:45 -070038
cdalton8917d622015-05-06 13:40:21 -070039static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
40 SkASSERT(GrBlendEquationIsAdvanced(equation));
41
42 static const char* kLayoutQualifierNames[] = {
43 "blend_support_screen",
44 "blend_support_overlay",
45 "blend_support_darken",
46 "blend_support_lighten",
47 "blend_support_colordodge",
48 "blend_support_colorburn",
49 "blend_support_hardlight",
50 "blend_support_softlight",
51 "blend_support_difference",
52 "blend_support_exclusion",
53 "blend_support_multiply",
54 "blend_support_hsl_hue",
55 "blend_support_hsl_saturation",
56 "blend_support_hsl_color",
57 "blend_support_hsl_luminosity"
58 };
59 return kLayoutQualifierNames[equation - kFirstAdvancedGrBlendEquation];
60
61 GR_STATIC_ASSERT(0 == kScreen_GrBlendEquation - kFirstAdvancedGrBlendEquation);
62 GR_STATIC_ASSERT(1 == kOverlay_GrBlendEquation - kFirstAdvancedGrBlendEquation);
63 GR_STATIC_ASSERT(2 == kDarken_GrBlendEquation - kFirstAdvancedGrBlendEquation);
64 GR_STATIC_ASSERT(3 == kLighten_GrBlendEquation - kFirstAdvancedGrBlendEquation);
65 GR_STATIC_ASSERT(4 == kColorDodge_GrBlendEquation - kFirstAdvancedGrBlendEquation);
66 GR_STATIC_ASSERT(5 == kColorBurn_GrBlendEquation - kFirstAdvancedGrBlendEquation);
67 GR_STATIC_ASSERT(6 == kHardLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
68 GR_STATIC_ASSERT(7 == kSoftLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
69 GR_STATIC_ASSERT(8 == kDifference_GrBlendEquation - kFirstAdvancedGrBlendEquation);
70 GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEquation);
71 GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEquation);
72 GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquation);
73 GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlendEquation);
74 GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEquation);
75 GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlendEquation);
76 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) ==
77 kTotalGrBlendEquationCount - kFirstAdvancedGrBlendEquation);
78}
79
joshualitt47bb3822014-10-07 16:43:25 -070080GrGLFragmentShaderBuilder::DstReadKey
rmistry63a9f842014-10-17 06:07:08 -070081GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps& caps) {
joshualitt30ba4362014-08-21 20:18:45 -070082 uint32_t key = kYesDstRead_DstReadKeyBit;
jvanverthe9c0fc62015-04-29 11:18:05 -070083 if (caps.glslCaps()->fbFetchSupport()) {
joshualitt30ba4362014-08-21 20:18:45 -070084 return key;
85 }
bsalomon49f085d2014-09-05 13:34:00 -070086 SkASSERT(dstCopy);
joshualitt30ba4362014-08-21 20:18:45 -070087 if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
88 // The fact that the config is alpha-only must be considered when generating code.
89 key |= kUseAlphaConfig_DstReadKeyBit;
90 }
91 if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
92 key |= kTopLeftOrigin_DstReadKeyBit;
93 }
94 SkASSERT(static_cast<DstReadKey>(key) == key);
95 return static_cast<DstReadKey>(key);
96}
97
joshualitt47bb3822014-10-07 16:43:25 -070098GrGLFragmentShaderBuilder::FragPosKey
rmistry63a9f842014-10-17 06:07:08 -070099GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst, const GrGLCaps&) {
joshualitt30ba4362014-08-21 20:18:45 -0700100 if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
101 return kTopLeftFragPosRead_FragPosKey;
102 } else {
103 return kBottomLeftFragPosRead_FragPosKey;
104 }
105}
106
107GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program,
joshualitt79f8fae2014-10-28 17:59:26 -0700108 uint8_t fragPosKey)
joshualitt30ba4362014-08-21 20:18:45 -0700109 : INHERITED(program)
110 , fHasCustomColorOutput(false)
111 , fHasSecondaryOutput(false)
112 , fSetupFragPosition(false)
joshualitt79f8fae2014-10-28 17:59:26 -0700113 , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey)
joshualittb4384b92014-10-21 12:53:15 -0700114 , fCustomColorOutputIndex(-1)
joshualitt47bb3822014-10-07 16:43:25 -0700115 , fHasReadDstColor(false)
116 , fHasReadFragmentPosition(false) {
joshualitt30ba4362014-08-21 20:18:45 -0700117}
118
119bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
120 switch (feature) {
121 case kStandardDerivatives_GLSLFeature: {
bsalomon861e1032014-12-16 07:33:49 -0800122 GrGLGpu* gpu = fProgramBuilder->gpu();
jvanverthe9c0fc62015-04-29 11:18:05 -0700123 if (!gpu->glCaps().shaderCaps()->shaderDerivativeSupport()) {
joshualitt30ba4362014-08-21 20:18:45 -0700124 return false;
125 }
rmistry63a9f842014-10-17 06:07:08 -0700126 if (kGLES_GrGLStandard == gpu->glStandard() &&
127 k110_GrGLSLGeneration == gpu->glslGeneration()) {
joshualitt30ba4362014-08-21 20:18:45 -0700128 this->addFeature(1 << kStandardDerivatives_GLSLFeature,
129 "GL_OES_standard_derivatives");
130 }
131 return true;
132 }
133 default:
134 SkFAIL("Unexpected GLSLFeature requested.");
135 return false;
136 }
137}
138
joshualittb0a8a372014-09-23 09:50:21 -0700139SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(
140 const GrGLProcessor::TransformedCoordsArray& coords, int index) {
joshualitt23e280d2014-09-18 12:26:38 -0700141 if (kVec3f_GrSLType != coords[index].getType()) {
142 SkASSERT(kVec2f_GrSLType == coords[index].getType());
joshualitt30ba4362014-08-21 20:18:45 -0700143 return coords[index].getName();
144 }
145
146 SkString coords2D("coords2D");
147 if (0 != index) {
148 coords2D.appendf("_%i", index);
149 }
150 this->codeAppendf("\tvec2 %s = %s.xy / %s.z;",
151 coords2D.c_str(), coords[index].c_str(), coords[index].c_str());
152 return coords2D;
153}
154
155const char* GrGLFragmentShaderBuilder::fragmentPosition() {
joshualitt47bb3822014-10-07 16:43:25 -0700156 fHasReadFragmentPosition = true;
joshualitt30ba4362014-08-21 20:18:45 -0700157
bsalomon861e1032014-12-16 07:33:49 -0800158 GrGLGpu* gpu = fProgramBuilder->gpu();
joshualitt30ba4362014-08-21 20:18:45 -0700159 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
160 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
161 // declaration varies in earlier GLSL specs. So it is simpler to omit it.
162 if (fTopLeftFragPosRead) {
163 fSetupFragPosition = true;
164 return "gl_FragCoord";
165 } else if (gpu->glCaps().fragCoordConventionsSupport()) {
166 if (!fSetupFragPosition) {
167 if (gpu->glslGeneration() < k150_GrGLSLGeneration) {
168 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
169 "GL_ARB_fragment_coord_conventions");
170 }
171 fInputs.push_back().set(kVec4f_GrSLType,
172 GrGLShaderVar::kIn_TypeModifier,
173 "gl_FragCoord",
bsalomonc0bd6482014-12-09 10:04:14 -0800174 kDefault_GrSLPrecision,
joshualitt30ba4362014-08-21 20:18:45 -0700175 GrGLShaderVar::kUpperLeft_Origin);
176 fSetupFragPosition = true;
177 }
178 return "gl_FragCoord";
179 } else {
180 static const char* kCoordName = "fragCoordYDown";
181 if (!fSetupFragPosition) {
182 // temporarily change the stage index because we're inserting non-stage code.
joshualitt47bb3822014-10-07 16:43:25 -0700183 GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder);
joshualitt30ba4362014-08-21 20:18:45 -0700184 SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
185 const char* rtHeightName;
186
187 fProgramBuilder->fUniformHandles.fRTHeightUni =
188 fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
joshualitt47bb3822014-10-07 16:43:25 -0700189 kFloat_GrSLType,
bsalomon422f56f2014-12-09 10:18:12 -0800190 kDefault_GrSLPrecision,
joshualitt47bb3822014-10-07 16:43:25 -0700191 "RTHeight",
192 &rtHeightName);
joshualitt30ba4362014-08-21 20:18:45 -0700193
194 // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that
195 // causes programs to fail to link. Making this function return a vec2() didn't fix the
196 // problem but using 1.0 for the last two components does.
197 this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, "
198 "1.0);\n", kCoordName, rtHeightName);
199 fSetupFragPosition = true;
200 }
201 SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
202 return kCoordName;
203 }
204}
205
joshualitt47bb3822014-10-07 16:43:25 -0700206const char* GrGLFragmentShaderBuilder::dstColor() {
207 fHasReadDstColor = true;
208
bsalomon861e1032014-12-16 07:33:49 -0800209 GrGLGpu* gpu = fProgramBuilder->gpu();
jvanverthe9c0fc62015-04-29 11:18:05 -0700210 if (gpu->glCaps().glslCaps()->fbFetchSupport()) {
joshualitt47bb3822014-10-07 16:43:25 -0700211 this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
jvanverthe9c0fc62015-04-29 11:18:05 -0700212 gpu->glCaps().glslCaps()->fbFetchExtensionString());
joshualittb4384b92014-10-21 12:53:15 -0700213
joshualitt3c1096f2015-01-13 13:13:59 -0800214 // Some versions of this extension string require declaring custom color output on ES 3.0+
jvanverthe9c0fc62015-04-29 11:18:05 -0700215 const char* fbFetchColorName = gpu->glCaps().glslCaps()->fbFetchColorName();
216 if (gpu->glCaps().glslCaps()->fbFetchNeedsCustomOutput()) {
joshualittb4384b92014-10-21 12:53:15 -0700217 this->enableCustomOutput();
218 fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
219 fbFetchColorName = declared_color_output_name();
220 }
221 return fbFetchColorName;
bsalomon50785a32015-02-06 07:02:37 -0800222 } else {
joshualitt47bb3822014-10-07 16:43:25 -0700223 return kDstCopyColorName;
bsalomon50785a32015-02-06 07:02:37 -0800224 }
joshualitt47bb3822014-10-07 16:43:25 -0700225}
226
cdalton8917d622015-05-06 13:40:21 -0700227void GrGLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) {
228 SkASSERT(GrBlendEquationIsAdvanced(equation));
229
230 const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps();
231 if (!caps.mustEnableAdvBlendEqs()) {
232 return;
233 }
234
235 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature,
236 "GL_KHR_blend_equation_advanced");
237 if (caps.mustEnableSpecificAdvBlendEqs()) {
238 this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_InterfaceQualifier);
239 } else {
240 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier);
241 }
242}
243
joshualitt47bb3822014-10-07 16:43:25 -0700244void GrGLFragmentShaderBuilder::enableCustomOutput() {
joshualittb4384b92014-10-21 12:53:15 -0700245 if (!fHasCustomColorOutput) {
246 fHasCustomColorOutput = true;
247 fCustomColorOutputIndex = fOutputs.count();
248 fOutputs.push_back().set(kVec4f_GrSLType,
249 GrGLShaderVar::kOut_TypeModifier,
250 declared_color_output_name());
251 }
joshualitt47bb3822014-10-07 16:43:25 -0700252}
253
254void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
255 SkASSERT(!fHasSecondaryOutput);
256 fHasSecondaryOutput = true;
257 fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier,
258 dual_source_output_name());
259}
260
261const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
262 return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
263}
264
265const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const {
266 return dual_source_output_name();
267}
268
joshualitt30ba4362014-08-21 20:18:45 -0700269bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
joshualitt43466a12015-02-13 17:18:27 -0800270 SkTDArray<GrGLuint>* shaderIds) {
bsalomon861e1032014-12-16 07:33:49 -0800271 GrGLGpu* gpu = fProgramBuilder->gpu();
joshualitt43466a12015-02-13 17:18:27 -0800272 this->versionDecl() = GrGetGLSLVersionDecl(gpu->ctxInfo());
bsalomonc0bd6482014-12-09 10:04:14 -0800273 append_default_precision_qualifier(kDefault_GrSLPrecision,
joshualitt30ba4362014-08-21 20:18:45 -0700274 gpu->glStandard(),
joshualitt43466a12015-02-13 17:18:27 -0800275 &this->precisionQualifier());
cdaltone4017d82015-05-06 11:48:56 -0700276 this->compileAndAppendLayoutQualifiers();
joshualitt43466a12015-02-13 17:18:27 -0800277 fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility,
278 &this->uniforms());
279 this->appendDecls(fInputs, &this->inputs());
joshualitt30ba4362014-08-21 20:18:45 -0700280 // We shouldn't have declared outputs on 1.10
281 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
joshualitt43466a12015-02-13 17:18:27 -0800282 this->appendDecls(fOutputs, &this->outputs());
283 return this->finalize(programId, GR_GL_FRAGMENT_SHADER, shaderIds);
joshualitt30ba4362014-08-21 20:18:45 -0700284}
285
joshualitt47bb3822014-10-07 16:43:25 -0700286void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
rmistry63a9f842014-10-17 06:07:08 -0700287 // ES 3.00 requires custom color output but doesn't support bindFragDataLocation
288 if (fHasCustomColorOutput &&
289 kGLES_GrGLStandard != fProgramBuilder->gpu()->ctxInfo().standard()) {
joshualitt47bb3822014-10-07 16:43:25 -0700290 GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
joshualitt30ba4362014-08-21 20:18:45 -0700291 }
joshualitt47bb3822014-10-07 16:43:25 -0700292 if (fHasSecondaryOutput) {
293 GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name()));
joshualitt30ba4362014-08-21 20:18:45 -0700294 }
295}
296
bsalomonc0bd6482014-12-09 10:04:14 -0800297void GrGLFragmentShaderBuilder::addVarying(GrGLVarying* v, GrSLPrecision fsPrec) {
joshualitt74077b92014-10-24 11:26:03 -0700298 v->fFsIn = v->fVsOut;
299 if (v->fGsOut) {
300 v->fFsIn = v->fGsOut;
joshualitt30ba4362014-08-21 20:18:45 -0700301 }
joshualitt74077b92014-10-24 11:26:03 -0700302 fInputs.push_back().set(v->fType, GrGLShaderVar::kVaryingIn_TypeModifier, v->fFsIn, fsPrec);
joshualitt30ba4362014-08-21 20:18:45 -0700303}