// Copyright 2013 The Flutter 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 FLUTTER_COMMON_GRAPHICS_PERSISTENT_CACHE_H_
#define FLUTTER_COMMON_GRAPHICS_PERSISTENT_CACHE_H_

#include <memory>
#include <mutex>
#include <set>

#include "flutter/assets/asset_manager.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/task_runner.h"
#include "flutter/fml/unique_fd.h"
#include "third_party/skia/include/gpu/GrContextOptions.h"

namespace flutter {

namespace testing {
class ShellTest;
}

/// A cache of SkData that gets stored to disk.
///
/// This is mainly used for Shaders but is also written to by Dart.  It is
/// thread-safe for reading and writing from multiple threads.
class PersistentCache : public GrContextOptions::PersistentCache {
 public:
  // Mutable static switch that can be set before GetCacheForProcess. If true,
  // we'll only read existing caches but not generate new ones. Some clients
  // (e.g., embedded devices) prefer generating persistent cache files for the
  // specific device beforehand, and ship them as readonly files in OTA
  // packages.
  static bool gIsReadOnly;

  static PersistentCache* GetCacheForProcess();
  static void ResetCacheForProcess();

  // This must be called before |GetCacheForProcess|. Otherwise, it won't
  // affect the cache directory returned by |GetCacheForProcess|.
  static void SetCacheDirectoryPath(std::string path);

  // Convert a binary SkData key into a Base32 encoded string.
  //
  // This is used to specify persistent cache filenames and service protocol
  // json keys.
  static std::string SkKeyToFilePath(const SkData& key);

  // Allocate a MallocMapping containing the given key and value in the file
  // format used by the cache.
  static std::unique_ptr<fml::MallocMapping> BuildCacheObject(
      const SkData& key,
      const SkData& data);

  // Header written into the files used to store cached Skia objects.
  struct CacheObjectHeader {
    // A prefix used to identify the cache object file format.
    static const uint32_t kSignature = 0xA869593F;
    static const uint32_t kVersion1 = 1;

    CacheObjectHeader(uint32_t p_key_size) : key_size(p_key_size) {}

    uint32_t signature = kSignature;
    uint32_t version = kVersion1;
    uint32_t key_size;
  };

  ~PersistentCache() override;

  void AddWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);

  void RemoveWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);

  // Whether Skia tries to store any shader into this persistent cache after
  // |ResetStoredNewShaders| is called. This flag is usually reset before each
  // frame so we can know if Skia tries to compile new shaders in that frame.
  bool StoredNewShaders() const { return stored_new_shaders_; }
  void ResetStoredNewShaders() { stored_new_shaders_ = false; }
  void DumpSkp(const SkData& data);
  bool IsDumpingSkp() const { return is_dumping_skp_; }
  void SetIsDumpingSkp(bool value) { is_dumping_skp_ = value; }

  // Remove all files inside the persistent cache directory.
  // Return whether the purge is successful.
  bool Purge();

  // |GrContextOptions::PersistentCache|
  sk_sp<SkData> load(const SkData& key) override;

  struct SkSLCache {
    sk_sp<SkData> key;
    sk_sp<SkData> value;
  };

  /// Load all the SkSL shader caches in the right directory.
  std::vector<SkSLCache> LoadSkSLs() const;

  //----------------------------------------------------------------------------
  /// @brief      Precompile SkSLs packaged with the application and gathered
  ///             during previous runs in the given context.
  ///
  /// @warning    The context must be the rendering context. This context may be
  ///             destroyed during application suspension and subsequently
  ///             recreated. The SkSLs must be precompiled again in the new
  ///             context.
  ///
  /// @param      context  The rendering context to precompile shaders in.
  ///
  /// @return     The number of SkSLs precompiled.
  ///
  size_t PrecompileKnownSkSLs(GrDirectContext* context) const;

  // Return mappings for all skp's accessible through the AssetManager
  std::vector<std::unique_ptr<fml::Mapping>> GetSkpsFromAssetManager() const;

  /// Set the asset manager from which PersistentCache can load SkLSs. A nullptr
  /// can be provided to clear the asset manager.
  static void SetAssetManager(std::shared_ptr<AssetManager> value);
  static std::shared_ptr<AssetManager> asset_manager() {
    return asset_manager_;
  }

  static bool cache_sksl() { return cache_sksl_; }

  static void SetCacheSkSL(bool value);

  static void MarkStrategySet() { strategy_set_ = true; }

  static constexpr char kSkSLSubdirName[] = "sksl";
  static constexpr char kAssetFileName[] = "io.flutter.shaders.json";

 private:
  static std::string cache_base_path_;

  static std::shared_ptr<AssetManager> asset_manager_;

  static std::mutex instance_mutex_;
  static std::unique_ptr<PersistentCache> gPersistentCache;

  // Mutable static switch that can be set before GetCacheForProcess is called
  // and GrContextOptions.fShaderCacheStrategy is set. If true, it means that
  // we'll set `GrContextOptions::fShaderCacheStrategy` to `kSkSL`, and all the
  // persistent cache should be stored and loaded from the "sksl" directory.
  static std::atomic<bool> cache_sksl_;

  // Guard flag to make sure that cache_sksl_ is not modified after
  // strategy_set_ becomes true.
  static std::atomic<bool> strategy_set_;

  const bool is_read_only_;
  const std::shared_ptr<fml::UniqueFD> cache_directory_;
  const std::shared_ptr<fml::UniqueFD> sksl_cache_directory_;
  mutable std::mutex worker_task_runners_mutex_;
  std::multiset<fml::RefPtr<fml::TaskRunner>> worker_task_runners_;

  bool stored_new_shaders_ = false;
  bool is_dumping_skp_ = false;

  static SkSLCache LoadFile(const fml::UniqueFD& dir,
                            const std::string& file_name,
                            bool need_key);

  bool IsValid() const;

  PersistentCache(bool read_only = false);

  // |GrContextOptions::PersistentCache|
  void store(const SkData& key, const SkData& data) override;

  fml::RefPtr<fml::TaskRunner> GetWorkerTaskRunner() const;

  friend class testing::ShellTest;

  FML_DISALLOW_COPY_AND_ASSIGN(PersistentCache);
};

}  // namespace flutter

#endif  // FLUTTER_COMMON_GRAPHICS_PERSISTENT_CACHE_H_
