Flutter Engine
persistent_cache.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_COMMON_GRAPHICS_PERSISTENT_CACHE_H_
6 #define FLUTTER_COMMON_GRAPHICS_PERSISTENT_CACHE_H_
7 
8 #include <memory>
9 #include <mutex>
10 #include <set>
11 
12 #include "flutter/assets/asset_manager.h"
13 #include "flutter/fml/macros.h"
14 #include "flutter/fml/task_runner.h"
15 #include "flutter/fml/unique_fd.h"
16 #include "third_party/skia/include/gpu/GrContextOptions.h"
17 
18 namespace flutter {
19 
20 namespace testing {
21 class ShellTest;
22 }
23 
24 /// A cache of SkData that gets stored to disk.
25 ///
26 /// This is mainly used for Shaders but is also written to by Dart. It is
27 /// thread-safe for reading and writing from multiple threads.
28 class PersistentCache : public GrContextOptions::PersistentCache {
29  public:
30  // Mutable static switch that can be set before GetCacheForProcess. If true,
31  // we'll only read existing caches but not generate new ones. Some clients
32  // (e.g., embedded devices) prefer generating persistent cache files for the
33  // specific device beforehand, and ship them as readonly files in OTA
34  // packages.
35  static bool gIsReadOnly;
36 
37  static PersistentCache* GetCacheForProcess();
38  static void ResetCacheForProcess();
39 
40  // This must be called before |GetCacheForProcess|. Otherwise, it won't
41  // affect the cache directory returned by |GetCacheForProcess|.
42  static void SetCacheDirectoryPath(std::string path);
43 
44  // Convert a binary SkData key into a Base32 encoded string.
45  //
46  // This is used to specify persistent cache filenames and service protocol
47  // json keys.
48  static std::string SkKeyToFilePath(const SkData& key);
49 
50  // Allocate a MallocMapping containing the given key and value in the file
51  // format used by the cache.
52  static std::unique_ptr<fml::MallocMapping> BuildCacheObject(
53  const SkData& key,
54  const SkData& data);
55 
56  // Header written into the files used to store cached Skia objects.
58  // A prefix used to identify the cache object file format.
59  static const uint32_t kSignature = 0xA869593F;
60  static const uint32_t kVersion1 = 1;
61 
62  CacheObjectHeader(uint32_t p_key_size) : key_size(p_key_size) {}
63 
64  uint32_t signature = kSignature;
65  uint32_t version = kVersion1;
66  uint32_t key_size;
67  };
68 
69  ~PersistentCache() override;
70 
71  void AddWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);
72 
73  void RemoveWorkerTaskRunner(fml::RefPtr<fml::TaskRunner> task_runner);
74 
75  // Whether Skia tries to store any shader into this persistent cache after
76  // |ResetStoredNewShaders| is called. This flag is usually reset before each
77  // frame so we can know if Skia tries to compile new shaders in that frame.
78  bool StoredNewShaders() const { return stored_new_shaders_; }
79  void ResetStoredNewShaders() { stored_new_shaders_ = false; }
80  void DumpSkp(const SkData& data);
81  bool IsDumpingSkp() const { return is_dumping_skp_; }
82  void SetIsDumpingSkp(bool value) { is_dumping_skp_ = value; }
83 
84  // Remove all files inside the persistent cache directory.
85  // Return whether the purge is successful.
86  bool Purge();
87 
88  // |GrContextOptions::PersistentCache|
89  sk_sp<SkData> load(const SkData& key) override;
90 
91  struct SkSLCache {
92  sk_sp<SkData> key;
93  sk_sp<SkData> value;
94  };
95 
96  /// Load all the SkSL shader caches in the right directory.
97  std::vector<SkSLCache> LoadSkSLs() const;
98 
99  //----------------------------------------------------------------------------
100  /// @brief Precompile SkSLs packaged with the application and gathered
101  /// during previous runs in the given context.
102  ///
103  /// @warning The context must be the rendering context. This context may be
104  /// destroyed during application suspension and subsequently
105  /// recreated. The SkSLs must be precompiled again in the new
106  /// context.
107  ///
108  /// @param context The rendering context to precompile shaders in.
109  ///
110  /// @return The number of SkSLs precompiled.
111  ///
112  size_t PrecompileKnownSkSLs(GrDirectContext* context) const;
113 
114  // Return mappings for all skp's accessible through the AssetManager
115  std::vector<std::unique_ptr<fml::Mapping>> GetSkpsFromAssetManager() const;
116 
117  /// Set the asset manager from which PersistentCache can load SkLSs. A nullptr
118  /// can be provided to clear the asset manager.
119  static void SetAssetManager(std::shared_ptr<AssetManager> value);
120  static std::shared_ptr<AssetManager> asset_manager() {
121  return asset_manager_;
122  }
123 
124  static bool cache_sksl() { return cache_sksl_; }
125 
126  static void SetCacheSkSL(bool value);
127 
128  static void MarkStrategySet() { strategy_set_ = true; }
129 
130  static constexpr char kSkSLSubdirName[] = "sksl";
131  static constexpr char kAssetFileName[] = "io.flutter.shaders.json";
132 
133  private:
134  static std::string cache_base_path_;
135 
136  static std::shared_ptr<AssetManager> asset_manager_;
137 
138  static std::mutex instance_mutex_;
139  static std::unique_ptr<PersistentCache> gPersistentCache;
140 
141  // Mutable static switch that can be set before GetCacheForProcess is called
142  // and GrContextOptions.fShaderCacheStrategy is set. If true, it means that
143  // we'll set `GrContextOptions::fShaderCacheStrategy` to `kSkSL`, and all the
144  // persistent cache should be stored and loaded from the "sksl" directory.
145  static std::atomic<bool> cache_sksl_;
146 
147  // Guard flag to make sure that cache_sksl_ is not modified after
148  // strategy_set_ becomes true.
149  static std::atomic<bool> strategy_set_;
150 
151  const bool is_read_only_;
152  const std::shared_ptr<fml::UniqueFD> cache_directory_;
153  const std::shared_ptr<fml::UniqueFD> sksl_cache_directory_;
154  mutable std::mutex worker_task_runners_mutex_;
155  std::multiset<fml::RefPtr<fml::TaskRunner>> worker_task_runners_;
156 
157  bool stored_new_shaders_ = false;
158  bool is_dumping_skp_ = false;
159 
160  static SkSLCache LoadFile(const fml::UniqueFD& dir,
161  const std::string& file_name,
162  bool need_key);
163 
164  bool IsValid() const;
165 
166  PersistentCache(bool read_only = false);
167 
168  // |GrContextOptions::PersistentCache|
169  void store(const SkData& key, const SkData& data) override;
170 
171  fml::RefPtr<fml::TaskRunner> GetWorkerTaskRunner() const;
172 
173  friend class testing::ShellTest;
174 
176 };
177 
178 } // namespace flutter
179 
180 #endif // FLUTTER_COMMON_GRAPHICS_PERSISTENT_CACHE_H_
std::unique_ptr< fml::Mapping > LoadFile(int namespace_fd, const char *path, bool executable)
static bool IsValid(double value)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition: switches.h:41
uint8_t value
void SetIsDumpingSkp(bool value)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
static std::shared_ptr< AssetManager > asset_manager()