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

#include "GrGLFragmentShaderBuilder.h"
#include "GrGLShaderStringBuilder.h"
#include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h"

namespace {
#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
static const char kDstCopyColorName[] = "_dstColor";
inline const char* declared_color_output_name() { return "fsColorOut"; }
inline const char* dual_source_output_name() { return "dualSourceOut"; }
inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
                                               GrGLStandard standard,
                                               SkString* str) {
    // Desktop GLSL has added precision qualifiers but they don't do anything.
    if (kGLES_GrGLStandard == standard) {
        switch (p) {
            case GrGLShaderVar::kHigh_Precision:
                str->append("precision highp float;\n");
                break;
            case GrGLShaderVar::kMedium_Precision:
                str->append("precision mediump float;\n");
                break;
            case GrGLShaderVar::kLow_Precision:
                str->append("precision lowp float;\n");
                break;
            case GrGLShaderVar::kDefault_Precision:
                SkFAIL("Default precision now allowed.");
            default:
                SkFAIL("Unknown precision value.");
        }
    }
}
}

GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
        const GrTexture* dstCopy, const GrGLCaps& caps) {
    uint32_t key = kYesDstRead_DstReadKeyBit;
    if (caps.fbFetchSupport()) {
        return key;
    }
    SkASSERT(NULL != dstCopy);
    if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(dstCopy->config())) {
        // The fact that the config is alpha-only must be considered when generating code.
        key |= kUseAlphaConfig_DstReadKeyBit;
    }
    if (kTopLeft_GrSurfaceOrigin == dstCopy->origin()) {
        key |= kTopLeftOrigin_DstReadKeyBit;
    }
    SkASSERT(static_cast<DstReadKey>(key) == key);
    return static_cast<DstReadKey>(key);
}

GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition(
        const GrRenderTarget* dst, const GrGLCaps&) {
    if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
        return kTopLeftFragPosRead_FragPosKey;
    } else {
        return kBottomLeftFragPosRead_FragPosKey;
    }
}

GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program,
                                                     const GrGLProgramDesc& desc)
    : INHERITED(program)
    , fHasCustomColorOutput(false)
    , fHasSecondaryOutput(false)
    , fSetupFragPosition(false)
    , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){
}

const char* GrGLFragmentShaderBuilder::dstColor() {
    if (fProgramBuilder->fCodeStage.inStageCode()) {
        const GrEffect* effect = fProgramBuilder->fCodeStage.effectStage()->getEffect();
        if (!effect->willReadDstColor()) {
            SkDEBUGFAIL("GrGLEffect asked for dst color but its generating GrEffect "
                        "did not request access.");
            return "";
        }
    }

    GrGpuGL* gpu = fProgramBuilder->gpu();
    if (gpu->glCaps().fbFetchSupport()) {
        this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
                         gpu->glCaps().fbFetchExtensionString());
        return gpu->glCaps().fbFetchColorName();
    } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
        return kDstCopyColorName;
    } else {
        return "";
    }
}

bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
    switch (feature) {
        case kStandardDerivatives_GLSLFeature: {
            GrGpuGL* gpu = fProgramBuilder->gpu();
            if (!gpu->glCaps().shaderDerivativeSupport()) {
                return false;
            }
            if (kGLES_GrGLStandard == gpu->glStandard()) {
                this->addFeature(1 << kStandardDerivatives_GLSLFeature,
                                 "GL_OES_standard_derivatives");
            }
            return true;
        }
        default:
            SkFAIL("Unexpected GLSLFeature requested.");
            return false;
    }
}

SkString GrGLFragmentShaderBuilder::ensureFSCoords2D(const TransformedCoordsArray& coords, int index) {
    if (kVec3f_GrSLType != coords[index].type()) {
        SkASSERT(kVec2f_GrSLType == coords[index].type());
        return coords[index].getName();
    }

    SkString coords2D("coords2D");
    if (0 != index) {
        coords2D.appendf("_%i", index);
    }
    this->codeAppendf("\tvec2 %s = %s.xy / %s.z;",
                      coords2D.c_str(), coords[index].c_str(), coords[index].c_str());
    return coords2D;
}

const char* GrGLFragmentShaderBuilder::fragmentPosition() {
    GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage;
    if (cs->inStageCode()) {
        const GrEffect* effect = cs->effectStage()->getEffect();
        if (!effect->willReadFragmentPosition()) {
            SkDEBUGFAIL("GrGLEffect asked for frag position but its generating GrEffect "
                        "did not request access.");
            return "";
        }
    }

    GrGpuGL* gpu = fProgramBuilder->gpu();
    // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
    // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
    // declaration varies in earlier GLSL specs. So it is simpler to omit it.
    if (fTopLeftFragPosRead) {
        fSetupFragPosition = true;
        return "gl_FragCoord";
    } else if (gpu->glCaps().fragCoordConventionsSupport()) {
        if (!fSetupFragPosition) {
            if (gpu->glslGeneration() < k150_GrGLSLGeneration) {
                this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
                                 "GL_ARB_fragment_coord_conventions");
            }
            fInputs.push_back().set(kVec4f_GrSLType,
                                    GrGLShaderVar::kIn_TypeModifier,
                                    "gl_FragCoord",
                                    GrGLShaderVar::kDefault_Precision,
                                    GrGLShaderVar::kUpperLeft_Origin);
            fSetupFragPosition = true;
        }
        return "gl_FragCoord";
    } else {
        static const char* kCoordName = "fragCoordYDown";
        if (!fSetupFragPosition) {
            // temporarily change the stage index because we're inserting non-stage code.
            GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);

            SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
            const char* rtHeightName;

            fProgramBuilder->fUniformHandles.fRTHeightUni =
                    fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                         kFloat_GrSLType,
                                         "RTHeight",
                                         &rtHeightName);

            // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that
            // causes programs to fail to link. Making this function return a vec2() didn't fix the
            // problem but using 1.0 for the last two components does.
            this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, "
                               "1.0);\n", kCoordName, rtHeightName);
            fSetupFragPosition = true;
        }
        SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
        return kCoordName;
    }
}

void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
               const char* name,
               const char** fsInName) {
    fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name);
    if (fsInName) {
        *fsInName = name;
    }
}

void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
    GrGpuGL* gpu = fProgramBuilder->gpu();
    if (fHasCustomColorOutput) {
        GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
    }
    if (fHasSecondaryOutput) {
        GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
    }
}

bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
                                                        SkTDArray<GrGLuint>* shaderIds) const {
    GrGpuGL* gpu = fProgramBuilder->gpu();
    SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo()));
    fragShaderSrc.append(fExtensions);
    append_default_precision_qualifier(kDefaultFragmentPrecision,
                                       gpu->glStandard(),
                                       &fragShaderSrc);
    fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
    fProgramBuilder->appendDecls(fInputs, &fragShaderSrc);
    // We shouldn't have declared outputs on 1.10
    SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
    fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc);
    fragShaderSrc.append(fFunctions);
    fragShaderSrc.append("void main() {\n");
    fragShaderSrc.append(fCode);
    fragShaderSrc.append("}\n");

    GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(),
            programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc);
    if (!fragShaderId) {
        return false;
    }

    *shaderIds->append() = fragShaderId;

    return true;
}

void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
    const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
    GrGpuGL* gpu = fProgramBuilder->gpu();

    ///////////////////////////////////////////////////////////////////////////
    // emit code to read the dst copy texture, if necessary
    if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) {
        bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
        const char* dstCopyTopLeftName;
        const char* dstCopyCoordScaleName;
        const char* dstCopySamplerName;
        uint32_t configMask;
        if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
            configMask = kA_GrColorComponentFlag;
        } else {
            configMask = kRGBA_GrColorComponentFlags;
        }
        fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                 kSampler2D_GrSLType,
                                 "DstCopySampler",
                                 &dstCopySamplerName);
        fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                 kVec2f_GrSLType,
                                 "DstCopyUpperLeft",
                                 &dstCopyTopLeftName);
        fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
            fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                 kVec2f_GrSLType,
                                 "DstCopyCoordScale",
                                 &dstCopyCoordScaleName);
        const char* fragPos = fragmentPosition();

        this->codeAppend("// Read color from copy of the destination.\n");
        this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
                          fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
        if (!topDown) {
            this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
        }
        this->codeAppendf("vec4 %s = ", kDstCopyColorName);
        this->appendTextureLookup(dstCopySamplerName,
                                  "_dstTexCoord",
                                  configMask,
                                  "rgba");
        this->codeAppend(";");
    }

    if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
        fOutputs.push_back().set(kVec4f_GrSLType,
                                 GrGLShaderVar::kOut_TypeModifier,
                                 declared_color_output_name());
        fHasCustomColorOutput = true;
    }
}

void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) {
    const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();

    ///////////////////////////////////////////////////////////////////////////
    // write the secondary color output if necessary
    if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
        const char* secondaryOutputName = this->enableSecondaryOutput();

        // default coeff to ones for kCoverage_DualSrcOutput
        GrGLSLExpr4 coeff(1);
        if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
            // Get (1-A) into coeff
            coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
        } else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput ==
                   header.fCoverageOutput){
            // Get (1-RGBA) into coeff
            coeff = GrGLSLExpr4(1) - inputColor;
        }
        // Get coeff * coverage into modulate and then write that to the dual source output.
        codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
    }

    ///////////////////////////////////////////////////////////////////////////
    // combine color and coverage as frag color

    // Get "color * coverage" into fragColor
    GrGLSLExpr4 fragColor = inputColor * inputCoverage;
    // Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
    if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
        GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;

        GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());

        fragColor = fragColor + dstContribution;
    }
    codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
}

const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() {
    if (!fHasSecondaryOutput) {
        fOutputs.push_back().set(kVec4f_GrSLType,
                                 GrGLShaderVar::kOut_TypeModifier,
                                 dual_source_output_name());
        fHasSecondaryOutput = true;
    }
    return dual_source_output_name();
}

const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
    return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
}

