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 #include "gpu/command_buffer/service/texture_manager.h" |
| 9 |
| 10 namespace gpu { |
| 11 |
| 12 const size_t ServiceDiscardableManager::kMaxSize; |
| 13 |
| 14 ServiceDiscardableManager::GpuDiscardableEntry::GpuDiscardableEntry( |
| 15 ServiceDiscardableHandle handle, |
| 16 size_t size) |
| 17 : handle(handle), size(size) {} |
| 18 ServiceDiscardableManager::GpuDiscardableEntry::GpuDiscardableEntry( |
| 19 const GpuDiscardableEntry& other) = default; |
| 20 ServiceDiscardableManager::GpuDiscardableEntry::GpuDiscardableEntry( |
| 21 GpuDiscardableEntry&& other) = default; |
| 22 ServiceDiscardableManager::GpuDiscardableEntry::~GpuDiscardableEntry() = |
| 23 default; |
| 24 |
| 25 ServiceDiscardableManager::ServiceDiscardableManager() |
| 26 : entries_(EntryCache::NO_AUTO_EVICT) {} |
| 27 ServiceDiscardableManager::~ServiceDiscardableManager() { |
| 28 #if DCHECK_IS_ON() |
| 29 for (const auto& entry : entries_) { |
| 30 DCHECK(nullptr == entry.second.unlocked_texture_ref); |
| 31 } |
| 32 #endif |
| 33 } |
| 34 |
| 35 void ServiceDiscardableManager::InsertLockedTexture( |
| 36 uint32_t texture_id, |
| 37 size_t texture_size, |
| 38 gles2::TextureManager* texture_manager, |
| 39 ServiceDiscardableHandle handle) { |
| 40 auto found = entries_.Get({texture_id, texture_manager}); |
| 41 if (found != entries_.end()) { |
| 42 // We have somehow initialized a texture twice. The client *shouldn't* send |
| 43 // this command, but if it does, we will clean up the old entry and use |
| 44 // the new one. |
| 45 total_size_ -= found->second.size; |
| 46 if (found->second.unlocked_texture_ref) { |
| 47 texture_manager->ReturnTexture( |
| 48 std::move(found->second.unlocked_texture_ref)); |
| 49 } |
| 50 entries_.Erase(found); |
| 51 } |
| 52 |
| 53 total_size_ += texture_size; |
| 54 entries_.Put({texture_id, texture_manager}, |
| 55 GpuDiscardableEntry{handle, texture_size}); |
| 56 EnforceLimits(); |
| 57 } |
| 58 |
| 59 bool ServiceDiscardableManager::UnlockTexture( |
| 60 uint32_t texture_id, |
| 61 gles2::TextureManager* texture_manager, |
| 62 gles2::TextureRef** texture_to_unbind) { |
| 63 *texture_to_unbind = nullptr; |
| 64 |
| 65 auto found = entries_.Get({texture_id, texture_manager}); |
| 66 if (found == entries_.end()) |
| 67 return false; |
| 68 |
| 69 found->second.handle.Unlock(); |
| 70 if (--found->second.service_ref_count_ == 0) { |
| 71 found->second.unlocked_texture_ref = |
| 72 texture_manager->TakeTexture(texture_id); |
| 73 *texture_to_unbind = found->second.unlocked_texture_ref.get(); |
| 74 } |
| 75 |
| 76 return true; |
| 77 } |
| 78 |
| 79 bool ServiceDiscardableManager::LockTexture( |
| 80 uint32_t texture_id, |
| 81 gles2::TextureManager* texture_manager) { |
| 82 auto found = entries_.Peek({texture_id, texture_manager}); |
| 83 if (found == entries_.end()) |
| 84 return false; |
| 85 |
| 86 ++found->second.service_ref_count_; |
| 87 if (found->second.unlocked_texture_ref) { |
| 88 texture_manager->ReturnTexture( |
| 89 std::move(found->second.unlocked_texture_ref)); |
| 90 } |
| 91 |
| 92 return true; |
| 93 } |
| 94 |
| 95 void ServiceDiscardableManager::OnTextureManagerDestruction( |
| 96 gles2::TextureManager* texture_manager) { |
| 97 for (auto& entry : entries_) { |
| 98 if (entry.first.texture_manager == texture_manager && |
| 99 entry.second.unlocked_texture_ref) { |
| 100 texture_manager->ReturnTexture( |
| 101 std::move(entry.second.unlocked_texture_ref)); |
| 102 } |
| 103 } |
| 104 } |
| 105 |
| 106 void ServiceDiscardableManager::OnTextureDeleted( |
| 107 uint32_t texture_id, |
| 108 gles2::TextureManager* texture_manager) { |
| 109 auto found = entries_.Get({texture_id, texture_manager}); |
| 110 if (found == entries_.end()) |
| 111 return; |
| 112 |
| 113 found->second.handle.ForceDelete(); |
| 114 total_size_ -= found->second.size; |
| 115 entries_.Erase(found); |
| 116 } |
| 117 |
| 118 void ServiceDiscardableManager::OnTextureSizeChanged( |
| 119 uint32_t texture_id, |
| 120 gles2::TextureManager* texture_manager, |
| 121 size_t new_size) { |
| 122 auto found = entries_.Get({texture_id, texture_manager}); |
| 123 if (found == entries_.end()) |
| 124 return; |
| 125 |
| 126 total_size_ -= found->second.size; |
| 127 found->second.size = new_size; |
| 128 total_size_ += found->second.size; |
| 129 |
| 130 EnforceLimits(); |
| 131 } |
| 132 |
| 133 void ServiceDiscardableManager::EnforceLimits() { |
| 134 for (auto it = entries_.rbegin(); it != entries_.rend();) { |
| 135 if (total_size_ <= kMaxSize) { |
| 136 return; |
| 137 } |
| 138 if (!it->second.handle.Delete()) { |
| 139 ++it; |
| 140 continue; |
| 141 } |
| 142 |
| 143 total_size_ -= it->second.size; |
| 144 |
| 145 gles2::TextureManager* texture_manager = it->first.texture_manager; |
| 146 uint32_t texture_id = it->first.texture_id; |
| 147 |
| 148 // While unlocked, we hold the texture ref. Return this to the texture |
| 149 // manager for cleanup. |
| 150 texture_manager->ReturnTexture(std::move(it->second.unlocked_texture_ref)); |
| 151 |
| 152 // Erase before calling texture_manager->RemoveTexture, to avoid attempting |
| 153 // to remove the texture from entries_ twice. |
| 154 it = entries_.Erase(it); |
| 155 texture_manager->RemoveTexture(texture_id); |
| 156 } |
| 157 } |
| 158 |
| 159 bool ServiceDiscardableManager::IsEntryLockedForTesting( |
| 160 uint32_t texture_id, |
| 161 gles2::TextureManager* texture_manager) const { |
| 162 auto found = entries_.Peek({texture_id, texture_manager}); |
| 163 DCHECK(found != entries_.end()); |
| 164 |
| 165 return found->second.handle.IsLockedForTesting(); |
| 166 } |
| 167 |
| 168 gles2::TextureRef* ServiceDiscardableManager::UnlockedTextureRefForTesting( |
| 169 uint32_t texture_id, |
| 170 gles2::TextureManager* texture_manager) const { |
| 171 auto found = entries_.Peek({texture_id, texture_manager}); |
| 172 DCHECK(found != entries_.end()); |
| 173 |
| 174 return found->second.unlocked_texture_ref.get(); |
| 175 } |
| 176 |
| 177 } // namespace gpu |
OLD | NEW |