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 "src/gpu/GrRenderTarget.h"
9 #include "src/gpu/GrShaderCaps.h"
10 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
11 #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
12 #include "src/gpu/glsl/GrGLSLUniformHandler.h"
13 #include "src/gpu/glsl/GrGLSLVarying.h"
14
GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder * program)15 GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
16 : GrGLSLShaderBuilder(program) {}
17
dstColor()18 const char* GrGLSLFragmentShaderBuilder::dstColor() {
19 SkDEBUGCODE(fHasReadDstColorThisStage_DebugOnly = true;)
20
21 const GrShaderCaps* shaderCaps = fProgramBuilder->shaderCaps();
22 if (shaderCaps->fbFetchSupport()) {
23 this->addFeature(1 << kFramebufferFetch_GLSLPrivateFeature,
24 shaderCaps->fbFetchExtensionString());
25
26 // Some versions of this extension string require declaring custom color output on ES 3.0+
27 const char* fbFetchColorName = "sk_LastFragColor";
28 if (shaderCaps->fbFetchNeedsCustomOutput()) {
29 this->enableCustomOutput();
30 fCustomColorOutput->setTypeModifier(GrShaderVar::TypeModifier::InOut);
31 fbFetchColorName = DeclaredColorOutputName();
32 // Set the dstColor to an intermediate variable so we don't override it with the output
33 this->codeAppendf("half4 %s = %s;", kDstColorName, fbFetchColorName);
34 } else {
35 return fbFetchColorName;
36 }
37 }
38 return kDstColorName;
39 }
40
enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation)41 void GrGLSLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) {
42 SkASSERT(GrBlendEquationIsAdvanced(equation));
43
44 if (fProgramBuilder->shaderCaps()->mustEnableAdvBlendEqs()) {
45 this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature,
46 "GL_KHR_blend_equation_advanced");
47 this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier);
48 }
49 }
50
enableCustomOutput()51 void GrGLSLFragmentShaderBuilder::enableCustomOutput() {
52 if (!fCustomColorOutput) {
53 fCustomColorOutput = &fOutputs.emplace_back(DeclaredColorOutputName(), kHalf4_GrSLType,
54 GrShaderVar::TypeModifier::Out);
55 fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back());
56 }
57 }
58
enableSecondaryOutput()59 void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() {
60 SkASSERT(!fHasSecondaryOutput);
61 fHasSecondaryOutput = true;
62 const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
63 if (const char* extension = caps.secondaryOutputExtensionString()) {
64 this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension);
65 }
66
67 // If the primary output is declared, we must declare also the secondary output
68 // and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
69 // output. The condition also co-incides with the condition in which GLSL ES 2.0
70 // requires the built-in gl_SecondaryFragColorEXT, whereas 3.0 requires a custom output.
71 if (caps.mustDeclareFragmentShaderOutput()) {
72 fOutputs.emplace_back(DeclaredSecondaryColorOutputName(), kHalf4_GrSLType,
73 GrShaderVar::TypeModifier::Out);
74 fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back());
75 }
76 }
77
getPrimaryColorOutputName() const78 const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const {
79 return DeclaredColorOutputName();
80 }
81
primaryColorOutputIsInOut() const82 bool GrGLSLFragmentShaderBuilder::primaryColorOutputIsInOut() const {
83 return fCustomColorOutput &&
84 fCustomColorOutput->getTypeModifier() == GrShaderVar::TypeModifier::InOut;
85 }
86
getSecondaryColorOutputName() const87 const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const {
88 if (this->hasSecondaryOutput()) {
89 return (fProgramBuilder->shaderCaps()->mustDeclareFragmentShaderOutput())
90 ? DeclaredSecondaryColorOutputName()
91 : "sk_SecondaryFragColor";
92 }
93 return nullptr;
94 }
95
getSurfaceOrigin() const96 GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
97 return fProgramBuilder->origin();
98 }
99
onFinalize()100 void GrGLSLFragmentShaderBuilder::onFinalize() {
101 fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
102 }
103