//
// Copyright 2017 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.
//
// MemoryProgramCache: Stores compiled and linked programs in memory so they don't
//   always have to be re-compiled. Can be used in conjunction with the platform
//   layer to warm up the cache from disk.

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_libc_calls
#endif

// Include zlib first, otherwise FAR gets defined elsewhere.
#define USE_SYSTEM_ZLIB
#include "compression_utils_portable.h"

#include "libANGLE/MemoryProgramCache.h"

#include <GLSLANG/ShaderVars.h>
#include <anglebase/sha1.h>

#include "common/BinaryStream.h"
#include "common/angle_version_info.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Uniform.h"
#include "libANGLE/capture/FrameCapture.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/renderer/ProgramImpl.h"
#include "platform/PlatformMethods.h"

namespace gl
{

namespace
{

// Limit decompressed programs to 10MB. If they're larger then this there is a good chance the data
// is not what we expect. This limits the amount of memory we will allocate based on a binary blob
// we believe is compressed data.
static constexpr size_t kMaxUncompressedProgramSize = 10 * 1024 * 1024;

void AppendProgramBindings(angle::BlobCacheHasher &hasher, const ProgramBindings &bindings)
{
    for (const auto &binding : bindings.getStableIterationMap())
    {
        hasher.Update(binding.first.data(), binding.first.size());
        angle::UpdateHashWithValue(hasher, binding.second);
    }
}

void AppendProgramAliasedBindings(angle::BlobCacheHasher &hasher,
                                  const ProgramAliasedBindings &bindings)
{
    for (const auto &binding : bindings.getStableIterationMap())
    {
        hasher.Update(binding.first.data(), binding.first.size());
        angle::UpdateHashWithValue(hasher, binding.second.location);
    }
}

}  // anonymous namespace

MemoryProgramCache::MemoryProgramCache(egl::BlobCache &blobCache) : mBlobCache(blobCache) {}

MemoryProgramCache::~MemoryProgramCache() {}

void MemoryProgramCache::ComputeHash(const Context *context,
                                     const Program *program,
                                     egl::BlobCache::Key *hashOut)
{
    // Compute the program hash.
    angle::BlobCacheHasher hasher;
    hasher.Init();

    // Start with the shader hashes.
    ShaderBitSet shaders;
    for (ShaderType shaderType : AllShaderTypes())
    {
        Shader *shader = program->getAttachedShader(shaderType);
        if (shader)
        {
            shaders.set(shaderType);
            hasher.Update(&shader->getShaderHash(), sizeof(egl::BlobCache::Key));
        }
    }
    angle::UpdateHashWithValue(hasher, shaders.bits());

    // Add some ANGLE metadata and Context properties, such as version and back-end.
    hasher.Update(angle::GetANGLEShaderProgramVersion(),
                  angle::GetANGLEShaderProgramVersionHashSize());
    angle::UpdateHashWithValue(hasher, angle::GetANGLESHVersion());
    angle::UpdateHashWithValue(hasher, context->getClientVersion().getMajor());
    angle::UpdateHashWithValue(hasher, context->getClientVersion().getMinor());
    const char *rendererString = reinterpret_cast<const char *>(context->getString(GL_RENDERER));
    ASSERT(rendererString != nullptr);
    hasher.Update(rendererString, strlen(rendererString));

    // Hash pre-link program properties.
    AppendProgramBindings(hasher, program->getAttributeBindings());
    AppendProgramAliasedBindings(hasher, program->getUniformLocationBindings());
    AppendProgramAliasedBindings(hasher, program->getFragmentOutputLocations());
    AppendProgramAliasedBindings(hasher, program->getFragmentOutputIndexes());
    for (const std::string &transformFeedbackVaryingName :
         program->getState().getTransformFeedbackVaryingNames())
    {
        hasher.Update(transformFeedbackVaryingName.data(), transformFeedbackVaryingName.size());
    }
    angle::UpdateHashWithValue(hasher, program->getTransformFeedbackBufferMode());

    // Include the status of FrameCapture, which adds source strings to the binary
    angle::UpdateHashWithValue(hasher,
                               context->getShareGroup()->getFrameCaptureShared()->enabled());

    // Get the hash
    ASSERT(hashOut);
    hasher.Final();
    memcpy(hashOut->data(), hasher.Digest(), angle::kBlobCacheKeyLength);
}

angle::Result MemoryProgramCache::getProgram(const Context *context,
                                             Program *program,
                                             egl::BlobCache::Key *hashOut,
                                             egl::CacheGetResult *resultOut)
{
    *resultOut = egl::CacheGetResult::NotFound;

    // If caching is effectively disabled, don't bother calculating the hash.
    if (!mBlobCache.isCachingEnabled(context))
    {
        return angle::Result::Continue;
    }

    ComputeHash(context, program, hashOut);

    angle::MemoryBuffer uncompressedData;
    switch (mBlobCache.getAndDecompress(context, context->getScratchBuffer(), *hashOut,
                                        kMaxUncompressedProgramSize, &uncompressedData))
    {
        case egl::BlobCache::GetAndDecompressResult::NotFound:
            return angle::Result::Continue;

        case egl::BlobCache::GetAndDecompressResult::DecompressFailure:
            ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                               "Error decompressing program binary data fetched from cache.");
            remove(*hashOut);
            // Consider this blob "not found".  As far as the rest of the code is considered,
            // corrupted cache might as well not have existed.
            return angle::Result::Continue;

        case egl::BlobCache::GetAndDecompressResult::Success:
            ANGLE_TRY(program->loadBinary(context, uncompressedData.data(),
                                          static_cast<int>(uncompressedData.size()), resultOut));

            // Result is either Success or Rejected
            ASSERT(*resultOut != egl::CacheGetResult::NotFound);

            // If cache load failed, evict the entry
            if (*resultOut == egl::CacheGetResult::Rejected)
            {
                ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                                   "Failed to load program binary from cache.");
                remove(*hashOut);
            }

            return angle::Result::Continue;
    }

    UNREACHABLE();
    return angle::Result::Continue;
}

bool MemoryProgramCache::getAt(size_t index,
                               const egl::BlobCache::Key **hashOut,
                               egl::BlobCache::Value *programOut)
{
    return mBlobCache.getAt(index, hashOut, programOut);
}

void MemoryProgramCache::remove(const egl::BlobCache::Key &programHash)
{
    mBlobCache.remove(programHash);
}

angle::Result MemoryProgramCache::putProgram(const egl::BlobCache::Key &programHash,
                                             const Context *context,
                                             Program *program)
{
    // If caching is effectively disabled, don't bother serializing the program.
    if (!mBlobCache.isCachingEnabled(context))
    {
        return angle::Result::Continue;
    }

    ANGLE_TRY(program->serialize(context));
    const angle::MemoryBuffer &serializedProgram = program->getSerializedBinary();

    if (serializedProgram.size() > kMaxUncompressedProgramSize)
    {
        std::ostringstream warningMessage;
        warningMessage << "Program is too large to cache: ";
        warningMessage << "program size: " << serializedProgram.size()
                       << ", max size: " << kMaxUncompressedProgramSize;
        ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, "%s",
                           warningMessage.str().c_str());
        return angle::Result::Continue;
    }

    angle::MemoryBuffer compressedData;
    if (!angle::CompressBlob(serializedProgram.size(), serializedProgram.data(), &compressedData))
    {
        ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                           "Error compressing binary data.");
        return angle::Result::Continue;
    }

    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCache.getMutex());
        // TODO: http://anglebug.com/42266037
        // This was a workaround for Chrome until it added support for EGL_ANDROID_blob_cache,
        // tracked by http://anglebug.com/42261225. This issue has since been closed, but removing
        // this still causes a test failure.
        auto *platform = ANGLEPlatformCurrent();
        angle::ProgramKeyType key = {};
        memcpy(key.data(), programHash.data(), angle::kBlobCacheKeyLength);
        platform->cacheProgram(platform, key, compressedData.size(), compressedData.data());
    }

    mBlobCache.put(context, programHash, std::move(compressedData));
    return angle::Result::Continue;
}

angle::Result MemoryProgramCache::updateProgram(const Context *context, Program *program)
{
    egl::BlobCache::Key programHash;
    ComputeHash(context, program, &programHash);
    return putProgram(programHash, context, program);
}

bool MemoryProgramCache::putBinary(const egl::BlobCache::Key &programHash,
                                   const uint8_t *binary,
                                   size_t length)
{
    // Copy the binary.
    angle::MemoryBuffer newEntry;
    if (!newEntry.resize(length))
    {
        return false;
    }
    memcpy(newEntry.data(), binary, length);

    // Store the binary.
    mBlobCache.populate(programHash, std::move(newEntry));

    return true;
}

void MemoryProgramCache::clear()
{
    mBlobCache.clear();
}

void MemoryProgramCache::resize(size_t maxCacheSizeBytes)
{
    mBlobCache.resize(maxCacheSizeBytes);
}

size_t MemoryProgramCache::entryCount() const
{
    return mBlobCache.entryCount();
}

size_t MemoryProgramCache::trim(size_t limit)
{
    return mBlobCache.trim(limit);
}

size_t MemoryProgramCache::size() const
{
    return mBlobCache.size();
}

size_t MemoryProgramCache::maxSize() const
{
    return mBlobCache.maxSize();
}

}  // namespace gl
