blob: 1b15a4b4f71ff4bf223b146f247b59ba5ada0b1d [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#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/functional/callback.h"
#include "base/functional/function_ref.h"
#include "base/gtest_prod_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/time/time.h"
#include "base/timer/timer.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 {
// ServiceTransferCache is a GPU process interface for retrieving cached entries
// from the transfer cache. These entries are populated by client calls to the
// ClientTransferCache or by an image decode accelerator task in the GPU
// process.
//
// In addition to access, the ServiceTransferCache is also responsible for
// unlocking and deleting entries when no longer needed, as well as enforcing
// cache limits. If the cache exceeds its specified limits, unlocked transfer
// cache entries may be deleted.
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;
};
ServiceTransferCache(const GpuPreferences& preferences,
base::RepeatingClosure flush_callback);
ServiceTransferCache(const ServiceTransferCache&) = delete;
ServiceTransferCache& operator=(const ServiceTransferCache&) = delete;
~ServiceTransferCache() override;
bool CreateLockedEntry(const EntryKey& key,
ServiceDiscardableHandle handle,
GrDirectContext* context,
skgpu::graphite::Recorder* graphite_recorder,
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);
// Creates an image transfer cache entry using |plane_images| (refer to
// ServiceImageTransferCacheEntry::BuildFromHardwareDecodedImage() for
// details). |decoder_id| and |entry_id| are used for creating the
// ServiceTransferCache::EntryKey (assuming cc::TransferCacheEntryType:kImage
// for the type). Returns true if the entry could be created and inserted;
// false otherwise.
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);
void PurgeMemory(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
// Test-only functions:
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:
FRIEND_TEST_ALL_PREFIXES(ServiceTransferCacheTest, PurgeEntryOnTimer);
struct CacheEntryInternal {
CacheEntryInternal(std::optional<ServiceDiscardableHandle> handle,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
CacheEntryInternal(CacheEntryInternal&& other);
CacheEntryInternal& operator=(CacheEntryInternal&& other);
~CacheEntryInternal();
std::optional<ServiceDiscardableHandle> handle;
std::unique_ptr<cc::ServiceTransferCacheEntry> entry;
base::TimeTicks last_use = base::TimeTicks::Now();
// For metrics.
uint32_t num_reuse = 0u;
base::TimeDelta max_last_use_delta;
};
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();
void MaybePostPruneOldEntries();
void PruneOldEntries();
// Helper to iterate through entries from least recently used to most
// recently used and erase them until `should_stop` returns true. Returns
// number of entries removed.
int RemoveOldEntriesUntil(
base::FunctionRef<bool(EntryCache::reverse_iterator)> should_stop);
template <typename Iterator>
Iterator ForceDeleteEntry(Iterator it);
const base::RepeatingClosure flush_callback_;
EntryCache entries_;
// Total size of all |entries_|. The same as summing
// GpuDiscardableEntry::size for each entry.
size_t total_size_ = 0;
// Total size of all |entries_| of TransferCacheEntryType::kImage.
size_t total_image_size_ = 0;
// Number of |entries_| of TransferCacheEntryType::kImage.
int total_image_count_ = 0;
// The limit above which the cache will start evicting resources.
size_t cache_size_limit_;
// The max number of entries we will hold in the cache.
size_t max_cache_entries_;
bool request_post_prune_old_entries_while_pending_ = false;
base::OneShotTimer prune_old_entries_timer_;
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_