1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_UTILS_H_
#define CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_UTILS_H_
#include <limits>
#include <memory>
#include <string>
#include "base/functional/callback.h"
#include "base/memory/discardable_memory.h"
#include "base/memory/scoped_refptr.h"
#include "cc/cc_export.h"
#include "cc/paint/decoded_draw_image.h"
#include "cc/paint/draw_image.h"
#include "cc/paint/paint_image.h"
#include "cc/paint/target_color_params.h"
#include "cc/raster/tile_task.h"
#include "cc/tiles/image_decode_cache_utils.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkSize.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace cc {
class SoftwareImageDecodeCacheUtils {
private:
// The following should only be accessed by the software image cache.
friend class SoftwareImageDecodeCache;
// CacheKey is a class that gets a cache key out of a given draw
// image. That is, this key uniquely identifies an image in the cache. Note
// that it's insufficient to use SkImage's unique id, since the same image can
// appear in the cache multiple times at different scales and filter
// qualities.
class CC_EXPORT CacheKey {
public:
// Enum indicating the type of processing to do for this key:
// kOriginal - use the original decode without any subrecting or scaling.
// kSubrectOriginal - extract a subrect from the original decode but do not
// scale it.
// kSubrectAndScale - extract a subrect (if needed) from the original decode
// and scale it.
enum ProcessingType { kOriginal, kSubrectOriginal, kSubrectAndScale };
static CacheKey FromDrawImage(const DrawImage& image,
SkColorType color_type);
CacheKey(const CacheKey& other);
CacheKey& operator=(const CacheKey& other);
bool operator==(const CacheKey& other) const {
// The frame_key always has to be the same. However, after that all
// original decodes are the same, so if we can use the original decode,
// return true. If not, then we have to compare every field.
// |nearest_neighbor_| is not compared below since it is not used for
// scaled decodes and does not affect the contents of the cache entry
// (just passed to skia for the filtering to be done at raster time).
DCHECK(!is_nearest_neighbor_ || type_ != kSubrectAndScale);
return frame_key_ == other.frame_key_ && type_ == other.type_ &&
target_color_params_ == other.target_color_params_ &&
(type_ == kOriginal || (src_rect_ == other.src_rect_ &&
target_size_ == other.target_size_));
}
bool operator!=(const CacheKey& other) const { return !(*this == other); }
const PaintImage::FrameKey& frame_key() const { return frame_key_; }
PaintImage::Id stable_id() const { return stable_id_; }
ProcessingType type() const { return type_; }
bool is_nearest_neighbor() const { return is_nearest_neighbor_; }
bool may_be_lcp_candidate() const { return may_be_lcp_candidate_; }
gfx::Rect src_rect() const { return src_rect_; }
gfx::Size target_size() const { return target_size_; }
const TargetColorParams& target_color_params() const {
return target_color_params_;
}
size_t get_hash() const { return hash_; }
// Helper to figure out how much memory the locked image represented by this
// key would take.
size_t locked_bytes() const {
// TODO(vmpstr): Handle formats other than RGBA.
base::CheckedNumeric<size_t> result = 4;
result *= target_size_.width();
result *= target_size_.height();
return result.ValueOrDefault(std::numeric_limits<size_t>::max());
}
std::string ToString() const;
private:
CacheKey(PaintImage::FrameKey frame_key,
PaintImage::Id stable_id,
ProcessingType type,
bool is_nearest_neighbor,
bool may_be_lcp_candidate,
const gfx::Rect& src_rect,
const gfx::Size& size,
const TargetColorParams& target_color_params);
PaintImage::FrameKey frame_key_;
// The stable id is does not factor into the cache key's value for hashing
// and comparison (as it is redundant). It is only used to look up other
// cache entries of the same stable id.
PaintImage::Id stable_id_;
ProcessingType type_;
bool is_nearest_neighbor_;
bool may_be_lcp_candidate_;
gfx::Rect src_rect_;
gfx::Size target_size_;
TargetColorParams target_color_params_;
size_t hash_;
};
struct CacheKeyHash {
size_t operator()(const CacheKey& key) const { return key.get_hash(); }
};
// CacheEntry is a convenience storage for discardable memory. It can also
// construct an image out of SkImageInfo and stored discardable memory.
class CC_EXPORT CacheEntry {
public:
CacheEntry();
CacheEntry(const SkImageInfo& info,
std::unique_ptr<base::DiscardableMemory> memory,
const SkSize& src_rect_offset);
~CacheEntry();
void MoveImageMemoryTo(CacheEntry* entry);
sk_sp<SkImage> image() const {
if (!memory)
return nullptr;
DCHECK(is_locked);
return image_;
}
const SkSize& src_rect_offset() const { return src_rect_offset_; }
bool Lock();
void Unlock();
// An ID which uniquely identifies this CacheEntry within the image decode
// cache. Used in memory tracing.
uint64_t tracing_id() const { return tracing_id_; }
// Mark this image as being used in either a draw or as a source for a
// scaled image. Either case represents this decode as being valuable and
// not wasted.
void mark_cached() { cached_ = true; }
// Since this is an inner class, we expose these variables publicly for
// simplicity.
// TODO(vmpstr): A good simple clean-up would be to rethink this class
// and its interactions to instead expose a few functions which would also
// facilitate easier DCHECKs.
int ref_count = 0;
bool decode_failed = false;
bool is_locked = false;
bool is_budgeted = false;
scoped_refptr<TileTask> in_raster_task;
scoped_refptr<TileTask> out_of_raster_task;
std::unique_ptr<base::DiscardableMemory> memory;
private:
SkImageInfo image_info_;
sk_sp<SkImage> image_;
SkSize src_rect_offset_;
uint64_t tracing_id_;
// Indicates whether this entry was ever in the cache.
bool cached_ = false;
};
// |on_no_memory| is called when memory allocation fails in this function,
// before retrying it once. As a consequence, this should free memory, and
// importantly, address space as well.
static std::unique_ptr<CacheEntry> DoDecodeImage(
const CacheKey& key,
const PaintImage& image,
SkColorType color_type,
PaintImage::GeneratorClientId client_id,
base::OnceClosure on_no_memory);
static std::unique_ptr<CacheEntry> GenerateCacheEntryFromCandidate(
const CacheKey& key,
const DecodedDrawImage& candidate,
bool needs_extract_subset,
SkColorType color_type);
};
} // namespace cc
#endif // CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_UTILS_H_
|