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

// Shader.h: Defines the abstract gl::Shader class and its concrete derived
// classes VertexShader and FragmentShader. Implements GL shader objects and
// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
// 3.8 page 84.

#ifndef LIBANGLE_SHADER_H_
#define LIBANGLE_SHADER_H_

#include <string>
#include <list>
#include <vector>

#include "angle_gl.h"
#include <GLSLANG/ShaderLang.h>

#include "common/angleutils.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/Debug.h"

namespace rx
{
class GLImplFactory;
class ShaderImpl;
class ShaderSh;
}

namespace gl
{
class Compiler;
class ContextState;
struct Limitations;
class ShaderProgramManager;
class Context;

class ShaderState final : angle::NonCopyable
{
  public:
    ShaderState(GLenum shaderType);
    ~ShaderState();

    const std::string &getLabel() const { return mLabel; }

    const std::string &getSource() const { return mSource; }
    const std::string &getTranslatedSource() const { return mTranslatedSource; }

    GLenum getShaderType() const { return mShaderType; }
    int getShaderVersion() const { return mShaderVersion; }

    const std::vector<sh::Varying> &getVaryings() const { return mVaryings; }
    const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
    const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; }
    const std::vector<sh::Attribute> &getActiveAttributes() const { return mActiveAttributes; }
    const std::vector<sh::OutputVariable> &getActiveOutputVariables() const
    {
        return mActiveOutputVariables;
    }

  private:
    friend class Shader;

    std::string mLabel;

    GLenum mShaderType;
    int mShaderVersion;
    std::string mTranslatedSource;
    std::string mSource;

    sh::WorkGroupSize mLocalSize;

    std::vector<sh::Varying> mVaryings;
    std::vector<sh::Uniform> mUniforms;
    std::vector<sh::InterfaceBlock> mInterfaceBlocks;
    std::vector<sh::Attribute> mActiveAttributes;
    std::vector<sh::OutputVariable> mActiveOutputVariables;
};

class Shader final : angle::NonCopyable, public LabeledObject
{
  public:
    Shader(ShaderProgramManager *manager,
           rx::GLImplFactory *implFactory,
           const gl::Limitations &rendererLimitations,
           GLenum type,
           GLuint handle);

    void destroy(const Context *context) {}
    virtual ~Shader();

    void setLabel(const std::string &label) override;
    const std::string &getLabel() const override;

    GLenum getType() const { return mType; }
    GLuint getHandle() const;

    rx::ShaderImpl *getImplementation() const { return mImplementation; }

    void deleteSource();
    void setSource(GLsizei count, const char *const *string, const GLint *length);
    int getInfoLogLength() const;
    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
    int getSourceLength() const;
    void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
    int getTranslatedSourceLength() const;
    int getTranslatedSourceWithDebugInfoLength() const;
    const std::string &getTranslatedSource() const { return mState.getTranslatedSource(); }
    void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
    void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const;

    void compile(const Context *context);
    bool isCompiled() const { return mCompiled; }

    void addRef();
    void release(const Context *context);
    unsigned int getRefCount() const;
    bool isFlaggedForDeletion() const;
    void flagForDeletion();

    int getShaderVersion() const;

    const std::vector<sh::Varying> &getVaryings() const;
    const std::vector<sh::Uniform> &getUniforms() const;
    const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
    const std::vector<sh::Attribute> &getActiveAttributes() const;
    const std::vector<sh::OutputVariable> &getActiveOutputVariables() const;

    int getSemanticIndex(const std::string &attributeName) const;

    const sh::WorkGroupSize &getWorkGroupSize() const { return mState.mLocalSize; }

  private:
    static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer);

    ShaderState mState;
    rx::ShaderImpl *mImplementation;
    const gl::Limitations &mRendererLimitations;
    const GLuint mHandle;
    const GLenum mType;
    unsigned int mRefCount;     // Number of program objects this shader is attached to
    bool mDeleteStatus;         // Flag to indicate that the shader can be deleted when no longer in use
    bool mCompiled;             // Indicates if this shader has been successfully compiled
    std::string mInfoLog;

    ShaderProgramManager *mResourceManager;
};

bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y);
}

#endif   // LIBANGLE_SHADER_H_
