//
// Copyright 2002 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.
//

#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_

#include <set>

#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/HashNames.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/Pragma.h"
#include "compiler/translator/tree_util/IntermTraverse.h"

namespace sh
{
class TCompiler;

class TOutputGLSLBase : public TIntermTraverser
{
  public:
    TOutputGLSLBase(TCompiler *compiler, TInfoSinkBase &objSink, ShCompileOptions compileOptions);

    ShShaderOutput getShaderOutput() const { return mOutput; }

    // Return the original name if hash function pointer is NULL;
    // otherwise return the hashed name. Has special handling for internal names and built-ins,
    // which are not hashed.
    ImmutableString hashName(const TSymbol *symbol);

  protected:
    TInfoSinkBase &objSink() { return mObjSink; }
    void writeFloat(TInfoSinkBase &out, float f);
    void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
    std::string getCommonLayoutQualifiers(TIntermSymbol *variable);
    std::string getMemoryQualifiers(const TType &type);
    virtual void writeLayoutQualifier(TIntermSymbol *variable);
    void writeFieldLayoutQualifier(const TField *field);
    void writeInvariantQualifier(const TType &type);
    void writePreciseQualifier(const TType &type);
    virtual void writeVariableType(const TType &type,
                                   const TSymbol *symbol,
                                   bool isFunctionArgument);
    virtual bool writeVariablePrecision(TPrecision precision) = 0;
    void writeFunctionParameters(const TFunction *func);
    const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion);
    void writeConstructorTriplet(Visit visit, const TType &type);
    ImmutableString getTypeName(const TType &type);

    void visitSymbol(TIntermSymbol *node) override;
    void visitConstantUnion(TIntermConstantUnion *node) override;
    bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
    bool visitBinary(Visit visit, TIntermBinary *node) override;
    bool visitUnary(Visit visit, TIntermUnary *node) override;
    bool visitTernary(Visit visit, TIntermTernary *node) override;
    bool visitIfElse(Visit visit, TIntermIfElse *node) override;
    bool visitSwitch(Visit visit, TIntermSwitch *node) override;
    bool visitCase(Visit visit, TIntermCase *node) override;
    void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
    bool visitBlock(Visit visit, TIntermBlock *node) override;
    bool visitGlobalQualifierDeclaration(Visit visit,
                                         TIntermGlobalQualifierDeclaration *node) override;
    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
    bool visitLoop(Visit visit, TIntermLoop *node) override;
    bool visitBranch(Visit visit, TIntermBranch *node) override;
    void visitPreprocessorDirective(TIntermPreprocessorDirective *node) override;

    void visitCodeBlock(TIntermBlock *node);

    ImmutableString hashFieldName(const TField *field);
    // Same as hashName(), but without hashing "main".
    ImmutableString hashFunctionNameIfNeeded(const TFunction *func);
    // Used to translate function names for differences between ESSL and GLSL
    virtual ImmutableString translateTextureFunction(const ImmutableString &name,
                                                     const ShCompileOptions &option)
    {
        return name;
    }

    void declareStruct(const TStructure *structure);
    void writeQualifier(TQualifier qualifier, const TType &type, const TSymbol *symbol);

    const char *mapQualifierToString(TQualifier qualifier);

    sh::GLenum getShaderType() const { return mShaderType; }
    bool isHighPrecisionSupported() const { return mHighPrecisionSupported; }
    const char *getIndentPrefix(int extraIndentDepth = 0);

  private:
    void declareInterfaceBlockLayout(const TType &type);
    void declareInterfaceBlock(const TType &type);

    void writeFunctionTriplet(Visit visit,
                              const ImmutableString &functionName,
                              bool useEmulatedFunction);

    TInfoSinkBase &mObjSink;
    bool mDeclaringVariable;

    // name hashing.
    ShHashFunction64 mHashFunction;
    NameMap &mNameMap;

    sh::GLenum mShaderType;
    const int mShaderVersion;
    ShShaderOutput mOutput;

    bool mHighPrecisionSupported;

    ShCompileOptions mCompileOptions;
};

void WritePragma(TInfoSinkBase &out, ShCompileOptions compileOptions, const TPragma &pragma);

void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out,
                                         sh::TLayoutPrimitiveType inputPrimitive,
                                         int invocations,
                                         sh::TLayoutPrimitiveType outputPrimitive,
                                         int maxVertices);

void WriteTessControlShaderLayoutQualifiers(TInfoSinkBase &out, int inputVertices);

void WriteTessEvaluationShaderLayoutQualifiers(TInfoSinkBase &out,
                                               sh::TLayoutTessEvaluationType inputPrimitive,
                                               sh::TLayoutTessEvaluationType inputVertexSpacing,
                                               sh::TLayoutTessEvaluationType inputOrdering,
                                               sh::TLayoutTessEvaluationType inputPoint);

bool NeedsToWriteLayoutQualifier(const TType &type);

void EmitEarlyFragmentTestsGLSL(const TCompiler &, TInfoSinkBase &sink);
void EmitWorkGroupSizeGLSL(const TCompiler &, TInfoSinkBase &sink);
void EmitMultiviewGLSL(const TCompiler &,
                       const ShCompileOptions &,
                       const TExtension,
                       const TBehavior,
                       TInfoSinkBase &sink);

}  // namespace sh

#endif  // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
