//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "compiler/translator/TranslatorESSL.h"

#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/PrunePureLiteralStatements.h"
#include "compiler/translator/RecordConstantPrecision.h"
#include "compiler/translator/OutputESSL.h"
#include "angle_gl.h"

namespace sh
{

TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
    : TCompiler(type, spec, SH_ESSL_OUTPUT)
{
}

void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
                                                 ShCompileOptions compileOptions)
{
    if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
    {
        InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
    }
}

void TranslatorESSL::translate(TIntermBlock *root, ShCompileOptions compileOptions)
{
    // The ESSL output doesn't define a default precision for float, so float literal statements
    // end up with no precision which is invalid ESSL.
    PrunePureLiteralStatements(root);

    TInfoSinkBase &sink = getInfoSink().obj;

    int shaderVer = getShaderVersion();
    if (shaderVer > 100)
    {
        sink << "#version " << shaderVer << " es\n";
    }

    // Write built-in extension behaviors.
    writeExtensionBehavior(compileOptions);

    // Write pragmas after extensions because some drivers consider pragmas
    // like non-preprocessor tokens.
    writePragma(compileOptions);

    bool precisionEmulation =
        getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;

    if (precisionEmulation)
    {
        EmulatePrecision emulatePrecision(getSymbolTable(), shaderVer);
        root->traverse(&emulatePrecision);
        emulatePrecision.updateTree();
        emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
    }

    RecordConstantPrecision(root, getTemporaryIndex());

    // Write emulated built-in functions if needed.
    if (!getBuiltInFunctionEmulator().isOutputEmpty())
    {
        sink << "// BEGIN: Generated code for built-in function emulation\n\n";
        if (getShaderType() == GL_FRAGMENT_SHADER)
        {
            sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
                 << "#define webgl_emu_precision highp\n"
                 << "#else\n"
                 << "#define webgl_emu_precision mediump\n"
                 << "#endif\n\n";
        }
        else
        {
            sink << "#define webgl_emu_precision highp\n";
        }

        getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
        sink << "// END: Generated code for built-in function emulation\n\n";
    }

    // Write array bounds clamping emulation if needed.
    getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);

    if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
    {
        const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
        sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
             << ", local_size_z=" << localSize[2] << ") in;\n";
    }

    // Write translated shader.
    TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
                           getSymbolTable(), getShaderType(), shaderVer, precisionEmulation,
                           compileOptions);

    if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
    {
        TName uniformName(TString("ViewID_OVR"));
        uniformName.setInternal(true);
        sink << "highp uniform int " << outputESSL.hashName(uniformName) << ";\n";
    }

    root->traverse(&outputESSL);
}

bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll()
{
    // Not necessary when translating to ESSL.
    return false;
}

void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
{
    TInfoSinkBase &sink                   = getInfoSink().obj;
    const TExtensionBehavior &extBehavior = getExtensionBehavior();
    for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end();
         ++iter)
    {
        if (iter->second != EBhUndefined)
        {
            if (getResources().NV_shader_framebuffer_fetch &&
                iter->first == "GL_EXT_shader_framebuffer_fetch")
            {
                sink << "#extension GL_NV_shader_framebuffer_fetch : "
                     << getBehaviorString(iter->second) << "\n";
            }
            else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers")
            {
                sink << "#extension GL_NV_draw_buffers : " << getBehaviorString(iter->second)
                     << "\n";
            }
            else if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM &&
                     (iter->first == "GL_OVR_multiview" || iter->first == "GL_OVR_multiview2"))
            {
                // No output
                continue;
            }
            else
            {
                sink << "#extension " << iter->first << " : " << getBehaviorString(iter->second)
                     << "\n";
            }
        }
    }
}

}  // namespace sh
