1 // Copyright 2016 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.
5 #ifndef CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_H_
6 #define CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_H_
11 #include <unordered_map>
13 #include "base/containers/mru_cache.h"
14 #include "base/memory/memory_pressure_listener.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/numerics/safe_math.h"
17 #include "base/trace_event/memory_dump_provider.h"
18 #include "cc/cc_export.h"
19 #include "cc/paint/draw_image.h"
20 #include "cc/tiles/image_decode_cache.h"
21 #include "cc/tiles/software_image_decode_cache_utils.h"
25 class CC_EXPORT SoftwareImageDecodeCache
26 : public ImageDecodeCache,
27 public base::trace_event::MemoryDumpProvider {
29 using Utils = SoftwareImageDecodeCacheUtils;
30 using CacheKey = Utils::CacheKey;
31 using CacheKeyHash = Utils::CacheKeyHash;
33 enum class DecodeTaskType { USE_IN_RASTER_TASKS, USE_OUT_OF_RASTER_TASKS };
35 SoftwareImageDecodeCache(SkColorType color_type,
36 size_t locked_memory_limit_bytes,
37 PaintImage::GeneratorClientId generator_client_id);
38 ~SoftwareImageDecodeCache() override;
40 // ImageDecodeCache overrides.
41 TaskResult GetTaskForImageAndRef(const DrawImage& image,
42 const TracingInfo& tracing_info) override;
43 TaskResult GetOutOfRasterDecodeTaskForImageAndRef(
44 const DrawImage& image) override;
45 void UnrefImage(const DrawImage& image) override;
46 DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) override;
47 void DrawWithImageFinished(const DrawImage& image,
48 const DecodedDrawImage& decoded_image) override;
49 void ReduceCacheUsage() override;
50 // Software doesn't keep outstanding images pinned, so this is a no-op.
51 void SetShouldAggressivelyFreeResources(
52 bool aggressively_free_resources) override {}
53 void ClearCache() override;
54 size_t GetMaximumMemoryLimitBytes() const override;
55 bool UseCacheForDrawImage(const DrawImage& image) const override;
57 // Decode the given image and store it in the cache. This is only called by an
58 // image decode task from a worker thread.
59 void DecodeImageInTask(const CacheKey& key,
60 const PaintImage& paint_image,
61 DecodeTaskType task_type);
63 void OnImageDecodeTaskCompleted(const CacheKey& key,
64 DecodeTaskType task_type);
66 // MemoryDumpProvider overrides.
67 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
68 base::trace_event::ProcessMemoryDump* pmd) override;
70 size_t GetNumCacheEntriesForTesting() const { return decoded_images_.size(); }
73 using CacheEntry = Utils::CacheEntry;
75 // MemoryBudget is a convenience class for memory bookkeeping and ensuring
76 // that we don't go over the limit when pre-decoding.
79 explicit MemoryBudget(size_t limit_bytes);
81 size_t AvailableMemoryBytes() const;
82 void AddUsage(size_t usage);
83 void SubtractUsage(size_t usage);
85 size_t total_limit_bytes() const { return limit_bytes_; }
86 size_t GetCurrentUsageSafe() const;
89 const size_t limit_bytes_;
90 base::CheckedNumeric<size_t> current_usage_bytes_;
93 using ImageMRUCache = base::
94 HashingMRUCache<CacheKey, std::unique_ptr<CacheEntry>, CacheKeyHash>;
96 // Actually decode the image. Note that this function can (and should) be
97 // called with no lock acquired, since it can do a lot of work. Note that it
98 // can also return nullptr to indicate the decode failed.
99 std::unique_ptr<CacheEntry> DecodeImageInternal(const CacheKey& key,
100 const DrawImage& draw_image);
102 // Get the decoded draw image for the given key and paint_image. Note that
103 // this function has to be called with no lock acquired, since it will acquire
104 // its own locks and might call DecodeImageInternal above. Note that
105 // when used internally, we still require that DrawWithImageFinished() is
106 // called afterwards.
107 DecodedDrawImage GetDecodedImageForDrawInternal(
109 const PaintImage& paint_image);
111 // Removes unlocked decoded images until the number of decoded images is
112 // reduced within the given limit.
113 void ReduceCacheUsageUntilWithinLimit(size_t limit);
115 void OnMemoryPressure(
116 base::MemoryPressureListener::MemoryPressureLevel level);
118 // Helper method to get the different tasks. Note that this should be used as
119 // if it was public (ie, all of the locks need to be properly acquired).
120 TaskResult GetTaskForImageAndRefInternal(const DrawImage& image,
121 const TracingInfo& tracing_info,
122 DecodeTaskType type);
124 CacheEntry* AddCacheEntry(const CacheKey& key);
126 void DecodeImageIfNecessary(const CacheKey& key,
127 const PaintImage& paint_image,
128 CacheEntry* cache_entry);
129 void AddBudgetForImage(const CacheKey& key, CacheEntry* entry);
130 void RemoveBudgetForImage(const CacheKey& key, CacheEntry* entry);
131 base::Optional<CacheKey> FindCachedCandidate(const CacheKey& key);
133 void UnrefImage(const CacheKey& key);
135 // The members below this comment can only be accessed if the lock is held to
136 // ensure that they are safe to access on multiple threads.
137 // The exception is accessing |locked_images_budget_.total_limit_bytes()|,
138 // which is const and thread safe.
141 // Decoded images and ref counts (predecode path).
142 ImageMRUCache decoded_images_;
144 std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
146 // A map of PaintImage::FrameKey to the ImageKeys for cached decodes of this
148 std::unordered_map<PaintImage::FrameKey,
149 std::vector<CacheKey>,
150 PaintImage::FrameKeyHash>
151 frame_key_to_image_keys_;
153 MemoryBudget locked_images_budget_;
155 const SkColorType color_type_;
156 const PaintImage::GeneratorClientId generator_client_id_;
158 size_t max_items_in_cache_;
159 // Records the maximum number of items in the cache over the lifetime of the
160 // cache. This is updated anytime we are requested to reduce cache usage.
161 size_t lifetime_max_items_in_cache_ = 0u;
166 #endif // CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_H_