| // 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_FLOW_RASTER_CACHE_KEY_H_ | |
| #define FLUTTER_FLOW_RASTER_CACHE_KEY_H_ | |
| #include <optional> | |
| #include <unordered_map> | |
| #include <utility> | |
| #include <vector> | |
| #include "flutter/fml/hash_combine.h" | |
| #include "flutter/fml/logging.h" | |
| #include "third_party/skia/include/core/SkMatrix.h" | |
| namespace flutter { | |
| class Layer; | |
| enum class RasterCacheKeyType { kLayer, kDisplayList, kLayerChildren }; | |
| class RasterCacheKeyID { | |
| public: | |
| static constexpr uint64_t kDefaultUniqueID = 0; | |
| RasterCacheKeyID(uint64_t unique_id, RasterCacheKeyType type) | |
| : unique_id_(unique_id), type_(type) {} | |
| RasterCacheKeyID(std::vector<RasterCacheKeyID> child_ids, | |
| RasterCacheKeyType type) | |
| : unique_id_(kDefaultUniqueID), | |
| type_(type), | |
| child_ids_(std::move(child_ids)) {} | |
| uint64_t unique_id() const { return unique_id_; } | |
| RasterCacheKeyType type() const { return type_; } | |
| const std::vector<RasterCacheKeyID>& child_ids() const { return child_ids_; } | |
| static std::optional<std::vector<RasterCacheKeyID>> LayerChildrenIds( | |
| const Layer* layer); | |
| std::size_t GetHash() const { | |
| if (cached_hash_) { | |
| return cached_hash_.value(); | |
| } | |
| std::size_t seed = fml::HashCombine(); | |
| fml::HashCombineSeed(seed, unique_id_); | |
| fml::HashCombineSeed(seed, type_); | |
| for (auto& child_id : child_ids_) { | |
| fml::HashCombineSeed(seed, child_id.GetHash()); | |
| } | |
| cached_hash_ = seed; | |
| return seed; | |
| } | |
| bool operator==(const RasterCacheKeyID& other) const { | |
| return unique_id_ == other.unique_id_ && type_ == other.type_ && | |
| GetHash() == other.GetHash() && child_ids_ == other.child_ids_; | |
| } | |
| bool operator!=(const RasterCacheKeyID& other) const { | |
| return !operator==(other); | |
| } | |
| private: | |
| const uint64_t unique_id_; | |
| const RasterCacheKeyType type_; | |
| const std::vector<RasterCacheKeyID> child_ids_; | |
| mutable std::optional<std::size_t> cached_hash_; | |
| }; | |
| enum class RasterCacheKeyKind { kLayerMetrics, kDisplayListMetrics }; | |
| class RasterCacheKey { | |
| public: | |
| RasterCacheKey(uint64_t unique_id, | |
| RasterCacheKeyType type, | |
| const SkMatrix& ctm) | |
| : RasterCacheKey(RasterCacheKeyID(unique_id, type), ctm) {} | |
| RasterCacheKey(RasterCacheKeyID id, const SkMatrix& ctm) | |
| : id_(std::move(id)), matrix_(ctm) { | |
| matrix_[SkMatrix::kMTransX] = 0; | |
| matrix_[SkMatrix::kMTransY] = 0; | |
| } | |
| const RasterCacheKeyID& id() const { return id_; } | |
| const SkMatrix& matrix() const { return matrix_; } | |
| RasterCacheKeyKind kind() const { | |
| switch (id_.type()) { | |
| case RasterCacheKeyType::kDisplayList: | |
| return RasterCacheKeyKind::kDisplayListMetrics; | |
| case RasterCacheKeyType::kLayer: | |
| case RasterCacheKeyType::kLayerChildren: | |
| return RasterCacheKeyKind::kLayerMetrics; | |
| } | |
| } | |
| struct Hash { | |
| std::size_t operator()(RasterCacheKey const& key) const { | |
| return key.id_.GetHash(); | |
| } | |
| }; | |
| struct Equal { | |
| constexpr bool operator()(const RasterCacheKey& lhs, | |
| const RasterCacheKey& rhs) const { | |
| return lhs.id_ == rhs.id_ && lhs.matrix_ == rhs.matrix_; | |
| } | |
| }; | |
| template <class Value> | |
| using Map = std::unordered_map<RasterCacheKey, Value, Hash, Equal>; | |
| private: | |
| RasterCacheKeyID id_; | |
| // ctm where only fractional (0-1) translations are preserved: | |
| // matrix_ = ctm; | |
| // matrix_[SkMatrix::kMTransX] = SkScalarFraction(ctm.getTranslateX()); | |
| // matrix_[SkMatrix::kMTransY] = SkScalarFraction(ctm.getTranslateY()); | |
| SkMatrix matrix_; | |
| }; | |
| } // namespace flutter | |
| #endif // FLUTTER_FLOW_RASTER_CACHE_KEY_H_ |