/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrShaderCaps.h"
#include "glsl/GrGLSLVarying.h"
#include "glsl/GrGLSLProgramBuilder.h"

void GrGLSLVaryingHandler::addPassThroughAttribute(const GrGeometryProcessor::Attribute* input,
                                                   const char* output, GrSLPrecision precision) {
    GrSLType type = GrVertexAttribTypeToSLType(input->fType);
    GrGLSLVertToFrag v(type);
    this->addVarying(input->fName, &v, precision);
    this->writePassThroughAttribute(input, output, v);
}

void GrGLSLVaryingHandler::addFlatPassThroughAttribute(const GrGeometryProcessor::Attribute* input,
                                                       const char* output,
                                                       GrSLPrecision precision) {
    GrSLType type = GrVertexAttribTypeToSLType(input->fType);
    GrGLSLVertToFrag v(type);
    this->addFlatVarying(input->fName, &v, precision);
    this->writePassThroughAttribute(input, output, v);
}

void GrGLSLVaryingHandler::writePassThroughAttribute(const GrGeometryProcessor::Attribute* input,
                                                     const char* output, const GrGLSLVarying& v) {
    SkASSERT(!fProgramBuilder->primitiveProcessor().willUseGeoShader());
    fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
    fProgramBuilder->fFS.codeAppendf("%s = %s;", output, v.fsIn());
}

void GrGLSLVaryingHandler::internalAddVarying(const char* name,
                                              GrGLSLVarying* varying,
                                              GrSLPrecision precision,
                                              bool flat) {
    bool willUseGeoShader = fProgramBuilder->primitiveProcessor().willUseGeoShader();
    VaryingInfo& v = fVaryings.push_back();

    SkASSERT(varying);
    v.fType = varying->fType;
    v.fPrecision = precision;
    v.fIsFlat = flat;
    fProgramBuilder->nameVariable(&v.fVsOut, 'v', name);
    v.fVisibility = kNone_GrShaderFlags;
    if (varying->vsVarying()) {
        varying->fVsOut = v.fVsOut.c_str();
        v.fVisibility |= kVertex_GrShaderFlag;
    }
    if (willUseGeoShader) {
        fProgramBuilder->nameVariable(&v.fGsOut, 'g', name);
        varying->fGsIn = v.fVsOut.c_str();
        varying->fGsOut = v.fGsOut.c_str();
        v.fVisibility |= kGeometry_GrShaderFlag;
    }
    if (varying->fsVarying()) {
        varying->fFsIn = (willUseGeoShader ? v.fGsOut : v.fVsOut).c_str();
        v.fVisibility |= kFragment_GrShaderFlag;
    }
}

void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) {
    int vaCount = gp.numAttribs();
    for (int i = 0; i < vaCount; i++) {
        const GrGeometryProcessor::Attribute& attr = gp.getAttrib(i);
        this->addAttribute(GrShaderVar(attr.fName,
                                       GrVertexAttribTypeToSLType(attr.fType),
                                       GrShaderVar::kIn_TypeModifier,
                                       GrShaderVar::kNonArray,
                                       attr.fPrecision));
    }
}

void GrGLSLVaryingHandler::addAttribute(const GrShaderVar& var) {
    SkASSERT(GrShaderVar::kIn_TypeModifier == var.getTypeModifier());
    for (int j = 0; j < fVertexInputs.count(); ++j) {
        const GrShaderVar& attr = fVertexInputs[j];
        // if attribute already added, don't add it again
        if (attr.getName().equals(var.getName())) {
            return;
        }
    }
    fVertexInputs.push_back(var);
}

void GrGLSLVaryingHandler::setNoPerspective() {
    const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
    if (!caps.noperspectiveInterpolationSupport()) {
        return;
    }
    if (const char* extension = caps.noperspectiveInterpolationExtensionString()) {
        int bit = 1 << GrGLSLFragmentBuilder::kNoPerspectiveInterpolation_GLSLPrivateFeature;
        fProgramBuilder->fVS.addFeature(bit, extension);
        if (fProgramBuilder->primitiveProcessor().willUseGeoShader()) {
            fProgramBuilder->fGS.addFeature(bit, extension);
        }
        fProgramBuilder->fFS.addFeature(bit, extension);
    }
    fDefaultInterpolationModifier = "noperspective";
}

void GrGLSLVaryingHandler::finalize() {
    for (int i = 0; i < fVaryings.count(); ++i) {
        const VaryingInfo& v = this->fVaryings[i];
        const char* modifier = v.fIsFlat ? "flat" : fDefaultInterpolationModifier;
        if (v.fVisibility & kVertex_GrShaderFlag) {
            fVertexOutputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kOut_TypeModifier,
                                           v.fPrecision, nullptr, modifier);
            if (v.fVisibility & kGeometry_GrShaderFlag) {
                fGeomInputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kUnsizedArray,
                                            GrShaderVar::kIn_TypeModifier, v.fPrecision, nullptr,
                                            modifier);
            }
        }
        if (v.fVisibility & kFragment_GrShaderFlag) {
            const char* fsIn = v.fVsOut.c_str();
            if (v.fVisibility & kGeometry_GrShaderFlag) {
                fGeomOutputs.push_back().set(v.fType, v.fGsOut, GrShaderVar::kOut_TypeModifier,
                                             v.fPrecision, nullptr, modifier);
                fsIn = v.fGsOut.c_str();
            }
            fFragInputs.push_back().set(v.fType, fsIn, GrShaderVar::kIn_TypeModifier, v.fPrecision,
                                        nullptr, modifier);
        }
    }
    this->onFinalize();
}

void GrGLSLVaryingHandler::appendDecls(const VarArray& vars, SkString* out) const {
    for (int i = 0; i < vars.count(); ++i) {
        vars[i].appendDecl(fProgramBuilder->shaderCaps(), out);
        out->append(";");
    }
}

void GrGLSLVaryingHandler::getVertexDecls(SkString* inputDecls, SkString* outputDecls) const {
    this->appendDecls(fVertexInputs, inputDecls);
    this->appendDecls(fVertexOutputs, outputDecls);
}

void GrGLSLVaryingHandler::getGeomDecls(SkString* inputDecls, SkString* outputDecls) const {
    this->appendDecls(fGeomInputs, inputDecls);
    this->appendDecls(fGeomOutputs, outputDecls);
}

void GrGLSLVaryingHandler::getFragDecls(SkString* inputDecls, SkString* outputDecls) const {
    // We should not have any outputs in the fragment shader when using version 1.10
    SkASSERT(k110_GrGLSLGeneration != fProgramBuilder->shaderCaps()->generation() ||
             fFragOutputs.empty());
    this->appendDecls(fFragInputs, inputDecls);
    this->appendDecls(fFragOutputs, outputDecls);
}
