Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "gpu/command_buffer/service/service_discardable_manager.h" | |
| 6 | |
| 7 #include "base/memory/singleton.h" | |
| 8 | |
| 9 namespace gpu { | |
| 10 namespace { | |
| 11 // TODO(ericrk): Arbitrary limit, refine this once we actually use this class in | |
| 12 // production. crbug.com/706456 | |
| 13 const size_t kMaxSize = 256 * 1024 * 1024; | |
| 14 } | |
| 15 | |
| 16 ServiceDiscardableManager::GpuDiscardableEntry::GpuDiscardableEntry( | |
| 17 ServiceDiscardableHandle handle, | |
| 18 size_t size) | |
| 19 : handle(handle), size(size) {} | |
| 20 ServiceDiscardableManager::GpuDiscardableEntry::GpuDiscardableEntry( | |
| 21 const GpuDiscardableEntry& other) = default; | |
| 22 ServiceDiscardableManager::GpuDiscardableEntry::GpuDiscardableEntry( | |
| 23 GpuDiscardableEntry&& other) = default; | |
| 24 ServiceDiscardableManager::GpuDiscardableEntry::~GpuDiscardableEntry() = | |
| 25 default; | |
| 26 | |
| 27 ServiceDiscardableManager::ServiceDiscardableManager() | |
| 28 : entries_(EntryCache::NO_AUTO_EVICT) {} | |
| 29 ServiceDiscardableManager::~ServiceDiscardableManager() { | |
| 30 #if DCHECK_IS_ON() | |
| 31 for (const auto& entry : entries_) { | |
| 32 DCHECK(nullptr == entry.second.unlocked_texture_ref); | |
| 33 } | |
| 34 #endif | |
| 35 } | |
| 36 | |
| 37 void ServiceDiscardableManager::InsertLockedTexture( | |
| 38 uint32_t texture_id, | |
| 39 size_t texture_size, | |
| 40 gles2::TextureManager* texture_manager, | |
| 41 ServiceDiscardableHandle handle) { | |
| 42 total_size_ += texture_size; | |
| 43 entries_.Put({texture_id, texture_manager}, | |
| 44 GpuDiscardableEntry{handle, texture_size}); | |
| 45 EnforceLimits(); | |
| 46 } | |
| 47 | |
| 48 bool ServiceDiscardableManager::UnlockTexture( | |
| 49 uint32_t texture_id, | |
| 50 gles2::TextureManager* texture_manager, | |
| 51 gles2::TextureRef** texture_to_unbind) { | |
| 52 *texture_to_unbind = nullptr; | |
| 53 | |
| 54 auto found = entries_.Get({texture_id, texture_manager}); | |
| 55 if (found == entries_.end()) | |
| 56 return false; | |
| 57 | |
| 58 found->second.handle.Unlock(); | |
| 59 if (--found->second.service_ref_count_ == 0) { | |
| 60 found->second.unlocked_texture_ref = | |
| 61 texture_manager->TakeTexture(texture_id); | |
| 62 *texture_to_unbind = found->second.unlocked_texture_ref.get(); | |
| 63 } | |
| 64 | |
| 65 return true; | |
| 66 } | |
| 67 | |
| 68 bool ServiceDiscardableManager::LockTexture( | |
| 69 uint32_t texture_id, | |
| 70 gles2::TextureManager* texture_manager) { | |
| 71 auto found = entries_.Peek({texture_id, texture_manager}); | |
| 72 if (found == entries_.end()) | |
| 73 return false; | |
| 74 | |
| 75 ++found->second.service_ref_count_; | |
| 76 if (found->second.unlocked_texture_ref) { | |
| 77 texture_manager->ReturnTexture( | |
| 78 std::move(found->second.unlocked_texture_ref)); | |
| 79 } | |
| 80 | |
| 81 return true; | |
| 82 } | |
| 83 | |
| 84 void ServiceDiscardableManager::OnTextureManagerDestruction( | |
| 85 gles2::TextureManager* texture_manager) { | |
| 86 for (auto& entry : entries_) { | |
| 87 if (entry.first.texture_manager == texture_manager && | |
| 88 entry.second.unlocked_texture_ref) { | |
| 89 texture_manager->ReturnTexture( | |
| 90 std::move(entry.second.unlocked_texture_ref)); | |
| 91 } | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 void ServiceDiscardableManager::OnTextureDeleted( | |
| 96 uint32_t texture_id, | |
| 97 gles2::TextureManager* texture_manager) { | |
| 98 auto found = entries_.Get({texture_id, texture_manager}); | |
| 99 if (found == entries_.end()) | |
| 100 return; | |
| 101 | |
| 102 found->second.handle.ForceDelete(); | |
| 103 total_size_ -= found->second.size; | |
| 104 entries_.Erase(found); | |
| 105 } | |
| 106 | |
| 107 void ServiceDiscardableManager::OnTextureSizeChanged( | |
| 108 uint32_t texture_id, | |
| 109 gles2::TextureManager* texture_manager, | |
| 110 size_t new_size) { | |
| 111 auto found = entries_.Get({texture_id, texture_manager}); | |
| 112 if (found == entries_.end()) | |
| 113 return; | |
| 114 | |
| 115 total_size_ -= found->second.size; | |
| 116 found->second.size = new_size; | |
| 117 total_size_ += found->second.size; | |
| 118 | |
| 119 EnforceLimits(); | |
| 120 } | |
| 121 | |
| 122 void ServiceDiscardableManager::EnforceLimits() { | |
| 123 for (auto it = entries_.rbegin(); it != entries_.rend();) { | |
| 124 if (total_size_ <= kMaxSize) { | |
| 125 return; | |
| 126 } | |
| 127 if (!it->second.handle.Delete()) { | |
| 128 ++it; | |
| 129 continue; | |
| 130 } | |
| 131 | |
| 132 total_size_ -= it->second.size; | |
| 133 it->first.texture_manager->ReturnTexture( | |
| 134 std::move(it->second.unlocked_texture_ref)); | |
| 135 it->first.texture_manager->RemoveTexture(it->first.texture_id); | |
| 136 it = entries_.Erase(it); | |
|
piman
2017/05/10 22:13:59
Won't texture_manager->RemoveTexture above call in
ericrk
2017/05/12 16:22:11
yes, we should :D
| |
| 137 } | |
| 138 } | |
| 139 | |
| 140 bool ServiceDiscardableManager::IsEntryLockedForTesting( | |
| 141 uint32_t texture_id, | |
| 142 gles2::TextureManager* texture_manager) const { | |
| 143 auto found = entries_.Peek({texture_id, texture_manager}); | |
| 144 DCHECK(found != entries_.end()); | |
| 145 | |
| 146 return found->second.handle.IsLockedForTesting(); | |
| 147 } | |
| 148 | |
| 149 } // namespace gpu | |
| OLD | NEW |