1 // Copyright 2018 The Chromium 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 CC_PAINT_PAINT_CACHE_H_ 6 #define CC_PAINT_PAINT_CACHE_H_ 7 8 #include <map> 9 #include <set> 10 11 #include "base/containers/mru_cache.h" 12 #include "base/containers/stack_container.h" 13 #include "cc/paint/paint_export.h" 14 #include "third_party/skia/include/core/SkPath.h" 15 #include "third_party/skia/include/core/SkTextBlob.h" 16 17 namespace cc { 18 19 // PaintCache is used to cache high frequency small paint data types, like 20 // SkTextBlob and SkPath in the GPU service. The ClientPaintCache budgets and 21 // controls the cache state in the ServicePaintCache, regularly purging old 22 // entries returned in ClientPaintCache::Purge from the service side cache. In 23 // addition to this, the complete cache is cleared during the raster context 24 // idle cleanup. This effectively means that the cache budget is used as working 25 // memory that is only kept while we are actively rasterizing. 26 // 27 // The entries are serialized by the caller during paint op serialization, and 28 // the cache assumes the deserialization and purging to be done in order for 29 // accurately tracking the service side state in ServicePaintCache. 30 // 31 // Note that while TransferCache should be used for large data types that would 32 // benefit from a shared cache budgeted across all clients, using a client 33 // controlled PaintCache with a tighter budget is better for these data types 34 // since it avoids the need for cross-process ref-counting required by the 35 // TransferCache. 36 37 using PaintCacheId = uint32_t; 38 using PaintCacheIds = std::vector<PaintCacheId>; 39 enum class PaintCacheDataType : uint32_t { kTextBlob, kPath, kLast = kPath }; 40 enum class PaintCacheEntryState : uint32_t { 41 kEmpty, 42 kCached, 43 kInlined, 44 kLast = kInlined 45 }; 46 47 constexpr size_t PaintCacheDataTypeCount = 48 static_cast<uint32_t>(PaintCacheDataType::kLast) + 1u; 49 50 class CC_PAINT_EXPORT ClientPaintCache { 51 public: 52 // If ClientPaintCache is constructed with a max_budget_bytes of 53 // kNoCachingBudget, its Put() method becomes a no-op, rendering the instance 54 // a no-op instance. 55 static constexpr size_t kNoCachingBudget = 0u; 56 57 explicit ClientPaintCache(size_t max_budget_bytes); 58 ClientPaintCache(const ClientPaintCache&) = delete; 59 ~ClientPaintCache(); 60 61 ClientPaintCache& operator=(const ClientPaintCache&) = delete; 62 63 bool Get(PaintCacheDataType type, PaintCacheId id); 64 void Put(PaintCacheDataType type, PaintCacheId id, size_t size); 65 66 // Populates |purged_data| with the list of ids which should be purged from 67 // the ServicePaintCache. 68 using PurgedData = PaintCacheIds[PaintCacheDataTypeCount]; 69 void Purge(PurgedData* purged_data); 70 71 // Finalize the state of pending entries, which were sent to the service-side 72 // cache. 73 void FinalizePendingEntries(); 74 75 // Notifies that the pending entries were not sent to the service-side cache 76 // and should be discarded. 77 void AbortPendingEntries(); 78 79 // Notifies that all entries should be purged from the ServicePaintCache. 80 // Returns true if any entries were evicted from this call. 81 bool PurgeAll(); 82 bytes_used()83 size_t bytes_used() const { return bytes_used_; } 84 85 private: 86 using CacheKey = std::pair<PaintCacheDataType, PaintCacheId>; 87 using CacheMap = base::MRUCache<CacheKey, size_t>; 88 89 template <typename Iterator> 90 void EraseFromMap(Iterator it); 91 92 CacheMap cache_map_; 93 const size_t max_budget_; 94 size_t bytes_used_ = 0u; 95 96 // List of entries added to the map but not committed since we might fail to 97 // send them to the service-side cache. This is necessary to ensure we 98 // maintain an accurate mirror of the service-side state. 99 base::StackVector<CacheKey, 1> pending_entries_; 100 }; 101 102 class CC_PAINT_EXPORT ServicePaintCache { 103 public: 104 ServicePaintCache(); 105 ~ServicePaintCache(); 106 107 // Stores the |blob| received from the client in the cache. 108 void PutTextBlob(PaintCacheId id, sk_sp<SkTextBlob> blob); 109 110 // Retrieves an entry for |id| stored in the cache. Or nullptr if the entry 111 // is not found. 112 sk_sp<SkTextBlob> GetTextBlob(PaintCacheId id) const; 113 114 // Stores |path| received from the client in the cache. 115 void PutPath(PaintCacheId, SkPath path); 116 117 // Retrieves an entry for |id| stored in the cache. The path data is stored in 118 // |path| pointed memory. Returns false, if the entry is not found. 119 bool GetPath(PaintCacheId id, SkPath* path) const; 120 121 void Purge(PaintCacheDataType type, 122 size_t n, 123 const volatile PaintCacheId* ids); 124 void PurgeAll(); empty()125 bool empty() const { return cached_blobs_.empty() && cached_paths_.empty(); } 126 127 private: 128 using BlobMap = std::map<PaintCacheId, sk_sp<SkTextBlob>>; 129 BlobMap cached_blobs_; 130 using PathMap = std::map<PaintCacheId, SkPath>; 131 PathMap cached_paths_; 132 }; 133 134 } // namespace cc 135 136 #endif // CC_PAINT_PAINT_CACHE_H_ 137