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 |