//
// Copyright 2018 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.
//
// BlobCache: 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.

#ifndef LIBANGLE_BLOB_CACHE_H_
#define LIBANGLE_BLOB_CACHE_H_

#include <array>
#include <cstring>

#include "common/SimpleMutex.h"
#include "libANGLE/Error.h"
#include "libANGLE/SizedMRUCache.h"
#include "libANGLE/angletypes.h"

namespace gl
{
class Context;
}  // namespace gl

namespace egl
{

// Used by MemoryProgramCache and MemoryShaderCache, this result indicates whether program/shader
// cache load from blob was successful.
enum class CacheGetResult
{
    // Binary blob was found and is valid
    Success,
    // Binary blob was not found
    NotFound,
    // Binary blob was found, but was rejected due to errors (corruption, version mismatch, etc)
    Rejected,
};

class BlobCache final : angle::NonCopyable
{
  public:
    static constexpr size_t kKeyLength = angle::kBlobCacheKeyLength;
    using Key                          = angle::BlobCacheKey;
    using Value                        = angle::BlobCacheValue;
    enum class CacheSource
    {
        Memory,
        Disk,
    };

    explicit BlobCache(size_t maxCacheSizeBytes);
    ~BlobCache();

    // Store a key-blob pair in the cache.  If application callbacks are set, the application cache
    // will be used.  Otherwise the value is cached in this object.
    void put(const gl::Context *context, const BlobCache::Key &key, angle::MemoryBuffer &&value);

    // Store a key-blob pair in the cache, but compress the blob before insertion. Returns false if
    // compression fails, returns true otherwise.
    bool compressAndPut(const gl::Context *context,
                        const BlobCache::Key &key,
                        angle::MemoryBuffer &&uncompressedValue,
                        size_t *compressedSize);

    // Store a key-blob pair in the application cache, only if application callbacks are set.
    void putApplication(const gl::Context *context,
                        const BlobCache::Key &key,
                        const angle::MemoryBuffer &value);

    // Store a key-blob pair in the cache without making callbacks to the application.  This is used
    // to repopulate this object's cache on startup without generating callback calls.
    void populate(const BlobCache::Key &key,
                  angle::MemoryBuffer &&value,
                  CacheSource source = CacheSource::Disk);

    // Check if the cache contains the blob corresponding to this key.  If application callbacks are
    // set, those will be used.  Otherwise they key is looked up in this object's cache.
    [[nodiscard]] bool get(const gl::Context *context,
                           angle::ScratchBuffer *scratchBuffer,
                           const BlobCache::Key &key,
                           BlobCache::Value *valueOut);

    // For querying the contents of the cache.
    [[nodiscard]] bool getAt(size_t index,
                             const BlobCache::Key **keyOut,
                             BlobCache::Value *valueOut);

    enum class GetAndDecompressResult
    {
        Success,
        NotFound,
        DecompressFailure,
    };
    [[nodiscard]] GetAndDecompressResult getAndDecompress(
        const gl::Context *context,
        angle::ScratchBuffer *scratchBuffer,
        const BlobCache::Key &key,
        size_t maxUncompressedDataSize,
        angle::MemoryBuffer *uncompressedValueOut);

    // Evict a blob from the binary cache.
    void remove(const BlobCache::Key &key);

    // Empty the cache.
    void clear()
    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
        mBlobCache.clear();
    }

    // Resize the cache. Discards current contents. Returns previous cache size.
    size_t resize(size_t maxCacheSizeBytes)
    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
        return mBlobCache.resize(maxCacheSizeBytes);
    }

    // Returns the number of entries in the cache.
    size_t entryCount() const
    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
        return mBlobCache.entryCount();
    }

    // Reduces the current cache size and returns the number of bytes freed.
    size_t trim(size_t limit)
    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
        return mBlobCache.shrinkToSize(limit);
    }

    // Returns the current cache size in bytes.
    size_t size() const
    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
        return mBlobCache.size();
    }

    // Returns whether the cache is empty
    bool empty() const
    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
        return mBlobCache.empty();
    }

    // Returns the maximum cache size in bytes.
    size_t maxSize() const
    {
        std::scoped_lock<angle::SimpleMutex> lock(mBlobCacheMutex);
        return mBlobCache.maxSize();
    }

    void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);

    bool areBlobCacheFuncsSet() const;

    bool isCachingEnabled(const gl::Context *context) const;

    angle::SimpleMutex &getMutex() { return mBlobCacheMutex; }

  private:
    size_t callBlobGetCallback(const gl::Context *context,
                               const void *key,
                               size_t keySize,
                               void *value,
                               size_t valueSize);

    // This internal cache is used only if the application is not providing caching callbacks
    using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;

    mutable angle::SimpleMutex mBlobCacheMutex;
    angle::SizedMRUCache<BlobCache::Key, CacheEntry> mBlobCache;

    EGLSetBlobFuncANDROID mSetBlobFunc;
    EGLGetBlobFuncANDROID mGetBlobFunc;
};

}  // namespace egl

#endif  // LIBANGLE_MEMORY_PROGRAM_CACHE_H_
