Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / gl / builders / GrGLFragmentShaderBuilder.cpp
1 /*
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"
9 #include "GrGLShaderStringBuilder.h"
10 #include "GrGLProgramBuilder.h"
11 #include "../GrGpuGL.h"
12
13 namespace {
14 #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
15 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
16 // ES2 FS only guarantees mediump and lowp support
17 static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
18 static const char kDstCopyColorName[] = "_dstColor";
19 inline const char* declared_color_output_name() { return "fsColorOut"; }
20 inline const char* dual_source_output_name() { return "dualSourceOut"; }
21 inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
22                                                GrGLStandard standard,
23                                                SkString* str) {
24     // Desktop GLSL has added precision qualifiers but they don't do anything.
25     if (kGLES_GrGLStandard == standard) {
26         switch (p) {
27             case GrGLShaderVar::kHigh_Precision:
28                 str->append("precision highp float;\n");
29                 break;
30             case GrGLShaderVar::kMedium_Precision:
31                 str->append("precision mediump float;\n");
32                 break;
33             case GrGLShaderVar::kLow_Precision:
34                 str->append("precision lowp float;\n");
35                 break;
36             case GrGLShaderVar::kDefault_Precision:
37                 SkFAIL("Default precision now allowed.");
38             default:
39                 SkFAIL("Unknown precision value.");
40         }
41     }
42 }
43 }
44
45 GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
46         const GrTexture* dstCopy, const GrGLCaps& caps) {
47     uint32_t key = kYesDstRead_DstReadKeyBit;
48     if (caps.fbFetchSupport()) {
49         return key;
50     }
51     SkASSERT(dstCopy);
52     if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
53         // The fact that the config is alpha-only must be considered when generating code.
54         key |= kUseAlphaConfig_DstReadKeyBit;
55     }
56     if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
57         key |= kTopLeftOrigin_DstReadKeyBit;
58     }
59     SkASSERT(static_cast<DstReadKey>(key) == key);
60     return static_cast<DstReadKey>(key);
61 }
62
63 GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition(
64         const GrRenderTarget* dst, const GrGLCaps&) {
65     if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
66         return kTopLeftFragPosRead_FragPosKey;
67     } else {
68         return kBottomLeftFragPosRead_FragPosKey;
69     }
70 }
71
72 GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program,
73                                                      const GrGLProgramDesc& desc)
74     : INHERITED(program)
75     , fHasCustomColorOutput(false)
76     , fHasSecondaryOutput(false)
77     , fSetupFragPosition(false)
78     , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){
79 }
80
81 const char* GrGLFragmentShaderBuilder::dstColor() {
82     if (fProgramBuilder->fCodeStage.inStageCode()) {
83         const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->getProcessor();
84         // TODO GPs can't read dst color, and full program builder only returns a pointer to the
85         // base fragment shader builder which does not have this function.  Unfortunately,
86         // the code stage class only has a GrProcessor pointer so this is required for the time
87         // being
88         if (!static_cast<const GrFragmentProcessor*>(effect)->willReadDstColor()) {
89             SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating GrProcessor "
90                         "did not request access.");
91             return "";
92         }
93     }
94
95     GrGpuGL* gpu = fProgramBuilder->gpu();
96     if (gpu->glCaps().fbFetchSupport()) {
97         this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
98                          gpu->glCaps().fbFetchExtensionString());
99         return gpu->glCaps().fbFetchColorName();
100     } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
101         return kDstCopyColorName;
102     } else {
103         return "";
104     }
105 }
106
107 bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
108     switch (feature) {
109         case kStandardDerivatives_GLSLFeature: {
110             GrGpuGL* gpu = fProgramBuilder->gpu();
111             if (!gpu->glCaps().shaderDerivativeSupport()) {
112                 return false;
113             }
114             if (kGLES_GrGLStandard == gpu->glStandard()) {
115                 this->addFeature(1 << kStandardDerivatives_GLSLFeature,
116                                  "GL_OES_standard_derivatives");
117             }
118             return true;
119         }
120         default:
121             SkFAIL("Unexpected GLSLFeature requested.");
122             return false;
123     }
124 }
125
126 SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(
127         const GrGLProcessor::TransformedCoordsArray& coords, int index) {
128     if (kVec3f_GrSLType != coords[index].getType()) {
129         SkASSERT(kVec2f_GrSLType == coords[index].getType());
130         return coords[index].getName();
131     }
132
133     SkString coords2D("coords2D");
134     if (0 != index) {
135         coords2D.appendf("_%i", index);
136     }
137     this->codeAppendf("\tvec2 %s = %s.xy / %s.z;",
138                       coords2D.c_str(), coords[index].c_str(), coords[index].c_str());
139     return coords2D;
140 }
141
142 const char* GrGLFragmentShaderBuilder::fragmentPosition() {
143     GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage;
144     if (cs->inStageCode()) {
145         const GrProcessor* effect = cs->effectStage()->getProcessor();
146         if (!effect->willReadFragmentPosition()) {
147             SkDEBUGFAIL("GrGLProcessor asked for frag position but its generating GrProcessor "
148                         "did not request access.");
149             return "";
150         }
151     }
152
153     GrGpuGL* gpu = fProgramBuilder->gpu();
154     // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
155     // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
156     // declaration varies in earlier GLSL specs. So it is simpler to omit it.
157     if (fTopLeftFragPosRead) {
158         fSetupFragPosition = true;
159         return "gl_FragCoord";
160     } else if (gpu->glCaps().fragCoordConventionsSupport()) {
161         if (!fSetupFragPosition) {
162             if (gpu->glslGeneration() < k150_GrGLSLGeneration) {
163                 this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
164                                  "GL_ARB_fragment_coord_conventions");
165             }
166             fInputs.push_back().set(kVec4f_GrSLType,
167                                     GrGLShaderVar::kIn_TypeModifier,
168                                     "gl_FragCoord",
169                                     GrGLShaderVar::kDefault_Precision,
170                                     GrGLShaderVar::kUpperLeft_Origin);
171             fSetupFragPosition = true;
172         }
173         return "gl_FragCoord";
174     } else {
175         static const char* kCoordName = "fragCoordYDown";
176         if (!fSetupFragPosition) {
177             // temporarily change the stage index because we're inserting non-stage code.
178             GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);
179
180             SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
181             const char* rtHeightName;
182
183             fProgramBuilder->fUniformHandles.fRTHeightUni =
184                     fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
185                                          kFloat_GrSLType,
186                                          "RTHeight",
187                                          &rtHeightName);
188
189             // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that
190             // causes programs to fail to link. Making this function return a vec2() didn't fix the
191             // problem but using 1.0 for the last two components does.
192             this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, "
193                                "1.0);\n", kCoordName, rtHeightName);
194             fSetupFragPosition = true;
195         }
196         SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
197         return kCoordName;
198     }
199 }
200
201 void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
202                const char* name,
203                const char** fsInName,
204                GrGLShaderVar::Precision fsPrecision) {
205     fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
206     if (fsInName) {
207         *fsInName = name;
208     }
209 }
210
211 void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
212     GrGpuGL* gpu = fProgramBuilder->gpu();
213     if (fHasCustomColorOutput) {
214         GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
215     }
216     if (fHasSecondaryOutput) {
217         GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
218     }
219 }
220
221 bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
222                                                         SkTDArray<GrGLuint>* shaderIds) const {
223     GrGpuGL* gpu = fProgramBuilder->gpu();
224     SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo()));
225     fragShaderSrc.append(fExtensions);
226     append_default_precision_qualifier(kDefaultFragmentPrecision,
227                                        gpu->glStandard(),
228                                        &fragShaderSrc);
229     fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
230     fProgramBuilder->appendDecls(fInputs, &fragShaderSrc);
231     // We shouldn't have declared outputs on 1.10
232     SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
233     fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc);
234     fragShaderSrc.append(fFunctions);
235     fragShaderSrc.append("void main() {\n");
236     fragShaderSrc.append(fCode);
237     fragShaderSrc.append("}\n");
238
239     GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId,
240                                                        GR_GL_FRAGMENT_SHADER, fragShaderSrc,
241                                                        gpu->gpuStats());
242     if (!fragShaderId) {
243         return false;
244     }
245
246     *shaderIds->append() = fragShaderId;
247
248     return true;
249 }
250
251 void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
252     const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
253     GrGpuGL* gpu = fProgramBuilder->gpu();
254
255     ///////////////////////////////////////////////////////////////////////////
256     // emit code to read the dst copy texture, if necessary
257     if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) {
258         bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
259         const char* dstCopyTopLeftName;
260         const char* dstCopyCoordScaleName;
261         const char* dstCopySamplerName;
262         uint32_t configMask;
263         if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
264             configMask = kA_GrColorComponentFlag;
265         } else {
266             configMask = kRGBA_GrColorComponentFlags;
267         }
268         fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
269             fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
270                                  kSampler2D_GrSLType,
271                                  "DstCopySampler",
272                                  &dstCopySamplerName);
273         fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
274             fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
275                                  kVec2f_GrSLType,
276                                  "DstCopyUpperLeft",
277                                  &dstCopyTopLeftName);
278         fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
279             fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
280                                  kVec2f_GrSLType,
281                                  "DstCopyCoordScale",
282                                  &dstCopyCoordScaleName);
283         const char* fragPos = fragmentPosition();
284
285         this->codeAppend("// Read color from copy of the destination.\n");
286         this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
287                           fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
288         if (!topDown) {
289             this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
290         }
291         this->codeAppendf("vec4 %s = ", kDstCopyColorName);
292         this->appendTextureLookup(dstCopySamplerName,
293                                   "_dstTexCoord",
294                                   configMask,
295                                   "rgba");
296         this->codeAppend(";");
297     }
298
299     if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
300         fOutputs.push_back().set(kVec4f_GrSLType,
301                                  GrGLShaderVar::kOut_TypeModifier,
302                                  declared_color_output_name());
303         fHasCustomColorOutput = true;
304     }
305 }
306
307 void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) {
308     const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
309
310     ///////////////////////////////////////////////////////////////////////////
311     // write the secondary color output if necessary
312     if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
313         const char* secondaryOutputName = this->enableSecondaryOutput();
314         GrGLSLExpr4 coeff(1);
315         switch (header.fSecondaryOutputType) {
316             case GrOptDrawState::kCoverage_SecondaryOutputType:
317                 break;
318             case GrOptDrawState::kCoverageISA_SecondaryOutputType:
319                 // Get (1-A) into coeff
320                 coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
321                 break;
322             case GrOptDrawState::kCoverageISC_SecondaryOutputType:
323                 // Get (1-RGBA) into coeff
324                 coeff = GrGLSLExpr4(1) - inputColor;
325                 break;
326             default:
327                 SkFAIL("Unexpected Secondary Output");
328         }
329         // Get coeff * coverage into modulate and then write that to the dual source output.
330         codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
331     }
332
333     ///////////////////////////////////////////////////////////////////////////
334     // combine color and coverage as frag color
335
336     // Get "color * coverage" into fragColor
337     GrGLSLExpr4 fragColor = inputColor * inputCoverage;
338     switch (header.fPrimaryOutputType) {
339         case GrOptDrawState::kModulate_PrimaryOutputType:
340             break;
341         case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
342             {
343                 // Tack on "+(1-coverage)dst onto the frag color.
344                 GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
345                 GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
346                 fragColor = fragColor + dstContribution;
347             }
348             break;
349         default:
350             SkFAIL("Unknown Primary Output");
351     }
352     codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
353 }
354
355 const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() {
356     if (!fHasSecondaryOutput) {
357         fOutputs.push_back().set(kVec4f_GrSLType,
358                                  GrGLShaderVar::kOut_TypeModifier,
359                                  dual_source_output_name());
360         fHasSecondaryOutput = true;
361     }
362     return dual_source_output_name();
363 }
364
365 const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
366     return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
367 }
368