blob: 8b2f16a1ab64a9f4fb54b6d5943f31367fb55427 [file] [log] [blame]
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// 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 "base/containers/mru_cache.h"
#include "base/containers/span.h"
#include "base/memory/memory_pressure_listener.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/SkRefCnt.h"
class GrContext;
class SkColorSpace;
struct SkImageInfo;
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();
~ServiceTransferCache() override;
bool CreateLockedEntry(const EntryKey& key,
ServiceDiscardableHandle handle,
GrContext* 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);
// Creates an image transfer cache entry using the decoded data in
// |decoded_image|. The |context| will be used to upload the image (if it's
// determined to fit in the GPU). |row_bytes| is the stride, and |image_info|
// describes the decoded data. |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 CreateLockedImageEntry(int decoder_id,
uint32_t entry_id,
ServiceDiscardableHandle handle,
GrContext* context,
base::span<const uint8_t> decoded_image,
size_t row_bytes,
const SkImageInfo& image_info,
bool needs_mips,
sk_sp<SkColorSpace> target_color_space);
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:
struct CacheEntryInternal {
CacheEntryInternal(base::Optional<ServiceDiscardableHandle> handle,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
CacheEntryInternal(CacheEntryInternal&& other);
CacheEntryInternal& operator=(CacheEntryInternal&& other);
~CacheEntryInternal();
base::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::MRUCache<EntryKey, CacheEntryInternal, EntryKeyComp>;
void EnforceLimits();
template <typename Iterator>
Iterator ForceDeleteEntry(Iterator it);
EntryCache entries_;
// Total size of all |entries_|. The same as summing
// GpuDiscardableEntry::size for each entry.
size_t total_size_ = 0;
// The limit above which the cache will start evicting resources.
size_t cache_size_limit_ = 0;
// The max number of entries we will hold in the cache.
size_t max_cache_entries_ = 0;
DISALLOW_COPY_AND_ASSIGN(ServiceTransferCache);
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_