1 // Copyright 2018 The Chromium Authors
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_UTILS_H_
6 #define CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_UTILS_H_
12 #include "base/callback.h"
13 #include "base/memory/discardable_memory.h"
14 #include "base/memory/scoped_refptr.h"
15 #include "cc/cc_export.h"
16 #include "cc/paint/decoded_draw_image.h"
17 #include "cc/paint/draw_image.h"
18 #include "cc/paint/paint_image.h"
19 #include "cc/paint/target_color_params.h"
20 #include "cc/raster/tile_task.h"
21 #include "cc/tiles/image_decode_cache_utils.h"
22 #include "third_party/skia/include/core/SkImage.h"
23 #include "third_party/skia/include/core/SkImageInfo.h"
24 #include "third_party/skia/include/core/SkSize.h"
25 #include "ui/gfx/color_space.h"
26 #include "ui/gfx/geometry/rect.h"
27 #include "ui/gfx/geometry/size.h"
31 class SoftwareImageDecodeCacheUtils {
33 // The following should only be accessed by the software image cache.
34 friend class SoftwareImageDecodeCache;
36 // CacheKey is a class that gets a cache key out of a given draw
37 // image. That is, this key uniquely identifies an image in the cache. Note
38 // that it's insufficient to use SkImage's unique id, since the same image can
39 // appear in the cache multiple times at different scales and filter
41 class CC_EXPORT CacheKey {
43 // Enum indicating the type of processing to do for this key:
44 // kOriginal - use the original decode without any subrecting or scaling.
45 // kSubrectOriginal - extract a subrect from the original decode but do not
47 // kSubrectAndScale - extract a subrect (if needed) from the original decode
49 enum ProcessingType { kOriginal, kSubrectOriginal, kSubrectAndScale };
51 static CacheKey FromDrawImage(const DrawImage& image,
52 SkColorType color_type);
54 CacheKey(const CacheKey& other);
55 CacheKey& operator=(const CacheKey& other);
57 bool operator==(const CacheKey& other) const {
58 // The frame_key always has to be the same. However, after that all
59 // original decodes are the same, so if we can use the original decode,
60 // return true. If not, then we have to compare every field.
61 // |nearest_neighbor_| is not compared below since it is not used for
62 // scaled decodes and does not affect the contents of the cache entry
63 // (just passed to skia for the filtering to be done at raster time).
64 DCHECK(!is_nearest_neighbor_ || type_ != kSubrectAndScale);
65 return frame_key_ == other.frame_key_ && type_ == other.type_ &&
66 target_color_params_ == other.target_color_params_ &&
67 (type_ == kOriginal || (src_rect_ == other.src_rect_ &&
68 target_size_ == other.target_size_));
71 bool operator!=(const CacheKey& other) const { return !(*this == other); }
73 const PaintImage::FrameKey& frame_key() const { return frame_key_; }
74 PaintImage::Id stable_id() const { return stable_id_; }
75 ProcessingType type() const { return type_; }
76 bool is_nearest_neighbor() const { return is_nearest_neighbor_; }
77 bool may_be_lcp_candidate() const { return may_be_lcp_candidate_; }
78 gfx::Rect src_rect() const { return src_rect_; }
79 gfx::Size target_size() const { return target_size_; }
80 const TargetColorParams& target_color_params() const {
81 return target_color_params_;
84 size_t get_hash() const { return hash_; }
86 // Helper to figure out how much memory the locked image represented by this
88 size_t locked_bytes() const {
89 // TODO(vmpstr): Handle formats other than RGBA.
90 base::CheckedNumeric<size_t> result = 4;
91 result *= target_size_.width();
92 result *= target_size_.height();
93 return result.ValueOrDefault(std::numeric_limits<size_t>::max());
96 std::string ToString() const;
99 CacheKey(PaintImage::FrameKey frame_key,
100 PaintImage::Id stable_id,
102 bool is_nearest_neighbor,
103 bool may_be_lcp_candidate,
104 const gfx::Rect& src_rect,
105 const gfx::Size& size,
106 const TargetColorParams& target_color_params);
108 PaintImage::FrameKey frame_key_;
109 // The stable id is does not factor into the cache key's value for hashing
110 // and comparison (as it is redundant). It is only used to look up other
111 // cache entries of the same stable id.
112 PaintImage::Id stable_id_;
113 ProcessingType type_;
114 bool is_nearest_neighbor_;
115 bool may_be_lcp_candidate_;
117 gfx::Size target_size_;
118 TargetColorParams target_color_params_;
122 struct CacheKeyHash {
123 size_t operator()(const CacheKey& key) const { return key.get_hash(); }
126 // CacheEntry is a convenience storage for discardable memory. It can also
127 // construct an image out of SkImageInfo and stored discardable memory.
128 class CC_EXPORT CacheEntry {
131 CacheEntry(const SkImageInfo& info,
132 std::unique_ptr<base::DiscardableMemory> memory,
133 const SkSize& src_rect_offset);
136 void MoveImageMemoryTo(CacheEntry* entry);
138 sk_sp<SkImage> image() const {
144 const SkSize& src_rect_offset() const { return src_rect_offset_; }
149 // An ID which uniquely identifies this CacheEntry within the image decode
150 // cache. Used in memory tracing.
151 uint64_t tracing_id() const { return tracing_id_; }
152 // Mark this image as being used in either a draw or as a source for a
153 // scaled image. Either case represents this decode as being valuable and
155 void mark_used() { usage_stats_.used = true; }
156 void mark_cached() { cached_ = true; }
157 void mark_out_of_raster() { usage_stats_.first_lock_out_of_raster = true; }
159 // Since this is an inner class, we expose these variables publicly for
161 // TODO(vmpstr): A good simple clean-up would be to rethink this class
162 // and its interactions to instead expose a few functions which would also
163 // facilitate easier DCHECKs.
165 bool decode_failed = false;
166 bool is_locked = false;
167 bool is_budgeted = false;
169 scoped_refptr<TileTask> in_raster_task;
170 scoped_refptr<TileTask> out_of_raster_task;
172 std::unique_ptr<base::DiscardableMemory> memory;
176 // We can only create a decoded image in a locked state, so the initial
180 bool last_lock_failed = false;
181 bool first_lock_wasted = false;
182 bool first_lock_out_of_raster = false;
185 SkImageInfo image_info_;
186 sk_sp<SkImage> image_;
187 SkSize src_rect_offset_;
188 uint64_t tracing_id_;
189 UsageStats usage_stats_;
190 // Indicates whether this entry was ever in the cache.
191 bool cached_ = false;
194 // |on_no_memory| is called when memory allocation fails in this function,
195 // before retrying it once. As a consequence, this should free memory, and
196 // importantly, address space as well.
197 static std::unique_ptr<CacheEntry> DoDecodeImage(
199 const PaintImage& image,
200 SkColorType color_type,
201 PaintImage::GeneratorClientId client_id,
202 base::OnceClosure on_no_memory);
203 static std::unique_ptr<CacheEntry> GenerateCacheEntryFromCandidate(
205 const DecodedDrawImage& candidate,
206 bool needs_extract_subset,
207 SkColorType color_type);
212 #endif // CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_UTILS_H_