1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/GrShaderCaps.h"
9cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
10cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::addPassThroughAttribute(const GrShaderVar& vsVar,
13cb93a386Sopenharmony_ci                                                   const char* output,
14cb93a386Sopenharmony_ci                                                   Interpolation interpolation) {
15cb93a386Sopenharmony_ci    SkASSERT(vsVar.getType() != kVoid_GrSLType);
16cb93a386Sopenharmony_ci    GrGLSLVarying v(vsVar.getType());
17cb93a386Sopenharmony_ci    this->addVarying(vsVar.c_str(), &v, interpolation);
18cb93a386Sopenharmony_ci    fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), vsVar.c_str());
19cb93a386Sopenharmony_ci    fProgramBuilder->fFS.codeAppendf("%s = %s;", output, v.fsIn());
20cb93a386Sopenharmony_ci}
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_cistatic bool use_flat_interpolation(GrGLSLVaryingHandler::Interpolation interpolation,
23cb93a386Sopenharmony_ci                                   const GrShaderCaps& shaderCaps) {
24cb93a386Sopenharmony_ci    switch (interpolation) {
25cb93a386Sopenharmony_ci        using Interpolation = GrGLSLVaryingHandler::Interpolation;
26cb93a386Sopenharmony_ci        case Interpolation::kInterpolated:
27cb93a386Sopenharmony_ci            return false;
28cb93a386Sopenharmony_ci        case Interpolation::kCanBeFlat:
29cb93a386Sopenharmony_ci            SkASSERT(!shaderCaps.preferFlatInterpolation() ||
30cb93a386Sopenharmony_ci                     shaderCaps.flatInterpolationSupport());
31cb93a386Sopenharmony_ci            return shaderCaps.preferFlatInterpolation();
32cb93a386Sopenharmony_ci        case Interpolation::kMustBeFlat:
33cb93a386Sopenharmony_ci            SkASSERT(shaderCaps.flatInterpolationSupport());
34cb93a386Sopenharmony_ci            return true;
35cb93a386Sopenharmony_ci    }
36cb93a386Sopenharmony_ci    SK_ABORT("Invalid interpolation");
37cb93a386Sopenharmony_ci}
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::addVarying(const char* name, GrGLSLVarying* varying,
40cb93a386Sopenharmony_ci                                      Interpolation interpolation) {
41cb93a386Sopenharmony_ci    SkASSERT(GrSLTypeIsFloatType(varying->type()) || Interpolation::kMustBeFlat == interpolation);
42cb93a386Sopenharmony_ci    VaryingInfo& v = fVaryings.push_back();
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci    SkASSERT(varying);
45cb93a386Sopenharmony_ci    SkASSERT(kVoid_GrSLType != varying->fType);
46cb93a386Sopenharmony_ci    v.fType = varying->fType;
47cb93a386Sopenharmony_ci    v.fIsFlat = use_flat_interpolation(interpolation, *fProgramBuilder->shaderCaps());
48cb93a386Sopenharmony_ci    v.fVsOut = fProgramBuilder->nameVariable('v', name);
49cb93a386Sopenharmony_ci    v.fVisibility = kNone_GrShaderFlags;
50cb93a386Sopenharmony_ci    if (varying->isInVertexShader()) {
51cb93a386Sopenharmony_ci        varying->fVsOut = v.fVsOut.c_str();
52cb93a386Sopenharmony_ci        v.fVisibility |= kVertex_GrShaderFlag;
53cb93a386Sopenharmony_ci    }
54cb93a386Sopenharmony_ci    if (varying->isInFragmentShader()) {
55cb93a386Sopenharmony_ci        varying->fFsIn = v.fVsOut.c_str();
56cb93a386Sopenharmony_ci        v.fVisibility |= kFragment_GrShaderFlag;
57cb93a386Sopenharmony_ci    }
58cb93a386Sopenharmony_ci}
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) {
61cb93a386Sopenharmony_ci    for (const auto& attr : gp.vertexAttributes()) {
62cb93a386Sopenharmony_ci        this->addAttribute(attr.asShaderVar());
63cb93a386Sopenharmony_ci    }
64cb93a386Sopenharmony_ci    for (const auto& attr : gp.instanceAttributes()) {
65cb93a386Sopenharmony_ci        this->addAttribute(attr.asShaderVar());
66cb93a386Sopenharmony_ci    }
67cb93a386Sopenharmony_ci}
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::addAttribute(const GrShaderVar& var) {
70cb93a386Sopenharmony_ci    SkASSERT(GrShaderVar::TypeModifier::In == var.getTypeModifier());
71cb93a386Sopenharmony_ci    for (const GrShaderVar& attr : fVertexInputs.items()) {
72cb93a386Sopenharmony_ci        // if attribute already added, don't add it again
73cb93a386Sopenharmony_ci        if (attr.getName().equals(var.getName())) {
74cb93a386Sopenharmony_ci            return;
75cb93a386Sopenharmony_ci        }
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci    fVertexInputs.push_back(var);
78cb93a386Sopenharmony_ci}
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::setNoPerspective() {
81cb93a386Sopenharmony_ci    const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
82cb93a386Sopenharmony_ci    if (!caps.noperspectiveInterpolationSupport()) {
83cb93a386Sopenharmony_ci        return;
84cb93a386Sopenharmony_ci    }
85cb93a386Sopenharmony_ci    if (const char* extension = caps.noperspectiveInterpolationExtensionString()) {
86cb93a386Sopenharmony_ci        int bit = 1 << GrGLSLShaderBuilder::kNoPerspectiveInterpolation_GLSLPrivateFeature;
87cb93a386Sopenharmony_ci        fProgramBuilder->fVS.addFeature(bit, extension);
88cb93a386Sopenharmony_ci        fProgramBuilder->fFS.addFeature(bit, extension);
89cb93a386Sopenharmony_ci    }
90cb93a386Sopenharmony_ci    fDefaultInterpolationModifier = "noperspective";
91cb93a386Sopenharmony_ci}
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::finalize() {
94cb93a386Sopenharmony_ci    for (const VaryingInfo& v : fVaryings.items()) {
95cb93a386Sopenharmony_ci        const char* modifier = v.fIsFlat ? "flat" : fDefaultInterpolationModifier;
96cb93a386Sopenharmony_ci        if (v.fVisibility & kVertex_GrShaderFlag) {
97cb93a386Sopenharmony_ci            fVertexOutputs.emplace_back(v.fVsOut, v.fType, GrShaderVar::TypeModifier::Out,
98cb93a386Sopenharmony_ci                                        GrShaderVar::kNonArray, SkString(), SkString(modifier));
99cb93a386Sopenharmony_ci        }
100cb93a386Sopenharmony_ci        if (v.fVisibility & kFragment_GrShaderFlag) {
101cb93a386Sopenharmony_ci            const char* fsIn = v.fVsOut.c_str();
102cb93a386Sopenharmony_ci            fFragInputs.emplace_back(SkString(fsIn), v.fType, GrShaderVar::TypeModifier::In,
103cb93a386Sopenharmony_ci                                     GrShaderVar::kNonArray, SkString(), SkString(modifier));
104cb93a386Sopenharmony_ci        }
105cb93a386Sopenharmony_ci    }
106cb93a386Sopenharmony_ci    this->onFinalize();
107cb93a386Sopenharmony_ci}
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::appendDecls(const VarArray& vars, SkString* out) const {
110cb93a386Sopenharmony_ci    for (const GrShaderVar& varying : vars.items()) {
111cb93a386Sopenharmony_ci        varying.appendDecl(fProgramBuilder->shaderCaps(), out);
112cb93a386Sopenharmony_ci        out->append(";");
113cb93a386Sopenharmony_ci    }
114cb93a386Sopenharmony_ci}
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::getVertexDecls(SkString* inputDecls, SkString* outputDecls) const {
117cb93a386Sopenharmony_ci    this->appendDecls(fVertexInputs, inputDecls);
118cb93a386Sopenharmony_ci    this->appendDecls(fVertexOutputs, outputDecls);
119cb93a386Sopenharmony_ci}
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_civoid GrGLSLVaryingHandler::getFragDecls(SkString* inputDecls, SkString* outputDecls) const {
122cb93a386Sopenharmony_ci    // We should not have any outputs in the fragment shader when using version 1.10
123cb93a386Sopenharmony_ci    SkASSERT(k110_GrGLSLGeneration != fProgramBuilder->shaderCaps()->generation() ||
124cb93a386Sopenharmony_ci             fFragOutputs.empty());
125cb93a386Sopenharmony_ci    this->appendDecls(fFragInputs, inputDecls);
126cb93a386Sopenharmony_ci    this->appendDecls(fFragOutputs, outputDecls);
127cb93a386Sopenharmony_ci}
128