blob: 880859c8a1a3428c81fa9b52ec678f7f68f39cc6 [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.
#include "gpu/command_buffer/service/service_transfer_cache.h"
#include "base/sys_info.h"
namespace gpu {
namespace {
size_t CacheSizeLimit() {
if (base::SysInfo::IsLowEndDevice()) {
return 4 * 1024 * 1024;
} else {
return 128 * 1024 * 1024;
}
}
} // namespace
ServiceTransferCache::CacheEntryInternal::CacheEntryInternal(
ServiceDiscardableHandle handle,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry)
: handle(handle), entry(std::move(entry)) {}
ServiceTransferCache::CacheEntryInternal::~CacheEntryInternal() = default;
ServiceTransferCache::CacheEntryInternal::CacheEntryInternal(
CacheEntryInternal&& other) = default;
ServiceTransferCache::CacheEntryInternal&
ServiceTransferCache::CacheEntryInternal::operator=(
CacheEntryInternal&& other) = default;
ServiceTransferCache::ServiceTransferCache()
: entries_(EntryCache::NO_AUTO_EVICT),
cache_size_limit_(CacheSizeLimit()) {}
ServiceTransferCache::~ServiceTransferCache() = default;
bool ServiceTransferCache::CreateLockedEntry(
cc::TransferCacheEntryType entry_type,
uint32_t entry_id,
ServiceDiscardableHandle handle,
GrContext* context,
base::span<uint8_t> data) {
auto key = std::make_pair(entry_type, entry_id);
auto found = entries_.Peek(key);
if (found != entries_.end()) {
return false;
}
std::unique_ptr<cc::ServiceTransferCacheEntry> entry =
cc::ServiceTransferCacheEntry::Create(entry_type);
if (!entry)
return false;
entry->Deserialize(context, data);
total_size_ += entry->CachedSize();
entries_.Put(key, CacheEntryInternal(handle, std::move(entry)));
EnforceLimits();
return true;
}
bool ServiceTransferCache::UnlockEntry(cc::TransferCacheEntryType entry_type,
uint32_t entry_id) {
auto key = std::make_pair(entry_type, entry_id);
auto found = entries_.Peek(key);
if (found == entries_.end())
return false;
found->second.handle.Unlock();
return true;
}
bool ServiceTransferCache::DeleteEntry(cc::TransferCacheEntryType entry_type,
uint32_t entry_id) {
auto key = std::make_pair(entry_type, entry_id);
auto found = entries_.Peek(key);
if (found == entries_.end())
return false;
found->second.handle.ForceDelete();
total_size_ -= found->second.entry->CachedSize();
entries_.Erase(found);
return true;
}
cc::ServiceTransferCacheEntry* ServiceTransferCache::GetEntry(
cc::TransferCacheEntryType entry_type,
uint32_t entry_id) {
auto key = std::make_pair(entry_type, entry_id);
auto found = entries_.Get(key);
if (found == entries_.end())
return nullptr;
return found->second.entry.get();
}
void ServiceTransferCache::EnforceLimits() {
for (auto it = entries_.rbegin(); it != entries_.rend();) {
if (total_size_ <= cache_size_limit_) {
return;
}
if (!it->second.handle.Delete()) {
++it;
continue;
}
total_size_ -= it->second.entry->CachedSize();
it = entries_.Erase(it);
}
}
} // namespace gpu