diff --git a/shell/common/persistent_cache.cc b/shell/common/persistent_cache.cc index c1ec498398dbb..4875f7229b58d 100644 --- a/shell/common/persistent_cache.cc +++ b/shell/common/persistent_cache.cc @@ -171,18 +171,42 @@ sk_sp ParseBase64(const std::string& input) { return SkData::MakeWithCopy(decoder.getData(), decoder.getDataSize()); } +static sk_sp LoadFile(const fml::UniqueFD& dir, + const std::string& file_name) { + auto file = fml::OpenFileReadOnly(dir, file_name.c_str()); + if (!file.is_valid()) { + return nullptr; + } + auto mapping = std::make_unique(file); + if (mapping->GetSize() == 0) { + return nullptr; + } + return SkData::MakeWithCopy(mapping->GetMapping(), mapping->GetSize()); +} + +static void PushSkSL(std::vector* result, + const fml::UniqueFD& directory, + const std::string& filename) { + sk_sp key = ParseBase32(filename); + sk_sp data = LoadFile(directory, filename); + if (key != nullptr && data != nullptr) { + result->push_back({key, data}); + } else { + FML_LOG(ERROR) << "Failed to load: " << filename; + } +} + std::vector PersistentCache::LoadSkSLs() { TRACE_EVENT0("flutter", "PersistentCache::LoadSkSLs"); std::vector result; - fml::FileVisitor visitor = [&result](const fml::UniqueFD& directory, - const std::string& filename) { - sk_sp key = ParseBase32(filename); - sk_sp data = LoadFile(directory, filename); - if (key != nullptr && data != nullptr) { - result.push_back({key, data}); - } else { - FML_LOG(ERROR) << "Failed to load: " << filename; - } + + std::unordered_set visited_filenames; + fml::FileVisitor visitor = [&result, &visited_filenames, this]( + const fml::UniqueFD& directory, + const std::string& filename) { + sksl_filenames_.insert(filename); + visited_filenames.insert(filename); + PushSkSL(&result, directory, filename); return true; }; @@ -191,6 +215,13 @@ std::vector PersistentCache::LoadSkSLs() { // cache is invalid. if (IsValid()) { fml::VisitFiles(*sksl_cache_directory_, visitor); + // In case `rewinddir` doesn't work properly, load SkSLs from known + // sksl files manually (https://github.com/flutter/flutter/issues/65258). + for (const std::string& filename : sksl_filenames_) { + if (visited_filenames.count(filename) == 0) { + PushSkSL(&result, *sksl_cache_directory_, filename); + } + } } std::unique_ptr mapping = nullptr; @@ -240,19 +271,6 @@ bool PersistentCache::IsValid() const { return cache_directory_ && cache_directory_->is_valid(); } -sk_sp PersistentCache::LoadFile(const fml::UniqueFD& dir, - const std::string& file_name) { - auto file = fml::OpenFileReadOnly(dir, file_name.c_str()); - if (!file.is_valid()) { - return nullptr; - } - auto mapping = std::make_unique(file); - if (mapping->GetSize() == 0) { - return nullptr; - } - return SkData::MakeWithCopy(mapping->GetMapping(), mapping->GetSize()); -} - // |GrContextOptions::PersistentCache| sk_sp PersistentCache::load(const SkData& key) { TRACE_EVENT0("flutter", "PersistentCacheLoad"); @@ -263,7 +281,7 @@ sk_sp PersistentCache::load(const SkData& key) { if (file_name.size() == 0) { return nullptr; } - auto result = PersistentCache::LoadFile(*cache_directory_, file_name); + auto result = LoadFile(*cache_directory_, file_name); if (result != nullptr) { TRACE_EVENT0("flutter", "PersistentCacheLoadHit"); } diff --git a/shell/common/persistent_cache.h b/shell/common/persistent_cache.h index 905eb9b55faf4..cd7a2505d9dbb 100644 --- a/shell/common/persistent_cache.h +++ b/shell/common/persistent_cache.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "flutter/assets/asset_manager.h" #include "flutter/fml/macros.h" @@ -105,12 +106,13 @@ class PersistentCache : public GrContextOptions::PersistentCache { mutable std::mutex worker_task_runners_mutex_; std::multiset> worker_task_runners_; + // Some iOS devices didn't `rewinddir` properly so we'll save the SkSL + // filenames visited to fix https://github.com/flutter/flutter/issues/65258. + std::unordered_set sksl_filenames_; + bool stored_new_shaders_ = false; bool is_dumping_skp_ = false; - static sk_sp LoadFile(const fml::UniqueFD& dir, - const std::string& filen_ame); - bool IsValid() const; PersistentCache(bool read_only = false);