blob: 045210aa8951b8ad3185ff6fc1f9708c29a0a8b1 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 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 "content/common/gpu/gpu_memory_manager.h"
6
Torne (Richard Coles)58218062012-11-14 11:43:16 +00007#include <algorithm>
8
9#include "base/bind.h"
10#include "base/command_line.h"
11#include "base/debug/trace_event.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +010012#include "base/message_loop/message_loop.h"
Ben Murdoch58e6fbe2013-07-26 10:20:38 +010013#include "base/process/process_handle.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010014#include "base/strings/string_number_conversions.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000015#include "content/common/gpu/gpu_channel_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000016#include "content/common/gpu/gpu_memory_manager_client.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000017#include "content/common/gpu/gpu_memory_tracking.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000018#include "content/common/gpu/gpu_memory_uma_stats.h"
19#include "content/common/gpu/gpu_messages.h"
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000020#include "gpu/command_buffer/common/gpu_memory_allocation.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021#include "gpu/command_buffer/service/gpu_switches.h"
22
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000023using gpu::MemoryAllocation;
24
Torne (Richard Coles)58218062012-11-14 11:43:16 +000025namespace content {
26namespace {
27
28const int kDelayedScheduleManageTimeoutMs = 67;
29
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000030const uint64 kBytesAllocatedUnmanagedStep = 16 * 1024 * 1024;
31
32void TrackValueChanged(uint64 old_size, uint64 new_size, uint64* total_size) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000033 DCHECK(new_size > old_size || *total_size >= (old_size - new_size));
34 *total_size += (new_size - old_size);
35}
36
37}
38
39GpuMemoryManager::GpuMemoryManager(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000040 GpuChannelManager* channel_manager,
41 uint64 max_surfaces_with_frontbuffer_soft_limit)
42 : channel_manager_(channel_manager),
43 manage_immediate_scheduled_(false),
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010044 disable_schedule_manage_(false),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000045 max_surfaces_with_frontbuffer_soft_limit_(
46 max_surfaces_with_frontbuffer_soft_limit),
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010047 client_hard_limit_bytes_(0),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000048 bytes_allocated_managed_current_(0),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000049 bytes_allocated_unmanaged_current_(0),
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010050 bytes_allocated_historical_max_(0)
51{ }
Torne (Richard Coles)58218062012-11-14 11:43:16 +000052
53GpuMemoryManager::~GpuMemoryManager() {
54 DCHECK(tracking_groups_.empty());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000055 DCHECK(clients_visible_mru_.empty());
56 DCHECK(clients_nonvisible_mru_.empty());
57 DCHECK(clients_nonsurface_.empty());
58 DCHECK(!bytes_allocated_managed_current_);
59 DCHECK(!bytes_allocated_unmanaged_current_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000060}
61
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000062void GpuMemoryManager::UpdateAvailableGpuMemory() {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010063 // If the value was overridden on the command line, use the specified value.
64 static bool client_hard_limit_bytes_overridden =
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010065 base::CommandLine::ForCurrentProcess()->HasSwitch(
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010066 switches::kForceGpuMemAvailableMb);
67 if (client_hard_limit_bytes_overridden) {
68 base::StringToUint64(
Torne (Richard Coles)6e8cce62014-08-19 13:00:08 +010069 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010070 switches::kForceGpuMemAvailableMb),
71 &client_hard_limit_bytes_);
72 client_hard_limit_bytes_ *= 1024 * 1024;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000073 return;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010074 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +000075
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010076#if defined(OS_ANDROID)
Torne (Richard Coles)58218062012-11-14 11:43:16 +000077 // On non-Android, we use an operating system query when possible.
78 // We do not have a reliable concept of multiple GPUs existing in
79 // a system, so just be safe and go with the minimum encountered.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000080 uint64 bytes_min = 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000081
82 // Only use the clients that are visible, because otherwise the set of clients
83 // we are querying could become extremely large.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000084 for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
85 it != clients_visible_mru_.end();
86 ++it) {
87 const GpuMemoryManagerClientState* client_state = *it;
88 if (!client_state->has_surface_)
Torne (Richard Coles)58218062012-11-14 11:43:16 +000089 continue;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000090 if (!client_state->visible_)
Torne (Richard Coles)58218062012-11-14 11:43:16 +000091 continue;
92
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000093 uint64 bytes = 0;
94 if (client_state->client_->GetTotalGpuMemory(&bytes)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000095 if (!bytes_min || bytes < bytes_min)
96 bytes_min = bytes;
97 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +000098 }
99
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100100 client_hard_limit_bytes_ = bytes_min;
101 // Clamp the observed value to a specific range on Android.
102 client_hard_limit_bytes_ = std::max(client_hard_limit_bytes_,
103 static_cast<uint64>(16 * 1024 * 1024));
104 client_hard_limit_bytes_ = std::min(client_hard_limit_bytes_,
105 static_cast<uint64>(256 * 1024 * 1024));
106#else
107 // Ignore what the system said and give all clients the same maximum
108 // allocation on desktop platforms.
109 client_hard_limit_bytes_ = 256 * 1024 * 1024;
110#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000111}
112
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000113void GpuMemoryManager::ScheduleManage(
114 ScheduleManageTime schedule_manage_time) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000115 if (disable_schedule_manage_)
116 return;
117 if (manage_immediate_scheduled_)
118 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000119 if (schedule_manage_time == kScheduleManageNow) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100120 base::MessageLoop::current()->PostTask(
121 FROM_HERE, base::Bind(&GpuMemoryManager::Manage, AsWeakPtr()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000122 manage_immediate_scheduled_ = true;
123 if (!delayed_manage_callback_.IsCancelled())
124 delayed_manage_callback_.Cancel();
125 } else {
126 if (!delayed_manage_callback_.IsCancelled())
127 return;
128 delayed_manage_callback_.Reset(base::Bind(&GpuMemoryManager::Manage,
129 AsWeakPtr()));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100130 base::MessageLoop::current()->PostDelayedTask(
131 FROM_HERE,
132 delayed_manage_callback_.callback(),
133 base::TimeDelta::FromMilliseconds(kDelayedScheduleManageTimeoutMs));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000134 }
135}
136
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000137void GpuMemoryManager::TrackMemoryAllocatedChange(
138 GpuMemoryTrackingGroup* tracking_group,
139 uint64 old_size,
140 uint64 new_size,
141 gpu::gles2::MemoryTracker::Pool tracking_pool) {
142 TrackValueChanged(old_size, new_size, &tracking_group->size_);
143 switch (tracking_pool) {
144 case gpu::gles2::MemoryTracker::kManaged:
145 TrackValueChanged(old_size, new_size, &bytes_allocated_managed_current_);
146 break;
147 case gpu::gles2::MemoryTracker::kUnmanaged:
148 TrackValueChanged(old_size,
149 new_size,
150 &bytes_allocated_unmanaged_current_);
151 break;
152 default:
153 NOTREACHED();
154 break;
155 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000156 if (new_size != old_size) {
157 TRACE_COUNTER1("gpu",
158 "GpuMemoryUsage",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000159 GetCurrentUsage());
160 }
161
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100162 if (GetCurrentUsage() > bytes_allocated_historical_max_ +
163 kBytesAllocatedUnmanagedStep) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000164 bytes_allocated_historical_max_ = GetCurrentUsage();
165 // If we're blowing into new memory usage territory, spam the browser
166 // process with the most up-to-date information about our memory usage.
167 SendUmaStatsToBrowser();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000168 }
169}
170
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000171bool GpuMemoryManager::EnsureGPUMemoryAvailable(uint64 /* size_needed */) {
172 // TODO: Check if there is enough space. Lose contexts until there is.
173 return true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000174}
175
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000176GpuMemoryManagerClientState* GpuMemoryManager::CreateClientState(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000177 GpuMemoryManagerClient* client,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000178 bool has_surface,
179 bool visible) {
180 TrackingGroupMap::iterator tracking_group_it =
181 tracking_groups_.find(client->GetMemoryTracker());
182 DCHECK(tracking_group_it != tracking_groups_.end());
183 GpuMemoryTrackingGroup* tracking_group = tracking_group_it->second;
184
185 GpuMemoryManagerClientState* client_state = new GpuMemoryManagerClientState(
186 this, client, tracking_group, has_surface, visible);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000187 AddClientToList(client_state);
188 ScheduleManage(kScheduleManageNow);
189 return client_state;
190}
191
192void GpuMemoryManager::OnDestroyClientState(
193 GpuMemoryManagerClientState* client_state) {
194 RemoveClientFromList(client_state);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000195 ScheduleManage(kScheduleManageLater);
196}
197
198void GpuMemoryManager::SetClientStateVisible(
199 GpuMemoryManagerClientState* client_state, bool visible) {
200 DCHECK(client_state->has_surface_);
201 if (client_state->visible_ == visible)
202 return;
203
204 RemoveClientFromList(client_state);
205 client_state->visible_ = visible;
206 AddClientToList(client_state);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000207 ScheduleManage(visible ? kScheduleManageNow : kScheduleManageLater);
208}
209
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000210uint64 GpuMemoryManager::GetClientMemoryUsage(
Ben Murdocheffb81e2014-03-31 11:51:25 +0100211 const GpuMemoryManagerClient* client) const {
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000212 TrackingGroupMap::const_iterator tracking_group_it =
213 tracking_groups_.find(client->GetMemoryTracker());
214 DCHECK(tracking_group_it != tracking_groups_.end());
215 return tracking_group_it->second->GetSize();
216}
217
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000218GpuMemoryTrackingGroup* GpuMemoryManager::CreateTrackingGroup(
219 base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker) {
220 GpuMemoryTrackingGroup* tracking_group = new GpuMemoryTrackingGroup(
221 pid, memory_tracker, this);
222 DCHECK(!tracking_groups_.count(tracking_group->GetMemoryTracker()));
223 tracking_groups_.insert(std::make_pair(tracking_group->GetMemoryTracker(),
224 tracking_group));
225 return tracking_group;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000226}
227
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000228void GpuMemoryManager::OnDestroyTrackingGroup(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000229 GpuMemoryTrackingGroup* tracking_group) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000230 DCHECK(tracking_groups_.count(tracking_group->GetMemoryTracker()));
231 tracking_groups_.erase(tracking_group->GetMemoryTracker());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000232}
233
234void GpuMemoryManager::GetVideoMemoryUsageStats(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000235 GPUVideoMemoryUsageStats* video_memory_usage_stats) const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000236 // For each context group, assign its memory usage to its PID
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000237 video_memory_usage_stats->process_map.clear();
238 for (TrackingGroupMap::const_iterator i =
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000239 tracking_groups_.begin(); i != tracking_groups_.end(); ++i) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000240 const GpuMemoryTrackingGroup* tracking_group = i->second;
241 video_memory_usage_stats->process_map[
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000242 tracking_group->GetPid()].video_memory += tracking_group->GetSize();
243 }
244
245 // Assign the total across all processes in the GPU process
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000246 video_memory_usage_stats->process_map[
247 base::GetCurrentProcId()].video_memory = GetCurrentUsage();
248 video_memory_usage_stats->process_map[
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000249 base::GetCurrentProcId()].has_duplicates = true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000250
251 video_memory_usage_stats->bytes_allocated = GetCurrentUsage();
252 video_memory_usage_stats->bytes_allocated_historical_max =
253 bytes_allocated_historical_max_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000254}
255
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000256void GpuMemoryManager::Manage() {
257 manage_immediate_scheduled_ = false;
258 delayed_manage_callback_.Cancel();
259
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000260 // Update the amount of GPU memory available on the system.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000261 UpdateAvailableGpuMemory();
262
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000263 // Determine which clients are "hibernated" (which determines the
264 // distribution of frontbuffers and memory among clients that don't have
265 // surfaces).
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000266 SetClientsHibernatedState();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000267
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000268 // Assign memory allocations to clients that have surfaces.
269 AssignSurfacesAllocations();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000270
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000271 // Assign memory allocations to clients that don't have surfaces.
272 AssignNonSurfacesAllocations();
273
274 SendUmaStatsToBrowser();
275}
276
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000277void GpuMemoryManager::AssignSurfacesAllocations() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000278 // Send that allocation to the clients.
279 ClientStateList clients = clients_visible_mru_;
280 clients.insert(clients.end(),
281 clients_nonvisible_mru_.begin(),
282 clients_nonvisible_mru_.end());
283 for (ClientStateList::const_iterator it = clients.begin();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000284 it != clients.end();
285 ++it) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000286 GpuMemoryManagerClientState* client_state = *it;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000287
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000288 // Populate and send the allocation to the client
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000289 MemoryAllocation allocation;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100290 allocation.bytes_limit_when_visible = client_hard_limit_bytes_;
291#if defined(OS_ANDROID)
292 // On Android, because there is only one visible tab at any time, allow
293 // that renderer to cache as much as it can.
294 allocation.priority_cutoff_when_visible =
295 MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
296#else
297 // On desktop platforms, instruct the renderers to cache only a smaller
298 // set, to play nice with other renderers and other applications. If this
299 // if not done, then the system can become unstable.
300 // http://crbug.com/145600 (Linux)
301 // http://crbug.com/141377 (Mac)
302 allocation.priority_cutoff_when_visible =
303 MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
304#endif
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000305
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000306 client_state->client_->SetMemoryAllocation(allocation);
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000307 client_state->client_->SuggestHaveFrontBuffer(!client_state->hibernated_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000308 }
309}
310
311void GpuMemoryManager::AssignNonSurfacesAllocations() {
312 for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
313 it != clients_nonsurface_.end();
314 ++it) {
315 GpuMemoryManagerClientState* client_state = *it;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000316 MemoryAllocation allocation;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000317
318 if (!client_state->hibernated_) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100319 allocation.bytes_limit_when_visible = client_hard_limit_bytes_;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000320 allocation.priority_cutoff_when_visible =
321 MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000322 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000323
324 client_state->client_->SetMemoryAllocation(allocation);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000325 }
326}
327
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000328void GpuMemoryManager::SetClientsHibernatedState() const {
329 // Re-set all tracking groups as being hibernated.
330 for (TrackingGroupMap::const_iterator it = tracking_groups_.begin();
331 it != tracking_groups_.end();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000332 ++it) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000333 GpuMemoryTrackingGroup* tracking_group = it->second;
334 tracking_group->hibernated_ = true;
335 }
336 // All clients with surfaces that are visible are non-hibernated.
337 uint64 non_hibernated_clients = 0;
338 for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
339 it != clients_visible_mru_.end();
340 ++it) {
341 GpuMemoryManagerClientState* client_state = *it;
342 client_state->hibernated_ = false;
343 client_state->tracking_group_->hibernated_ = false;
344 non_hibernated_clients++;
345 }
346 // Then an additional few clients with surfaces are non-hibernated too, up to
347 // a fixed limit.
348 for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
349 it != clients_nonvisible_mru_.end();
350 ++it) {
351 GpuMemoryManagerClientState* client_state = *it;
352 if (non_hibernated_clients < max_surfaces_with_frontbuffer_soft_limit_) {
353 client_state->hibernated_ = false;
354 client_state->tracking_group_->hibernated_ = false;
355 non_hibernated_clients++;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000356 } else {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000357 client_state->hibernated_ = true;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000358 }
359 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000360 // Clients that don't have surfaces are non-hibernated if they are
361 // in a GL share group with a non-hibernated surface.
362 for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
363 it != clients_nonsurface_.end();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000364 ++it) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000365 GpuMemoryManagerClientState* client_state = *it;
366 client_state->hibernated_ = client_state->tracking_group_->hibernated_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000367 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000368}
369
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000370void GpuMemoryManager::SendUmaStatsToBrowser() {
371 if (!channel_manager_)
372 return;
373 GPUMemoryUmaStats params;
374 params.bytes_allocated_current = GetCurrentUsage();
375 params.bytes_allocated_max = bytes_allocated_historical_max_;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100376 params.bytes_limit = client_hard_limit_bytes_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000377 params.client_count = clients_visible_mru_.size() +
378 clients_nonvisible_mru_.size() +
379 clients_nonsurface_.size();
380 params.context_group_count = tracking_groups_.size();
381 channel_manager_->Send(new GpuHostMsg_GpuMemoryUmaStats(params));
382}
383
384GpuMemoryManager::ClientStateList* GpuMemoryManager::GetClientList(
385 GpuMemoryManagerClientState* client_state) {
386 if (client_state->has_surface_) {
387 if (client_state->visible_)
388 return &clients_visible_mru_;
389 else
390 return &clients_nonvisible_mru_;
391 }
392 return &clients_nonsurface_;
393}
394
395void GpuMemoryManager::AddClientToList(
396 GpuMemoryManagerClientState* client_state) {
397 DCHECK(!client_state->list_iterator_valid_);
398 ClientStateList* client_list = GetClientList(client_state);
399 client_state->list_iterator_ = client_list->insert(
400 client_list->begin(), client_state);
401 client_state->list_iterator_valid_ = true;
402}
403
404void GpuMemoryManager::RemoveClientFromList(
405 GpuMemoryManagerClientState* client_state) {
406 DCHECK(client_state->list_iterator_valid_);
407 ClientStateList* client_list = GetClientList(client_state);
408 client_list->erase(client_state->list_iterator_);
409 client_state->list_iterator_valid_ = false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000410}
411
412} // namespace content