/*
 * 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 "gl/GrGLProgram.h"
#include "gl/GrGLSLPrettyPrint.h"
#include "gl/GrGLUniformHandle.h"
#include "GrCoordTransform.h"
#include "GrDrawEffect.h"
#include "../GrGpuGL.h"
#include "GrGLFragmentShaderBuilder.h"
#include "GrGLProgramBuilder.h"
#include "GrTexture.h"
#include "GrGLVertexShaderBuilder.h"
#include "SkRTConf.h"
#include "SkTraceEvent.h"

namespace {
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)

// number of each input/output type in a single allocation block
static const int kVarsPerBlock = 8;

// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

bool GrGLProgramBuilder::genProgram(const GrEffectStage* geometryProcessor,
                                    const GrEffectStage* colorStages[],
                                    const GrEffectStage* coverageStages[]) {
    const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();

    fFS.emitCodeBeforeEffects();

    ///////////////////////////////////////////////////////////////////////////
    // get the initial color and coverage to feed into the first effect in each effect chain

    GrGLSLExpr4 inputColor;
    GrGLSLExpr4 inputCoverage;

    if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
        const char* name;
        fUniformHandles.fColorUni =
            this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                             kVec4f_GrSLType,
                             "Color",
                             &name);
        inputColor = GrGLSLExpr4(name);
    } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
        inputColor = GrGLSLExpr4(1);
    }

    if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
        const char* name;
        fUniformHandles.fCoverageUni =
            this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                             kVec4f_GrSLType,
                             "Coverage",
                             &name);
        inputCoverage = GrGLSLExpr4(name);
    } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
        inputCoverage = GrGLSLExpr4(1);
    }

    this->emitCodeBeforeEffects(&inputColor, &inputCoverage);

    ///////////////////////////////////////////////////////////////////////////
    // emit the per-effect code for both color and coverage effects

    GrGLProgramDesc::EffectKeyProvider colorKeyProvider(
        &this->desc(), GrGLProgramDesc::EffectKeyProvider::kColor_EffectType);
    fColorEffects.reset(this->createAndEmitEffects(colorStages,
                                                   this->desc().numColorEffects(),
                                                   colorKeyProvider,
                                                   &inputColor));

    this->emitGeometryProcessor(geometryProcessor, &inputCoverage);

    GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
        &this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
    fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
                                                      this->desc().numCoverageEffects(),
                                                      coverageKeyProvider,
                                                      &inputCoverage));

    this->emitCodeAfterEffects();

    fFS.emitCodeAfterEffects(inputColor, inputCoverage);

    if (!this->finish()) {
        return false;
    }

    return true;
}

//////////////////////////////////////////////////////////////////////////////

GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
                                       const GrGLProgramDesc& desc)
    : fFragOnly(!desc.getHeader().fRequiresVertexShader &&
                gpu->glCaps().pathRenderingSupport() &&
                gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode)
    , fTexCoordSetCnt(0)
    , fProgramID(0)
    , fFS(this, desc)
    , fSeparableVaryingInfos(kVarsPerBlock)
    , fDesc(desc)
    , fGpu(gpu)
    , fUniforms(kVarsPerBlock) {
}

void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
    if ('\0' == prefix) {
        *out = name;
    } else {
        out->printf("%c%s", prefix, name);
    }
    if (fCodeStage.inStageCode()) {
        if (out->endsWith('_')) {
            // Names containing "__" are reserved.
            out->append("x");
        }
        out->appendf("_Stage%d", fCodeStage.stageIndex());
    }
}

GrGLProgramDataManager::UniformHandle GrGLProgramBuilder::addUniformArray(uint32_t visibility,
                                                                          GrSLType type,
                                                                          const char* name,
                                                                          int count,
                                                                          const char** outName) {
    SkASSERT(name && strlen(name));
    SkDEBUGCODE(static const uint32_t kVisibilityMask = kVertex_Visibility | kFragment_Visibility);
    SkASSERT(0 == (~kVisibilityMask & visibility));
    SkASSERT(0 != visibility);

    UniformInfo& uni = fUniforms.push_back();
    uni.fVariable.setType(type);
    uni.fVariable.setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
    this->nameVariable(uni.fVariable.accessName(), 'u', name);
    uni.fVariable.setArrayCount(count);
    uni.fVisibility = visibility;

    // If it is visible in both the VS and FS, the precision must match.
    // We declare a default FS precision, but not a default VS. So set the var
    // to use the default FS precision.
    if ((kVertex_Visibility | kFragment_Visibility) == visibility) {
        // the fragment and vertex precisions must match
        uni.fVariable.setPrecision(kDefaultFragmentPrecision);
    }

    if (NULL != outName) {
        *outName = uni.fVariable.c_str();
    }
    return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
}

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

void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
                                            SkString* out) const {
    for (int i = 0; i < fUniforms.count(); ++i) {
        if (fUniforms[i].fVisibility & visibility) {
            fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
            out->append(";\n");
        }
    }
}

void GrGLProgramBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programEffectsBuilder,
                                              const GrEffectStage* effectStages[],
                                              int effectCnt,
                                              const GrGLProgramDesc::EffectKeyProvider& keyProvider,
                                              GrGLSLExpr4* fsInOutColor) {
    bool effectEmitted = false;

    GrGLSLExpr4 inColor = *fsInOutColor;
    GrGLSLExpr4 outColor;

    for (int e = 0; e < effectCnt; ++e) {
        SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
        const GrEffectStage& stage = *effectStages[e];

        CodeStage::AutoStageRestore csar(&fCodeStage, &stage);

        if (inColor.isZeros()) {
            SkString inColorName;

            // Effects have no way to communicate zeros, they treat an empty string as ones.
            this->nameVariable(&inColorName, '\0', "input");
            fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str());
            inColor = inColorName;
        }

        // create var to hold stage result
        SkString outColorName;
        this->nameVariable(&outColorName, '\0', "output");
        fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
        outColor = outColorName;


        programEffectsBuilder->emitEffect(stage,
                                          keyProvider.get(e),
                                          outColor.c_str(),
                                          inColor.isOnes() ? NULL : inColor.c_str(),
                                          fCodeStage.stageIndex());

        inColor = outColor;
        effectEmitted = true;
    }

    if (effectEmitted) {
        *fsInOutColor = outColor;
    }
}

bool GrGLProgramBuilder::finish() {
    SkASSERT(0 == fProgramID);
    GL_CALL_RET(fProgramID, CreateProgram());
    if (!fProgramID) {
        return false;
    }

    SkTDArray<GrGLuint> shadersToDelete;

    if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
        GL_CALL(DeleteProgram(fProgramID));
        return false;
    }

    this->bindProgramLocations(fProgramID);

    GL_CALL(LinkProgram(fProgramID));

    // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
    bool checkLinked = !fGpu->ctxInfo().isChromium();
#ifdef SK_DEBUG
    checkLinked = true;
#endif
    if (checkLinked) {
        GrGLint linked = GR_GL_INIT_ZERO;
        GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
        if (!linked) {
            GrGLint infoLen = GR_GL_INIT_ZERO;
            GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
            SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
            if (infoLen > 0) {
                // retrieve length even though we don't need it to workaround
                // bug in chrome cmd buffer param validation.
                GrGLsizei length = GR_GL_INIT_ZERO;
                GL_CALL(GetProgramInfoLog(fProgramID,
                                          infoLen+1,
                                          &length,
                                          (char*)log.get()));
                GrPrintf((char*)log.get());
            }
            SkDEBUGFAIL("Error linking program");
            GL_CALL(DeleteProgram(fProgramID));
            fProgramID = 0;
            return false;
        }
    }

    this->resolveProgramLocations(fProgramID);

    for (int i = 0; i < shadersToDelete.count(); ++i) {
      GL_CALL(DeleteShader(shadersToDelete[i]));
    }

    return true;
}

bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId,
                                                 SkTDArray<GrGLuint>* shaderIds) const {
    return fFS.compileAndAttachShaders(programId, shaderIds);
}

void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
    fFS.bindProgramLocations(programId);

    // skbug.com/2056
    bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
    if (usingBindUniform) {
        int count = fUniforms.count();
        for (int i = 0; i < count; ++i) {
            GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str()));
            fUniforms[i].fLocation = i;
        }
    }
}

void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
    bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
    if (!usingBindUniform) {
        int count = fUniforms.count();
        for (int i = 0; i < count; ++i) {
            GrGLint location;
            GL_CALL_RET(location,
                        GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
            fUniforms[i].fLocation = location;
        }
    }

    int count = fSeparableVaryingInfos.count();
    for (int i = 0; i < count; ++i) {
        GrGLint location;
        GL_CALL_RET(location,
                    GetProgramResourceLocation(programId,
                                               GR_GL_FRAGMENT_INPUT,
                                               fSeparableVaryingInfos[i].fVariable.c_str()));
        fSeparableVaryingInfos[i].fLocation = location;
    }
}

const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
    return fGpu->ctxInfo();
}

////////////////////////////////////////////////////////////////////////////////

GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
                                              const GrGLProgramDesc& desc)
    : INHERITED(gpu, desc)
    , fGS(this)
    , fVS(this) {
}

void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color,
                                                   GrGLSLExpr4* coverage) {
    fVS.emitCodeBeforeEffects(color, coverage);
}

void GrGLFullProgramBuilder::emitGeometryProcessor(const GrEffectStage* geometryProcessor,
                                                   GrGLSLExpr4* coverage) {
    if (NULL != geometryProcessor) {
        GrGLProgramDesc::EffectKeyProvider geometryProcessorKeyProvider(
                &this->desc(), GrGLProgramDesc::EffectKeyProvider::kGeometryProcessor_EffectType);
        fGeometryProcessor.reset(this->createAndEmitEffect(
                                 geometryProcessor,
                                 geometryProcessorKeyProvider,
                                 coverage));
    }
}

void GrGLFullProgramBuilder::emitCodeAfterEffects() {
    fVS.emitCodeAfterEffects();
}

void GrGLFullProgramBuilder::addVarying(GrSLType type,
                                        const char* name,
                                        const char** vsOutName,
                                        const char** fsInName,
                                        GrGLShaderVar::Precision fsPrecision) {
    fVS.addVarying(type, name, vsOutName);

    SkString* fsInputName = fVS.fOutputs.back().accessName();

#if GR_GL_EXPERIMENTAL_GS
    if (desc().getHeader().fExperimentalGS) {
       // TODO let the caller use these names
       fGS.addVarying(type, fsInputName->c_str(), NULL);
       fsInputName = fGS.fOutputs.back().accessName();
    }
#endif
    fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
}

GrGLFullProgramBuilder::VaryingHandle
GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
                                            const char* name,
                                            const char** vsOutName,
                                            const char** fsInName) {
    addVarying(type, name, vsOutName, fsInName);
    SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
    varying.fVariable = fFS.fInputs.back();
    return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
}


GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
        const GrEffectStage* effectStages[],
        int effectCnt,
        const GrGLProgramDesc::EffectKeyProvider& keyProvider,
        GrGLSLExpr4* inOutFSColor) {

    GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
    this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
                                          effectStages,
                                          effectCnt,
                                          keyProvider,
                                          inOutFSColor);
    return programEffectsBuilder.finish();
}

void GrGLFullProgramBuilder::createAndEmitEffect(GrGLProgramEffectsBuilder* programEffectsBuilder,
                                              const GrEffectStage* effectStages,
                                              const GrGLProgramDesc::EffectKeyProvider& keyProvider,
                                              GrGLSLExpr4* fsInOutColor) {
    GrGLSLExpr4 inColor = *fsInOutColor;
    GrGLSLExpr4 outColor;

    SkASSERT(NULL != effectStages && NULL != effectStages->getEffect());
    const GrEffectStage& stage = *effectStages;

    // Using scope to force ASR destructor to be triggered
    {
        CodeStage::AutoStageRestore csar(&fCodeStage, &stage);

        if (inColor.isZeros()) {
            SkString inColorName;

            // Effects have no way to communicate zeros, they treat an empty string as ones.
            this->nameVariable(&inColorName, '\0', "input");
            fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
            inColor = inColorName;
        }

        // create var to hold stage result
        SkString outColorName;
        this->nameVariable(&outColorName, '\0', "output");
        fFS.codeAppendf("vec4 %s;", outColorName.c_str());
        outColor = outColorName;


        programEffectsBuilder->emitEffect(stage,
                                          keyProvider.get(0),
                                          outColor.c_str(),
                                          inColor.isOnes() ? NULL : inColor.c_str(),
                                          fCodeStage.stageIndex());
    }

    *fsInOutColor = outColor;
}

GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffect(
        const GrEffectStage* geometryProcessor,
        const GrGLProgramDesc::EffectKeyProvider& keyProvider,
        GrGLSLExpr4* inOutFSColor) {

    GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, 1);
    this->createAndEmitEffect(&programEffectsBuilder, geometryProcessor, keyProvider, inOutFSColor);
    return programEffectsBuilder.finish();
}

bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
                                                     SkTDArray<GrGLuint>* shaderIds) const {
    return INHERITED::compileAndAttachShaders(programId, shaderIds)
         && fVS.compileAndAttachShaders(programId, shaderIds)
#if GR_GL_EXPERIMENTAL_GS
         && (!desc().getHeader().fExperimentalGS
                 || fGS.compileAndAttachShaders(programId, shaderIds))
#endif
         ;
}

void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
    fVS.bindProgramLocations(programId);
    INHERITED::bindProgramLocations(programId);
}

////////////////////////////////////////////////////////////////////////////////

GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
                                                               const GrGLProgramDesc& desc)
    : INHERITED(gpu, desc) {
    SkASSERT(!desc.getHeader().fRequiresVertexShader);
    SkASSERT(gpu->glCaps().pathRenderingSupport());
    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
}

int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
    int firstFreeCoordSet = fTexCoordSetCnt;
    fTexCoordSetCnt += count;
    SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
    return firstFreeCoordSet;
}

GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(
        const GrEffectStage* effectStages[], int effectCnt,
        const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {

    GrGLPathTexGenProgramEffectsBuilder pathTexGenEffectsBuilder(this,
                                                                 effectCnt);
    this->INHERITED::createAndEmitEffects(&pathTexGenEffectsBuilder,
                                          effectStages,
                                          effectCnt,
                                          keyProvider,
                                          inOutFSColor);
    return pathTexGenEffectsBuilder.finish();
}
