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 "GrGLSLFragmentShaderBuilder.h"
9#include "GrRenderTarget.h"
10#include "GrRenderTargetPriv.h"
11#include "GrShaderCaps.h"
12#include "gl/GrGLGpu.h"
13#include "glsl/GrGLSLProgramBuilder.h"
14#include "glsl/GrGLSLUniformHandler.h"
15#include "glsl/GrGLSLVarying.h"
16#include "../private/GrGLSL.h"
17
18const char* GrGLSLFragmentShaderBuilder::kDstColorName = "_dstColor";
19
20static const char* sample_offset_array_name(GrGLSLFPFragmentBuilder::Coordinates coords) {
21    static const char* kArrayNames[] = {
22        "deviceSpaceSampleOffsets",
23        "windowSpaceSampleOffsets"
24    };
25    return kArrayNames[coords];
26
27    GR_STATIC_ASSERT(0 == GrGLSLFPFragmentBuilder::kSkiaDevice_Coordinates);
28    GR_STATIC_ASSERT(1 == GrGLSLFPFragmentBuilder::kGLSLWindow_Coordinates);
29    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kArrayNames) == GrGLSLFPFragmentBuilder::kLast_Coordinates + 1);
30}
31
32static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
33    SkASSERT(GrBlendEquationIsAdvanced(equation));
34
35    static const char* kLayoutQualifierNames[] = {
36        "blend_support_screen",
37        "blend_support_overlay",
38        "blend_support_darken",
39        "blend_support_lighten",
40        "blend_support_colordodge",
41        "blend_support_colorburn",
42        "blend_support_hardlight",
43        "blend_support_softlight",
44        "blend_support_difference",
45        "blend_support_exclusion",
46        "blend_support_multiply",
47        "blend_support_hsl_hue",
48        "blend_support_hsl_saturation",
49        "blend_support_hsl_color",
50        "blend_support_hsl_luminosity"
51    };
52    return kLayoutQualifierNames[equation - kFirstAdvancedGrBlendEquation];
53
54    GR_STATIC_ASSERT(0 == kScreen_GrBlendEquation - kFirstAdvancedGrBlendEquation);
55    GR_STATIC_ASSERT(1 == kOverlay_GrBlendEquation - kFirstAdvancedGrBlendEquation);
56    GR_STATIC_ASSERT(2 == kDarken_GrBlendEquation - kFirstAdvancedGrBlendEquation);
57    GR_STATIC_ASSERT(3 == kLighten_GrBlendEquation - kFirstAdvancedGrBlendEquation);
58    GR_STATIC_ASSERT(4 == kColorDodge_GrBlendEquation - kFirstAdvancedGrBlendEquation);
59    GR_STATIC_ASSERT(5 == kColorBurn_GrBlendEquation - kFirstAdvancedGrBlendEquation);
60    GR_STATIC_ASSERT(6 == kHardLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
61    GR_STATIC_ASSERT(7 == kSoftLight_GrBlendEquation - kFirstAdvancedGrBlendEquation);
62    GR_STATIC_ASSERT(8 == kDifference_GrBlendEquation - kFirstAdvancedGrBlendEquation);
63    GR_STATIC_ASSERT(9 == kExclusion_GrBlendEquation - kFirstAdvancedGrBlendEquation);
64    GR_STATIC_ASSERT(10 == kMultiply_GrBlendEquation - kFirstAdvancedGrBlendEquation);
65    GR_STATIC_ASSERT(11 == kHSLHue_GrBlendEquation - kFirstAdvancedGrBlendEquation);
66    GR_STATIC_ASSERT(12 == kHSLSaturation_GrBlendEquation - kFirstAdvancedGrBlendEquation);
67    GR_STATIC_ASSERT(13 == kHSLColor_GrBlendEquation - kFirstAdvancedGrBlendEquation);
68    GR_STATIC_ASSERT(14 == kHSLLuminosity_GrBlendEquation - kFirstAdvancedGrBlendEquation);
69    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kLayoutQualifierNames) ==
70                     kGrBlendEquationCnt - kFirstAdvancedGrBlendEquation);
71}
72
73uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin) {
74    SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin);
75    return origin + 1;
76
77    GR_STATIC_ASSERT(0 == kTopLeft_GrSurfaceOrigin);
78    GR_STATIC_ASSERT(1 == kBottomLeft_GrSurfaceOrigin);
79}
80
81GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program)
82    : GrGLSLFragmentBuilder(program)
83    , fSetupFragPosition(false)
84    , fHasCustomColorOutput(false)
85    , fCustomColorOutputIndex(-1)
86    , fHasSecondaryOutput(false)
87    , fUsedSampleOffsetArrays(0)
88    , fHasInitializedSampleMask(false)
89    , fForceHighPrecision(false) {
90    fSubstageIndices.push_back(0);
91#ifdef SK_DEBUG
92    fUsedProcessorFeatures = GrProcessor::kNone_RequiredFeatures;
93    fHasReadDstColor = false;
94#endif
95}
96
97bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
98    const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
99    switch (feature) {
100        case kMultisampleInterpolation_GLSLFeature:
101            if (!shaderCaps.multisampleInterpolationSupport()) {
102                return false;
103            }
104            if (const char* extension = shaderCaps.multisampleInterpolationExtensionString()) {
105                this->addFeature(1 << kMultisampleInterpolation_GLSLFeature, extension);
106            }
107            return true;
108        default:
109            SK_ABORT("Unexpected GLSLFeature requested.");
110            return false;
111    }
112}
113
114SkString GrGLSLFragmentShaderBuilder::ensureCoords2D(const GrShaderVar& coords) {
115    if (kFloat3_GrSLType != coords.getType() && kHalf3_GrSLType != coords.getType()) {
116        SkASSERT(kFloat2_GrSLType == coords.getType() || kHalf2_GrSLType == coords.getType());
117        return coords.getName();
118    }
119
120    SkString coords2D;
121    coords2D.printf("%s_ensure2D", coords.c_str());
122    this->codeAppendf("\tfloat2 %s = %s.xy / %s.z;", coords2D.c_str(), coords.c_str(),
123                      coords.c_str());
124    return coords2D;
125}
126
127void GrGLSLFragmentShaderBuilder::appendOffsetToSample(const char* sampleIdx, Coordinates coords) {
128    SkASSERT(fProgramBuilder->header().fSamplePatternKey);
129    SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kSampleLocations_RequiredFeature);
130    if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
131        // With a top left origin, device and window space are equal, so we only use device coords.
132        coords = kSkiaDevice_Coordinates;
133    }
134    this->codeAppendf("%s[%s]", sample_offset_array_name(coords), sampleIdx);
135    fUsedSampleOffsetArrays |= (1 << coords);
136}
137
138void GrGLSLFragmentShaderBuilder::maskSampleCoverage(const char* mask, bool invert) {
139    const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
140    if (!shaderCaps.sampleVariablesSupport()) {
141        SkDEBUGFAIL("Attempted to mask sample coverage without support.");
142        return;
143    }
144    if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
145        this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
146    }
147    if (!fHasInitializedSampleMask) {
148        this->codePrependf("gl_SampleMask[0] = -1;");
149        fHasInitializedSampleMask = true;
150    }
151    if (invert) {
152        this->codeAppendf("gl_SampleMask[0] &= ~(%s);", mask);
153    } else {
154        this->codeAppendf("gl_SampleMask[0] &= %s;", mask);
155    }
156}
157
158void GrGLSLFragmentShaderBuilder::overrideSampleCoverage(const char* mask) {
159    const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
160    if (!shaderCaps.sampleMaskOverrideCoverageSupport()) {
161        SkDEBUGFAIL("Attempted to override sample coverage without support.");
162        return;
163    }
164    SkASSERT(shaderCaps.sampleVariablesSupport());
165    if (const char* extension = shaderCaps.sampleVariablesExtensionString()) {
166        this->addFeature(1 << kSampleVariables_GLSLPrivateFeature, extension);
167    }
168    if (this->addFeature(1 << kSampleMaskOverrideCoverage_GLSLPrivateFeature,
169                         "GL_NV_sample_mask_override_coverage")) {
170        // Redeclare gl_SampleMask with layout(override_coverage) if we haven't already.
171        fOutputs.push_back().set(kInt_GrSLType, "gl_SampleMask", 1, GrShaderVar::kOut_TypeModifier,
172                                 kHigh_GrSLPrecision, "override_coverage");
173    }
174    this->codeAppendf("gl_SampleMask[0] = %s;", mask);
175    fHasInitializedSampleMask = true;
176}
177
178const char* GrGLSLFragmentShaderBuilder::dstColor() {
179    SkDEBUGCODE(fHasReadDstColor = true;)
180
181    const char* override = fProgramBuilder->primitiveProcessor().getDestColorOverride();
182    if (override != nullptr) {
183        return override;
184    }
185
186    const GrShaderCaps* shaderCaps = fProgramBuilder->shaderCaps();
187    if (shaderCaps->fbFetchSupport()) {
188        this->addFeature(1 << kFramebufferFetch_GLSLPrivateFeature,
189                         shaderCaps->fbFetchExtensionString());
190
191        // Some versions of this extension string require declaring custom color output on ES 3.0+
192        const char* fbFetchColorName = shaderCaps->fbFetchColorName();
193        if (shaderCaps->fbFetchNeedsCustomOutput()) {
194            this->enableCustomOutput();
195            fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
196            fbFetchColorName = DeclaredColorOutputName();
197            // Set the dstColor to an intermediate variable so we don't override it with the output
198            this->codeAppendf("half4 %s = %s;", kDstColorName, fbFetchColorName);
199        } else {
200            return fbFetchColorName;
201        }
202    }
203    return kDstColorName;
204}
205
206void GrGLSLFragmentShaderBuilder::enableAdvancedBlendEquationIfNeeded(GrBlendEquation equation) {
207    SkASSERT(GrBlendEquationIsAdvanced(equation));
208
209    const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
210    if (!caps.mustEnableAdvBlendEqs()) {
211        return;
212    }
213
214    this->addFeature(1 << kBlendEquationAdvanced_GLSLPrivateFeature,
215                     "GL_KHR_blend_equation_advanced");
216    if (caps.mustEnableSpecificAdvBlendEqs()) {
217        this->addLayoutQualifier(specific_layout_qualifier_name(equation), kOut_InterfaceQualifier);
218    } else {
219        this->addLayoutQualifier("blend_support_all_equations", kOut_InterfaceQualifier);
220    }
221}
222
223void GrGLSLFragmentShaderBuilder::enableCustomOutput() {
224    if (!fHasCustomColorOutput) {
225        fHasCustomColorOutput = true;
226        fCustomColorOutputIndex = fOutputs.count();
227        fOutputs.push_back().set(kHalf4_GrSLType, DeclaredColorOutputName(),
228                                 GrShaderVar::kOut_TypeModifier);
229        fProgramBuilder->finalizeFragmentOutputColor(fOutputs.back());
230    }
231}
232
233void GrGLSLFragmentShaderBuilder::enableSecondaryOutput() {
234    SkASSERT(!fHasSecondaryOutput);
235    fHasSecondaryOutput = true;
236    const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
237    if (const char* extension = caps.secondaryOutputExtensionString()) {
238        this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension);
239    }
240
241    // If the primary output is declared, we must declare also the secondary output
242    // and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
243    // output. The condition also co-incides with the condition in whici GLES SL 2.0
244    // requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
245    if (caps.mustDeclareFragmentShaderOutput()) {
246        fOutputs.push_back().set(kHalf4_GrSLType, DeclaredSecondaryColorOutputName(),
247                                 GrShaderVar::kOut_TypeModifier);
248        fProgramBuilder->finalizeFragmentSecondaryColor(fOutputs.back());
249    }
250}
251
252const char* GrGLSLFragmentShaderBuilder::getPrimaryColorOutputName() const {
253    return fHasCustomColorOutput ? DeclaredColorOutputName() : "sk_FragColor";
254}
255
256bool GrGLSLFragmentShaderBuilder::primaryColorOutputIsInOut() const {
257    return fHasCustomColorOutput &&
258           fOutputs[fCustomColorOutputIndex].getTypeModifier() == GrShaderVar::kInOut_TypeModifier;
259}
260
261void GrGLSLFragmentBuilder::declAppendf(const char* fmt, ...) {
262    va_list argp;
263    va_start(argp, fmt);
264    inputs().appendVAList(fmt, argp);
265    va_end(argp);
266}
267
268const char* GrGLSLFragmentShaderBuilder::getSecondaryColorOutputName() const {
269    const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
270    return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutputName()
271                                                  : "gl_SecondaryFragColorEXT";
272}
273
274GrSurfaceOrigin GrGLSLFragmentShaderBuilder::getSurfaceOrigin() const {
275    SkASSERT(fProgramBuilder->header().fSurfaceOriginKey);
276    return static_cast<GrSurfaceOrigin>(fProgramBuilder->header().fSurfaceOriginKey-1);
277
278    GR_STATIC_ASSERT(0 == kTopLeft_GrSurfaceOrigin);
279    GR_STATIC_ASSERT(1 == kBottomLeft_GrSurfaceOrigin);
280}
281
282void GrGLSLFragmentShaderBuilder::onFinalize() {
283    fProgramBuilder->varyingHandler()->getFragDecls(&this->inputs(), &this->outputs());
284    if (fUsedSampleOffsetArrays & (1 << kSkiaDevice_Coordinates)) {
285        this->defineSampleOffsetArray(sample_offset_array_name(kSkiaDevice_Coordinates),
286                                      SkMatrix::MakeTrans(-0.5f, -0.5f));
287    }
288    if (fUsedSampleOffsetArrays & (1 << kGLSLWindow_Coordinates)) {
289        // With a top left origin, device and window space are equal, so we only use device coords.
290        SkASSERT(kBottomLeft_GrSurfaceOrigin == this->getSurfaceOrigin());
291        SkMatrix m;
292        m.setScale(1, -1);
293        m.preTranslate(-0.5f, -0.5f);
294        this->defineSampleOffsetArray(sample_offset_array_name(kGLSLWindow_Coordinates), m);
295    }
296}
297
298void GrGLSLFragmentShaderBuilder::defineSampleOffsetArray(const char* name, const SkMatrix& m) {
299    SkASSERT(fProgramBuilder->caps()->sampleLocationsSupport());
300    const GrPipeline& pipeline = fProgramBuilder->pipeline();
301    const GrRenderTargetPriv& rtp = pipeline.renderTarget()->renderTargetPriv();
302    const GrGpu::MultisampleSpecs& specs = rtp.getMultisampleSpecs(pipeline);
303    SkSTArray<16, SkPoint, true> offsets;
304    offsets.push_back_n(specs.fEffectiveSampleCnt);
305    m.mapPoints(offsets.begin(), specs.fSampleLocations, specs.fEffectiveSampleCnt);
306    this->definitions().appendf("const float2 %s[] = float2[](", name);
307    for (int i = 0; i < specs.fEffectiveSampleCnt; ++i) {
308        this->definitions().appendf("float2(%f, %f)", offsets[i].x(), offsets[i].y());
309        this->definitions().append(i + 1 != specs.fEffectiveSampleCnt ? ", " : ");\n");
310    }
311}
312
313void GrGLSLFragmentShaderBuilder::onBeforeChildProcEmitCode() {
314    SkASSERT(fSubstageIndices.count() >= 1);
315    fSubstageIndices.push_back(0);
316    // second-to-last value in the fSubstageIndices stack is the index of the child proc
317    // at that level which is currently emitting code.
318    fMangleString.appendf("_c%d", fSubstageIndices[fSubstageIndices.count() - 2]);
319}
320
321void GrGLSLFragmentShaderBuilder::onAfterChildProcEmitCode() {
322    SkASSERT(fSubstageIndices.count() >= 2);
323    fSubstageIndices.pop_back();
324    fSubstageIndices.back()++;
325    int removeAt = fMangleString.findLastOf('_');
326    fMangleString.remove(removeAt, fMangleString.size() - removeAt);
327}
328