15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_memory_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
1358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_handle.h"
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/gpu_channel_manager.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/gpu_memory_manager_client.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/gpu_memory_tracking.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/gpu_memory_uma_stats.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/gpu_messages.h"
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "gpu/command_buffer/common/gpu_memory_allocation.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/gpu_switches.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using gpu::MemoryAllocation;
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDelayedScheduleManageTimeoutMs = 67;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint64 kBytesAllocatedUnmanagedStep = 16 * 1024 * 1024;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TrackValueChanged(uint64 old_size, uint64 new_size, uint64* total_size) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(new_size > old_size || *total_size >= (old_size - new_size));
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *total_size += (new_size - old_size);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuMemoryManager::GpuMemoryManager(
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuChannelManager* channel_manager,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint64 max_surfaces_with_frontbuffer_soft_limit)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : channel_manager_(channel_manager),
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      manage_immediate_scheduled_(false),
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      disable_schedule_manage_(false),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_surfaces_with_frontbuffer_soft_limit_(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          max_surfaces_with_frontbuffer_soft_limit),
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      client_hard_limit_bytes_(0),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_allocated_managed_current_(0),
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_allocated_unmanaged_current_(0),
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      bytes_allocated_historical_max_(0)
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles){ }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GpuMemoryManager::~GpuMemoryManager() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(tracking_groups_.empty());
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(clients_visible_mru_.empty());
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(clients_nonvisible_mru_.empty());
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(clients_nonsurface_.empty());
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!bytes_allocated_managed_current_);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!bytes_allocated_unmanaged_current_);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::UpdateAvailableGpuMemory() {
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If the value was overridden on the command line, use the specified value.
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  static bool client_hard_limit_bytes_overridden =
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::CommandLine::ForCurrentProcess()->HasSwitch(
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          switches::kForceGpuMemAvailableMb);
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (client_hard_limit_bytes_overridden) {
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    base::StringToUint64(
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            switches::kForceGpuMemAvailableMb),
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        &client_hard_limit_bytes_);
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    client_hard_limit_bytes_ *= 1024 * 1024;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_ANDROID)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On non-Android, we use an operating system query when possible.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not have a reliable concept of multiple GPUs existing in
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a system, so just be safe and go with the minimum encountered.
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 bytes_min = 0;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only use the clients that are visible, because otherwise the set of clients
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we are querying could become extremely large.
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      it != clients_visible_mru_.end();
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++it) {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GpuMemoryManagerClientState* client_state = *it;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!client_state->has_surface_)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!client_state->visible_)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint64 bytes = 0;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (client_state->client_->GetTotalGpuMemory(&bytes)) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!bytes_min || bytes < bytes_min)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_min = bytes;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  client_hard_limit_bytes_ = bytes_min;
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Clamp the observed value to a specific range on Android.
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  client_hard_limit_bytes_ = std::max(client_hard_limit_bytes_,
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      static_cast<uint64>(16 * 1024 * 1024));
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  client_hard_limit_bytes_ = std::min(client_hard_limit_bytes_,
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      static_cast<uint64>(256 * 1024 * 1024));
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Ignore what the system said and give all clients the same maximum
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // allocation on desktop platforms.
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  client_hard_limit_bytes_ = 512 * 1024 * 1024;
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::ScheduleManage(
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScheduleManageTime schedule_manage_time) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disable_schedule_manage_)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (manage_immediate_scheduled_)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (schedule_manage_time == kScheduleManageNow) {
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE, base::Bind(&GpuMemoryManager::Manage, AsWeakPtr()));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manage_immediate_scheduled_ = true;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!delayed_manage_callback_.IsCancelled())
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delayed_manage_callback_.Cancel();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!delayed_manage_callback_.IsCancelled())
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delayed_manage_callback_.Reset(base::Bind(&GpuMemoryManager::Manage,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              AsWeakPtr()));
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE,
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        delayed_manage_callback_.callback(),
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kDelayedScheduleManageTimeoutMs));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::TrackMemoryAllocatedChange(
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryTrackingGroup* tracking_group,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint64 old_size,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint64 new_size,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gpu::gles2::MemoryTracker::Pool tracking_pool) {
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TrackValueChanged(old_size, new_size, &tracking_group->size_);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (tracking_pool) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::gles2::MemoryTracker::kManaged:
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TrackValueChanged(old_size, new_size, &bytes_allocated_managed_current_);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case gpu::gles2::MemoryTracker::kUnmanaged:
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TrackValueChanged(old_size,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        new_size,
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        &bytes_allocated_unmanaged_current_);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_size != old_size) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TRACE_COUNTER1("gpu",
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "GpuMemoryUsage",
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   GetCurrentUsage());
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (GetCurrentUsage() > bytes_allocated_historical_max_ +
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          kBytesAllocatedUnmanagedStep) {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_allocated_historical_max_ = GetCurrentUsage();
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If we're blowing into new memory usage territory, spam the browser
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // process with the most up-to-date information about our memory usage.
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendUmaStatsToBrowser();
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GpuMemoryManager::EnsureGPUMemoryAvailable(uint64 /* size_needed */) {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO: Check if there is enough space. Lose contexts until there is.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GpuMemoryManagerClientState* GpuMemoryManager::CreateClientState(
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClient* client,
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_surface,
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool visible) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TrackingGroupMap::iterator tracking_group_it =
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      tracking_groups_.find(client->GetMemoryTracker());
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(tracking_group_it != tracking_groups_.end());
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuMemoryTrackingGroup* tracking_group = tracking_group_it->second;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuMemoryManagerClientState* client_state = new GpuMemoryManagerClientState(
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this, client, tracking_group, has_surface, visible);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddClientToList(client_state);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScheduleManage(kScheduleManageNow);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_state;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::OnDestroyClientState(
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RemoveClientFromList(client_state);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScheduleManage(kScheduleManageLater);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::SetClientStateVisible(
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state, bool visible) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(client_state->has_surface_);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (client_state->visible_ == visible)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RemoveClientFromList(client_state);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_state->visible_ = visible;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddClientToList(client_state);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScheduleManage(visible ? kScheduleManageNow : kScheduleManageLater);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)uint64 GpuMemoryManager::GetClientMemoryUsage(
211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const GpuMemoryManagerClient* client) const {
212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TrackingGroupMap::const_iterator tracking_group_it =
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      tracking_groups_.find(client->GetMemoryTracker());
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(tracking_group_it != tracking_groups_.end());
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return tracking_group_it->second->GetSize();
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GpuMemoryTrackingGroup* GpuMemoryManager::CreateTrackingGroup(
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker) {
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GpuMemoryTrackingGroup* tracking_group = new GpuMemoryTrackingGroup(
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pid, memory_tracker, this);
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!tracking_groups_.count(tracking_group->GetMemoryTracker()));
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tracking_groups_.insert(std::make_pair(tracking_group->GetMemoryTracker(),
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         tracking_group));
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return tracking_group;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::OnDestroyTrackingGroup(
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GpuMemoryTrackingGroup* tracking_group) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(tracking_groups_.count(tracking_group->GetMemoryTracker()));
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tracking_groups_.erase(tracking_group->GetMemoryTracker());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuMemoryManager::GetVideoMemoryUsageStats(
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GPUVideoMemoryUsageStats* video_memory_usage_stats) const {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each context group, assign its memory usage to its PID
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  video_memory_usage_stats->process_map.clear();
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (TrackingGroupMap::const_iterator i =
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       tracking_groups_.begin(); i != tracking_groups_.end(); ++i) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GpuMemoryTrackingGroup* tracking_group = i->second;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    video_memory_usage_stats->process_map[
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tracking_group->GetPid()].video_memory += tracking_group->GetSize();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assign the total across all processes in the GPU process
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  video_memory_usage_stats->process_map[
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::GetCurrentProcId()].video_memory = GetCurrentUsage();
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  video_memory_usage_stats->process_map[
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::GetCurrentProcId()].has_duplicates = true;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  video_memory_usage_stats->bytes_allocated = GetCurrentUsage();
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  video_memory_usage_stats->bytes_allocated_historical_max =
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_allocated_historical_max_;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GpuMemoryManager::Manage() {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manage_immediate_scheduled_ = false;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delayed_manage_callback_.Cancel();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the amount of GPU memory available on the system.
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateAvailableGpuMemory();
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Determine which clients are "hibernated" (which determines the
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // distribution of frontbuffers and memory among clients that don't have
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // surfaces).
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetClientsHibernatedState();
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Assign memory allocations to clients that have surfaces.
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssignSurfacesAllocations();
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Assign memory allocations to clients that don't have surfaces.
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AssignNonSurfacesAllocations();
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendUmaStatsToBrowser();
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::AssignSurfacesAllocations() {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send that allocation to the clients.
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientStateList clients = clients_visible_mru_;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  clients.insert(clients.end(),
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 clients_nonvisible_mru_.begin(),
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 clients_nonvisible_mru_.end());
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ClientStateList::const_iterator it = clients.begin();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != clients.end();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state = *it;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Populate and send the allocation to the client
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    MemoryAllocation allocation;
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    allocation.bytes_limit_when_visible = client_hard_limit_bytes_;
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(OS_ANDROID)
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // On Android, because there is only one visible tab at any time, allow
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // that renderer to cache as much as it can.
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    allocation.priority_cutoff_when_visible =
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // On desktop platforms, instruct the renderers to cache only a smaller
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // set, to play nice with other renderers and other applications. If this
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // if not done, then the system can become unstable.
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // http://crbug.com/145600 (Linux)
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // http://crbug.com/141377 (Mac)
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    allocation.priority_cutoff_when_visible =
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_state->client_->SetMemoryAllocation(allocation);
3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    client_state->client_->SuggestHaveFrontBuffer(!client_state->hibernated_);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::AssignNonSurfacesAllocations() {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != clients_nonsurface_.end();
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state = *it;
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    MemoryAllocation allocation;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!client_state->hibernated_) {
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      allocation.bytes_limit_when_visible = client_hard_limit_bytes_;
3201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      allocation.priority_cutoff_when_visible =
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_state->client_->SetMemoryAllocation(allocation);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::SetClientsHibernatedState() const {
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Re-set all tracking groups as being hibernated.
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (TrackingGroupMap::const_iterator it = tracking_groups_.begin();
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != tracking_groups_.end();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryTrackingGroup* tracking_group = it->second;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    tracking_group->hibernated_ = true;
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // All clients with surfaces that are visible are non-hibernated.
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint64 non_hibernated_clients = 0;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != clients_visible_mru_.end();
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state = *it;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_state->hibernated_ = false;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_state->tracking_group_->hibernated_ = false;
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    non_hibernated_clients++;
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Then an additional few clients with surfaces are non-hibernated too, up to
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a fixed limit.
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != clients_nonvisible_mru_.end();
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++it) {
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state = *it;
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (non_hibernated_clients < max_surfaces_with_frontbuffer_soft_limit_) {
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_state->hibernated_ = false;
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_state->tracking_group_->hibernated_ = false;
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      non_hibernated_clients++;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_state->hibernated_ = true;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clients that don't have surfaces are non-hibernated if they are
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in a GL share group with a non-hibernated surface.
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != clients_nonsurface_.end();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state = *it;
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    client_state->hibernated_ = client_state->tracking_group_->hibernated_;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::SendUmaStatsToBrowser() {
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!channel_manager_)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GPUMemoryUmaStats params;
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.bytes_allocated_current = GetCurrentUsage();
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.bytes_allocated_max = bytes_allocated_historical_max_;
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  params.bytes_limit = client_hard_limit_bytes_;
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.client_count = clients_visible_mru_.size() +
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        clients_nonvisible_mru_.size() +
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        clients_nonsurface_.size();
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.context_group_count = tracking_groups_.size();
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  channel_manager_->Send(new GpuHostMsg_GpuMemoryUmaStats(params));
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GpuMemoryManager::ClientStateList* GpuMemoryManager::GetClientList(
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (client_state->has_surface_) {
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (client_state->visible_)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return &clients_visible_mru_;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return &clients_nonvisible_mru_;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &clients_nonsurface_;
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::AddClientToList(
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state) {
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!client_state->list_iterator_valid_);
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientStateList* client_list = GetClientList(client_state);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_state->list_iterator_ = client_list->insert(
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_list->begin(), client_state);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_state->list_iterator_valid_ = true;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GpuMemoryManager::RemoveClientFromList(
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GpuMemoryManagerClientState* client_state) {
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(client_state->list_iterator_valid_);
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientStateList* client_list = GetClientList(client_state);
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_list->erase(client_state->list_iterator_);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_state->list_iterator_valid_ = false;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
413