#ifndef CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_H_
#define CC_TILES_SOFTWARE_IMAGE_DECODE_CACHE_H_
#include <stdint.h>
#include <memory>
#include <unordered_map>
#include <vector>
#include "base/containers/lru_cache.h"
#include "base/numerics/safe_math.h"
#include "base/thread_annotations.h"
#include "base/trace_event/memory_dump_provider.h"
#include "cc/cc_export.h"
#include "cc/paint/draw_image.h"
#include "cc/tiles/image_decode_cache.h"
#include "cc/tiles/software_image_decode_cache_utils.h"
namespace cc {
class CC_EXPORT SoftwareImageDecodeCache
: public ImageDecodeCache,
public base::trace_event::MemoryDumpProvider {
public:
using Utils = SoftwareImageDecodeCacheUtils;
using CacheKey = Utils::CacheKey;
using CacheKeyHash = Utils::CacheKeyHash;
enum class TaskProcessingResult { kFullDecode, kLockOnly, kCancelled };
SoftwareImageDecodeCache(SkColorType color_type,
size_t locked_memory_limit_bytes);
~SoftwareImageDecodeCache() override;
TaskResult GetTaskForImageAndRef(ClientId client_id,
const DrawImage& image,
const TracingInfo& tracing_info) override;
TaskResult GetOutOfRasterDecodeTaskForImageAndRef(
ClientId client_id,
const DrawImage& image,
bool speculative = false) override;
void UnrefImage(const DrawImage& image) override;
DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) override;
void DrawWithImageFinished(const DrawImage& image,
const DecodedDrawImage& decoded_image) override;
void ReduceCacheUsage() override;
void SetShouldAggressivelyFreeResources(
bool aggressively_free_resources) override {}
void ClearCache() override;
size_t GetMaximumMemoryLimitBytes() const override;
bool UseCacheForDrawImage(const DrawImage& image) const override;
void RecordStats() override {}
ClientId GenerateClientId() override;
TaskProcessingResult DecodeImageInTask(const CacheKey& key,
const PaintImage& paint_image,
TaskType task_type);
void OnImageDecodeTaskCompleted(const CacheKey& key, TaskType task_type);
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
size_t GetNumCacheEntriesForTesting();
size_t GetMaxNumCacheEntriesForTesting();
private:
using CacheEntry = Utils::CacheEntry;
class MemoryBudget {
public:
explicit MemoryBudget(size_t limit_bytes);
size_t AvailableMemoryBytes() const;
void AddUsage(size_t usage);
void SubtractUsage(size_t usage);
void ResetUsage();
size_t total_limit_bytes() const { return limit_bytes_; }
size_t GetCurrentUsageSafe() const;
private:
const size_t limit_bytes_;
base::CheckedNumeric<size_t> current_usage_bytes_;
};
using ImageLRUCache = base::
HashingLRUCache<CacheKey, std::unique_ptr<CacheEntry>, CacheKeyHash>;
DecodedDrawImage GetDecodedImageForDrawInternal(const CacheKey& key,
const PaintImage& paint_image)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void ReduceCacheUsageUntilWithinLimit(size_t limit)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
TaskResult GetTaskForImageAndRefInternal(const DrawImage& image,
const TracingInfo& tracing_info,
TaskType type,
bool speculative)
LOCKS_EXCLUDED(lock_);
CacheEntry* AddCacheEntry(const CacheKey& key)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
TaskProcessingResult DecodeImageIfNecessary(const CacheKey& key,
const PaintImage& paint_image,
CacheEntry* cache_entry)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void AddBudgetForImage(const CacheKey& key, CacheEntry* entry)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void RemoveBudgetForImage(const CacheKey& key, CacheEntry* entry)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
std::optional<CacheKey> FindCachedCandidate(const CacheKey& key)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void UnrefImage(const CacheKey& key) EXCLUSIVE_LOCKS_REQUIRED(lock_);
SkColorType GetColorTypeForPaintImage(
const TargetColorParams& target_color_params,
const PaintImage& paint_image);
base::Lock lock_;
ImageLRUCache decoded_images_ GUARDED_BY(lock_);
std::unordered_map<PaintImage::FrameKey,
std::vector<CacheKey>,
PaintImage::FrameKeyHash>
frame_key_to_image_keys_ GUARDED_BY(lock_);
MemoryBudget locked_images_budget_;
const SkColorType color_type_;
const PaintImage::GeneratorClientId generator_client_id_;
const size_t max_items_in_cache_;
};
}
#endif