#ifndef GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
#define GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/containers/lru_cache.h"
#include "base/containers/span.h"
#include "base/memory/memory_pressure_listener.h"
#include "cc/paint/image_transfer_cache_entry.h"
#include "cc/paint/transfer_cache_entry.h"
#include "gpu/command_buffer/common/discardable_handle.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/gpu_gles2_export.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkYUVAInfo.h"
class GrDirectContext;
class SkImage;
namespace gpu {
class GPU_GLES2_EXPORT ServiceTransferCache
: public base::trace_event::MemoryDumpProvider {
public:
struct GPU_GLES2_EXPORT EntryKey {
EntryKey(int decoder_id,
cc::TransferCacheEntryType entry_type,
uint32_t entry_id);
int decoder_id;
cc::TransferCacheEntryType entry_type;
uint32_t entry_id;
};
explicit ServiceTransferCache(const GpuPreferences& preferences);
ServiceTransferCache(const ServiceTransferCache&) = delete;
ServiceTransferCache& operator=(const ServiceTransferCache&) = delete;
~ServiceTransferCache() override;
bool CreateLockedEntry(const EntryKey& key,
ServiceDiscardableHandle handle,
GrDirectContext* context,
base::span<uint8_t> data);
void CreateLocalEntry(const EntryKey& key,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
bool UnlockEntry(const EntryKey& key);
bool DeleteEntry(const EntryKey& key);
cc::ServiceTransferCacheEntry* GetEntry(const EntryKey& key);
void DeleteAllEntriesForDecoder(int decoder_id);
bool CreateLockedHardwareDecodedImageEntry(
int decoder_id,
uint32_t entry_id,
ServiceDiscardableHandle handle,
GrDirectContext* context,
std::vector<sk_sp<SkImage>> plane_images,
SkYUVAInfo::PlaneConfig plane_config,
SkYUVAInfo::Subsampling subsampling,
SkYUVColorSpace yuv_color_space,
size_t buffer_byte_size,
bool needs_mips);
#if BUILDFLAG(ENABLE_HEIF_DECODER)
bool CreateLockedRGBAHardwareDecodedImageEntry(
int decoder_id,
uint32_t entry_id,
ServiceDiscardableHandle handle,
GrDirectContext* context,
std::vector<sk_sp<SkImage>> plane_images,
size_t buffer_byte_size);
#endif
void PurgeMemory(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
void SetCacheSizeLimitForTesting(size_t cache_size_limit) {
cache_size_limit_ = cache_size_limit;
EnforceLimits();
}
void SetMaxCacheEntriesForTesting(size_t max_cache_entries) {
max_cache_entries_ = max_cache_entries;
EnforceLimits();
}
size_t cache_size_for_testing() const { return total_size_; }
size_t entries_count_for_testing() const { return entries_.size(); }
private:
struct CacheEntryInternal {
CacheEntryInternal(absl::optional<ServiceDiscardableHandle> handle,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
CacheEntryInternal(CacheEntryInternal&& other);
CacheEntryInternal& operator=(CacheEntryInternal&& other);
~CacheEntryInternal();
absl::optional<ServiceDiscardableHandle> handle;
std::unique_ptr<cc::ServiceTransferCacheEntry> entry;
};
struct EntryKeyComp {
bool operator()(const EntryKey& lhs, const EntryKey& rhs) const {
if (lhs.decoder_id != rhs.decoder_id)
return lhs.decoder_id < rhs.decoder_id;
if (lhs.entry_type != rhs.entry_type)
return lhs.entry_type < rhs.entry_type;
return lhs.entry_id < rhs.entry_id;
}
};
using EntryCache = base::LRUCache<EntryKey, CacheEntryInternal, EntryKeyComp>;
void EnforceLimits();
template <typename Iterator>
Iterator ForceDeleteEntry(Iterator it);
EntryCache entries_;
size_t total_size_ = 0;
size_t total_image_size_ = 0;
int total_image_count_ = 0;
size_t cache_size_limit_;
size_t max_cache_entries_;
};
}
#endif