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

// Compiler.cpp: implements the gl::Compiler class.

#include "libANGLE/Compiler.h"

#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/State.h"
#include "libANGLE/renderer/CompilerImpl.h"
#include "libANGLE/renderer/GLImplFactory.h"

namespace gl
{

namespace
{

// To know when to call sh::Initialize and sh::Finalize.
size_t gActiveCompilers = 0;

ShShaderSpec SelectShaderSpec(GLint majorVersion,
                              GLint minorVersion,
                              bool isWebGL,
                              EGLenum clientType)
{
    // For Desktop GL
    if (clientType == EGL_OPENGL_API)
    {
        return SH_GL_COMPATIBILITY_SPEC;
    }

    if (majorVersion >= 3)
    {
        switch (minorVersion)
        {
            case 2:
                ASSERT(!isWebGL);
                return SH_GLES3_2_SPEC;
            case 1:
                return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC;
            case 0:
                return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC;
            default:
                UNREACHABLE();
        }
    }

    // GLES1 emulation: Use GLES3 shader spec.
    if (!isWebGL && majorVersion == 1)
    {
        return SH_GLES3_SPEC;
    }

    return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
}

}  // anonymous namespace

Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Display *display)
    : mImplementation(implFactory->createCompiler()),
      mSpec(SelectShaderSpec(state.getClientMajorVersion(),
                             state.getClientMinorVersion(),
                             state.isWebGL(),
                             state.getClientType())),
      mOutputType(mImplementation->getTranslatorOutputType()),
      mResources()
{
    // TODO(http://anglebug.com/3819): Update for GL version specific validation
    ASSERT(state.getClientMajorVersion() == 1 || state.getClientMajorVersion() == 2 ||
           state.getClientMajorVersion() == 3 || state.getClientMajorVersion() == 4);

    const gl::Caps &caps             = state.getCaps();
    const gl::Extensions &extensions = state.getExtensions();

    {
        std::lock_guard<std::mutex> lock(display->getDisplayGlobalMutex());
        if (gActiveCompilers == 0)
        {
            sh::Initialize();
        }
        ++gActiveCompilers;
    }

    sh::InitBuiltInResources(&mResources);
    mResources.MaxVertexAttribs             = caps.maxVertexAttributes;
    mResources.MaxVertexUniformVectors      = caps.maxVertexUniformVectors;
    mResources.MaxVaryingVectors            = caps.maxVaryingVectors;
    mResources.MaxVertexTextureImageUnits   = caps.maxShaderTextureImageUnits[ShaderType::Vertex];
    mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
    mResources.MaxTextureImageUnits         = caps.maxShaderTextureImageUnits[ShaderType::Fragment];
    mResources.MaxFragmentUniformVectors    = caps.maxFragmentUniformVectors;
    mResources.MaxDrawBuffers               = caps.maxDrawBuffers;
    mResources.OES_standard_derivatives     = extensions.standardDerivativesOES;
    mResources.EXT_draw_buffers             = extensions.drawBuffersEXT;
    mResources.EXT_shader_texture_lod       = extensions.shaderTextureLodEXT;
    mResources.EXT_shader_non_constant_global_initializers =
        extensions.shaderNonConstantGlobalInitializersEXT;
    mResources.OES_EGL_image_external          = extensions.EGLImageExternalOES;
    mResources.OES_EGL_image_external_essl3    = extensions.EGLImageExternalEssl3OES;
    mResources.NV_EGL_stream_consumer_external = extensions.EGLStreamConsumerExternalNV;
    mResources.NV_shader_noperspective_interpolation =
        extensions.shaderNoperspectiveInterpolationNV;
    mResources.ARB_texture_rectangle = extensions.textureRectangleANGLE;
    mResources.EXT_gpu_shader5       = extensions.gpuShader5EXT;
    mResources.OES_shader_io_blocks  = extensions.shaderIoBlocksOES;
    mResources.EXT_shader_io_blocks  = extensions.shaderIoBlocksEXT;
    mResources.OES_texture_storage_multisample_2d_array =
        extensions.textureStorageMultisample2dArrayOES;
    mResources.OES_texture_3D            = extensions.texture3DOES;
    mResources.ANGLE_texture_multisample = extensions.textureMultisampleANGLE;
    mResources.ANGLE_multi_draw          = extensions.multiDrawANGLE;
    mResources.ANGLE_base_vertex_base_instance_shader_builtin =
        extensions.baseVertexBaseInstanceShaderBuiltinANGLE;
    mResources.APPLE_clip_distance = extensions.clipDistanceAPPLE;
    // OES_shader_multisample_interpolation
    mResources.OES_shader_multisample_interpolation = extensions.shaderMultisampleInterpolationOES;
    mResources.OES_shader_image_atomic              = extensions.shaderImageAtomicOES;
    // TODO: use shader precision caps to determine if high precision is supported?
    mResources.FragmentPrecisionHigh = 1;
    mResources.EXT_frag_depth        = extensions.fragDepthEXT;

    // OVR_multiview state
    mResources.OVR_multiview = extensions.multiviewOVR;

    // OVR_multiview2 state
    mResources.OVR_multiview2 = extensions.multiview2OVR;
    mResources.MaxViewsOVR    = caps.maxViews;

    // EXT_multisampled_render_to_texture and EXT_multisampled_render_to_texture2
    mResources.EXT_multisampled_render_to_texture  = extensions.multisampledRenderToTextureEXT;
    mResources.EXT_multisampled_render_to_texture2 = extensions.multisampledRenderToTexture2EXT;

    // WEBGL_video_texture
    mResources.WEBGL_video_texture = extensions.videoTextureWEBGL;

    // OES_texture_cube_map_array
    mResources.OES_texture_cube_map_array = extensions.textureCubeMapArrayOES;
    mResources.EXT_texture_cube_map_array = extensions.textureCubeMapArrayEXT;

    // EXT_shadow_samplers
    mResources.EXT_shadow_samplers = extensions.shadowSamplersEXT;

    // OES_texture_buffer
    mResources.OES_texture_buffer = extensions.textureBufferOES;
    mResources.EXT_texture_buffer = extensions.textureBufferEXT;

    // GL_EXT_YUV_target
    mResources.EXT_YUV_target = extensions.YUVTargetEXT;

    mResources.EXT_shader_framebuffer_fetch_non_coherent =
        extensions.shaderFramebufferFetchNonCoherentEXT;

    // GL_EXT_clip_cull_distance
    mResources.EXT_clip_cull_distance = extensions.clipCullDistanceEXT;

    // GL_EXT_primitive_bounding_box
    mResources.EXT_primitive_bounding_box = extensions.primitiveBoundingBoxEXT;

    // GLSL ES 3.0 constants
    mResources.MaxVertexOutputVectors  = caps.maxVertexOutputComponents / 4;
    mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
    mResources.MinProgramTexelOffset   = caps.minProgramTexelOffset;
    mResources.MaxProgramTexelOffset   = caps.maxProgramTexelOffset;

    // EXT_blend_func_extended
    mResources.EXT_blend_func_extended  = extensions.blendFuncExtendedEXT;
    mResources.MaxDualSourceDrawBuffers = caps.maxDualSourceDrawBuffers;

    // APPLE_clip_distance/EXT_clip_cull_distance
    mResources.MaxClipDistances                = caps.maxClipDistances;
    mResources.MaxCullDistances                = caps.maxCullDistances;
    mResources.MaxCombinedClipAndCullDistances = caps.maxCombinedClipAndCullDistances;

    // OES_sample_variables
    mResources.OES_sample_variables = extensions.sampleVariablesOES;
    mResources.MaxSamples           = caps.maxSamples;

    // GLSL ES 3.1 constants
    mResources.MaxProgramTextureGatherOffset    = caps.maxProgramTextureGatherOffset;
    mResources.MinProgramTextureGatherOffset    = caps.minProgramTextureGatherOffset;
    mResources.MaxImageUnits                    = caps.maxImageUnits;
    mResources.MaxVertexImageUniforms           = caps.maxShaderImageUniforms[ShaderType::Vertex];
    mResources.MaxFragmentImageUniforms         = caps.maxShaderImageUniforms[ShaderType::Fragment];
    mResources.MaxComputeImageUniforms          = caps.maxShaderImageUniforms[ShaderType::Compute];
    mResources.MaxCombinedImageUniforms         = caps.maxCombinedImageUniforms;
    mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
    mResources.MaxUniformLocations              = caps.maxUniformLocations;

    for (size_t index = 0u; index < 3u; ++index)
    {
        mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
        mResources.MaxComputeWorkGroupSize[index]  = caps.maxComputeWorkGroupSize[index];
    }

    mResources.MaxComputeUniformComponents = caps.maxShaderUniformComponents[ShaderType::Compute];
    mResources.MaxComputeTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Compute];

    mResources.MaxComputeAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Compute];
    mResources.MaxComputeAtomicCounterBuffers =
        caps.maxShaderAtomicCounterBuffers[ShaderType::Compute];

    mResources.MaxVertexAtomicCounters   = caps.maxShaderAtomicCounters[ShaderType::Vertex];
    mResources.MaxFragmentAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Fragment];
    mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters;
    mResources.MaxAtomicCounterBindings  = caps.maxAtomicCounterBufferBindings;
    mResources.MaxVertexAtomicCounterBuffers =
        caps.maxShaderAtomicCounterBuffers[ShaderType::Vertex];
    mResources.MaxFragmentAtomicCounterBuffers =
        caps.maxShaderAtomicCounterBuffers[ShaderType::Fragment];
    mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
    mResources.MaxAtomicCounterBufferSize      = caps.maxAtomicCounterBufferSize;

    mResources.MaxUniformBufferBindings       = caps.maxUniformBufferBindings;
    mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings;

    // Needed by point size clamping workaround
    mResources.MaxPointSize = caps.maxAliasedPointSize;

    if (state.getClientMajorVersion() == 2 && !extensions.drawBuffersEXT)
    {
        mResources.MaxDrawBuffers = 1;
    }

    // Geometry Shader constants
    mResources.EXT_geometry_shader          = extensions.geometryShaderEXT;
    mResources.OES_geometry_shader          = extensions.geometryShaderOES;
    mResources.MaxGeometryUniformComponents = caps.maxShaderUniformComponents[ShaderType::Geometry];
    mResources.MaxGeometryUniformBlocks     = caps.maxShaderUniformBlocks[ShaderType::Geometry];
    mResources.MaxGeometryInputComponents   = caps.maxGeometryInputComponents;
    mResources.MaxGeometryOutputComponents  = caps.maxGeometryOutputComponents;
    mResources.MaxGeometryOutputVertices    = caps.maxGeometryOutputVertices;
    mResources.MaxGeometryTotalOutputComponents = caps.maxGeometryTotalOutputComponents;
    mResources.MaxGeometryTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Geometry];

    mResources.MaxGeometryAtomicCounterBuffers =
        caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry];
    mResources.MaxGeometryAtomicCounters      = caps.maxShaderAtomicCounters[ShaderType::Geometry];
    mResources.MaxGeometryShaderStorageBlocks = caps.maxShaderStorageBlocks[ShaderType::Geometry];
    mResources.MaxGeometryShaderInvocations   = caps.maxGeometryShaderInvocations;
    mResources.MaxGeometryImageUniforms       = caps.maxShaderImageUniforms[ShaderType::Geometry];

    // Tessellation Shader constants
    mResources.EXT_tessellation_shader        = extensions.tessellationShaderEXT;
    mResources.MaxTessControlInputComponents  = caps.maxTessControlInputComponents;
    mResources.MaxTessControlOutputComponents = caps.maxTessControlOutputComponents;
    mResources.MaxTessControlTextureImageUnits =
        caps.maxShaderTextureImageUnits[ShaderType::TessControl];
    mResources.MaxTessControlUniformComponents =
        caps.maxShaderUniformComponents[ShaderType::TessControl];
    mResources.MaxTessControlTotalOutputComponents = caps.maxTessControlTotalOutputComponents;
    mResources.MaxTessControlImageUniforms  = caps.maxShaderImageUniforms[ShaderType::TessControl];
    mResources.MaxTessControlAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::TessControl];
    mResources.MaxTessControlAtomicCounterBuffers =
        caps.maxShaderAtomicCounterBuffers[ShaderType::TessControl];

    mResources.MaxTessPatchComponents = caps.maxTessPatchComponents;
    mResources.MaxPatchVertices       = caps.maxPatchVertices;
    mResources.MaxTessGenLevel        = caps.maxTessGenLevel;

    mResources.MaxTessEvaluationInputComponents  = caps.maxTessEvaluationInputComponents;
    mResources.MaxTessEvaluationOutputComponents = caps.maxTessEvaluationOutputComponents;
    mResources.MaxTessEvaluationTextureImageUnits =
        caps.maxShaderTextureImageUnits[ShaderType::TessEvaluation];
    mResources.MaxTessEvaluationUniformComponents =
        caps.maxShaderUniformComponents[ShaderType::TessEvaluation];
    mResources.MaxTessEvaluationImageUniforms =
        caps.maxShaderImageUniforms[ShaderType::TessEvaluation];
    mResources.MaxTessEvaluationAtomicCounters =
        caps.maxShaderAtomicCounters[ShaderType::TessEvaluation];
    mResources.MaxTessEvaluationAtomicCounterBuffers =
        caps.maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation];

    // Subpixel bits.
    mResources.SubPixelBits = static_cast<int>(caps.subPixelBits);

    // Direct-to-metal constants:
    mResources.DriverUniformsBindingIndex    = caps.driverUniformsBindingIndex;
    mResources.DefaultUniformsBindingIndex   = caps.defaultUniformsBindingIndex;
    mResources.UBOArgumentBufferBindingIndex = caps.UBOArgumentBufferBindingIndex;
}

Compiler::~Compiler() = default;

void Compiler::onDestroy(const Context *context)
{
    std::lock_guard<std::mutex> lock(context->getDisplay()->getDisplayGlobalMutex());
    for (auto &pool : mPools)
    {
        for (ShCompilerInstance &instance : pool)
        {
            instance.destroy();
        }
    }
    --gActiveCompilers;
    if (gActiveCompilers == 0)
    {
        sh::Finalize();
    }
}

ShCompilerInstance Compiler::getInstance(ShaderType type)
{
    ASSERT(type != ShaderType::InvalidEnum);
    auto &pool = mPools[type];
    if (pool.empty())
    {
        ShHandle handle = sh::ConstructCompiler(ToGLenum(type), mSpec, mOutputType, &mResources);
        ASSERT(handle);
        return ShCompilerInstance(handle, mOutputType, type);
    }
    else
    {
        ShCompilerInstance instance = std::move(pool.back());
        pool.pop_back();
        return instance;
    }
}

void Compiler::putInstance(ShCompilerInstance &&instance)
{
    static constexpr size_t kMaxPoolSize = 32;
    auto &pool                           = mPools[instance.getShaderType()];
    if (pool.size() < kMaxPoolSize)
    {
        pool.push_back(std::move(instance));
    }
    else
    {
        instance.destroy();
    }
}

ShCompilerInstance::ShCompilerInstance() : mHandle(nullptr) {}

ShCompilerInstance::ShCompilerInstance(ShHandle handle,
                                       ShShaderOutput outputType,
                                       ShaderType shaderType)
    : mHandle(handle), mOutputType(outputType), mShaderType(shaderType)
{}

ShCompilerInstance::~ShCompilerInstance()
{
    ASSERT(mHandle == nullptr);
}

void ShCompilerInstance::destroy()
{
    if (mHandle != nullptr)
    {
        sh::Destruct(mHandle);
        mHandle = nullptr;
    }
}

ShCompilerInstance::ShCompilerInstance(ShCompilerInstance &&other)
    : mHandle(other.mHandle), mOutputType(other.mOutputType), mShaderType(other.mShaderType)
{
    other.mHandle = nullptr;
}

ShCompilerInstance &ShCompilerInstance::operator=(ShCompilerInstance &&other)
{
    mHandle       = other.mHandle;
    mOutputType   = other.mOutputType;
    mShaderType   = other.mShaderType;
    other.mHandle = nullptr;
    return *this;
}

ShHandle ShCompilerInstance::getHandle()
{
    return mHandle;
}

ShaderType ShCompilerInstance::getShaderType() const
{
    return mShaderType;
}

const std::string &ShCompilerInstance::getBuiltinResourcesString()
{
    return sh::GetBuiltInResourcesString(mHandle);
}

ShShaderOutput ShCompilerInstance::getShaderOutputType() const
{
    return mOutputType;
}

}  // namespace gl
