This source file includes following definitions.
- TrackValueChanged
- RoundUp
- RoundDown
- disable_schedule_manage_
- GetAvailableGpuMemory
- GetDefaultAvailableGpuMemory
- GetMaximumTotalGpuMemory
- GetMaximumClientAllocation
- CalcAvailableFromGpuTotal
- UpdateAvailableGpuMemory
- UpdateUnmanagedMemoryLimits
- ScheduleManage
- TrackMemoryAllocatedChange
- EnsureGPUMemoryAvailable
- CreateClientState
- OnDestroyClientState
- SetClientStateVisible
- SetClientStateManagedMemoryStats
- GetClientMemoryUsage
- CreateTrackingGroup
- OnDestroyTrackingGroup
- GetVideoMemoryUsageStats
- ComputeCap
- ComputeClientAllocationWhenVisible
- ComputeVisibleSurfacesAllocations
- DistributeRemainingMemoryToVisibleSurfaces
- AssignSurfacesAllocations
- AssignNonSurfacesAllocations
- SetClientsHibernatedState
- SendUmaStatsToBrowser
- GetClientList
- AddClientToList
- RemoveClientFromList
#include "content/common/gpu/gpu_memory_manager.h"
#include <algorithm>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_memory_manager_client.h"
#include "content/common/gpu/gpu_memory_tracking.h"
#include "content/common/gpu/gpu_memory_uma_stats.h"
#include "content/common/gpu/gpu_messages.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/service/gpu_switches.h"
using gpu::ManagedMemoryStats;
using gpu::MemoryAllocation;
namespace content {
namespace {
const int kDelayedScheduleManageTimeoutMs = 67;
const uint64 kBytesAllocatedUnmanagedStep = 16 * 1024 * 1024;
void TrackValueChanged(uint64 old_size, uint64 new_size, uint64* total_size) {
  DCHECK(new_size > old_size || *total_size >= (old_size - new_size));
  *total_size += (new_size - old_size);
}
template<typename T>
T RoundUp(T n, T mul) {
  return ((n + mul - 1) / mul) * mul;
}
template<typename T>
T RoundDown(T n, T mul) {
  return (n / mul) * mul;
}
}
GpuMemoryManager::GpuMemoryManager(
    GpuChannelManager* channel_manager,
    uint64 max_surfaces_with_frontbuffer_soft_limit)
    : channel_manager_(channel_manager),
      manage_immediate_scheduled_(false),
      max_surfaces_with_frontbuffer_soft_limit_(
          max_surfaces_with_frontbuffer_soft_limit),
      priority_cutoff_(MemoryAllocation::CUTOFF_ALLOW_EVERYTHING),
      bytes_available_gpu_memory_(0),
      bytes_available_gpu_memory_overridden_(false),
      bytes_minimum_per_client_(0),
      bytes_default_per_client_(0),
      bytes_allocated_managed_current_(0),
      bytes_allocated_unmanaged_current_(0),
      bytes_allocated_historical_max_(0),
      bytes_allocated_unmanaged_high_(0),
      bytes_allocated_unmanaged_low_(0),
      bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep),
      disable_schedule_manage_(false)
{
  CommandLine* command_line = CommandLine::ForCurrentProcess();
  
  
  
  
#if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
  priority_cutoff_ = MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
#endif
#if defined(OS_ANDROID)
  bytes_default_per_client_ = 8 * 1024 * 1024;
  bytes_minimum_per_client_ = 8 * 1024 * 1024;
#elif defined(OS_CHROMEOS)
  bytes_default_per_client_ = 64 * 1024 * 1024;
  bytes_minimum_per_client_ = 4 * 1024 * 1024;
#elif defined(OS_MACOSX)
  bytes_default_per_client_ = 128 * 1024 * 1024;
  bytes_minimum_per_client_ = 128 * 1024 * 1024;
#else
  bytes_default_per_client_ = 64 * 1024 * 1024;
  bytes_minimum_per_client_ = 64 * 1024 * 1024;
#endif
  if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) {
    base::StringToUint64(
        command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb),
        &bytes_available_gpu_memory_);
    bytes_available_gpu_memory_ *= 1024 * 1024;
    bytes_available_gpu_memory_overridden_ = true;
  } else
    bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory();
}
GpuMemoryManager::~GpuMemoryManager() {
  DCHECK(tracking_groups_.empty());
  DCHECK(clients_visible_mru_.empty());
  DCHECK(clients_nonvisible_mru_.empty());
  DCHECK(clients_nonsurface_.empty());
  DCHECK(!bytes_allocated_managed_current_);
  DCHECK(!bytes_allocated_unmanaged_current_);
}
uint64 GpuMemoryManager::GetAvailableGpuMemory() const {
  
  
  if (bytes_allocated_unmanaged_low_ > bytes_available_gpu_memory_)
    return 0;
  return bytes_available_gpu_memory_ - bytes_allocated_unmanaged_low_;
}
uint64 GpuMemoryManager::GetDefaultAvailableGpuMemory() const {
#if defined(OS_ANDROID)
  return 16 * 1024 * 1024;
#elif defined(OS_CHROMEOS)
  return 1024 * 1024 * 1024;
#else
  return 256 * 1024 * 1024;
#endif
}
uint64 GpuMemoryManager::GetMaximumTotalGpuMemory() const {
#if defined(OS_ANDROID)
  return 256 * 1024 * 1024;
#else
  return 1024 * 1024 * 1024;
#endif
}
uint64 GpuMemoryManager::GetMaximumClientAllocation() const {
#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
  return bytes_available_gpu_memory_;
#else
  
  
  
  return bytes_available_gpu_memory_ / 2;
#endif
}
uint64 GpuMemoryManager::CalcAvailableFromGpuTotal(uint64 total_gpu_memory) {
#if defined(OS_ANDROID)
  
  
  return total_gpu_memory;
#else
  
  
  return std::min(3 * total_gpu_memory / 4, total_gpu_memory - 64*1024*1024);
#endif
}
void GpuMemoryManager::UpdateAvailableGpuMemory() {
  
  
  if (bytes_available_gpu_memory_overridden_)
    return;
  
  
  
  uint64 bytes_min = 0;
  
  
  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
      it != clients_visible_mru_.end();
      ++it) {
    const GpuMemoryManagerClientState* client_state = *it;
    if (!client_state->has_surface_)
      continue;
    if (!client_state->visible_)
      continue;
    uint64 bytes = 0;
    if (client_state->client_->GetTotalGpuMemory(&bytes)) {
      if (!bytes_min || bytes < bytes_min)
        bytes_min = bytes;
    }
  }
  if (!bytes_min)
    return;
  bytes_available_gpu_memory_ = CalcAvailableFromGpuTotal(bytes_min);
  
  bytes_available_gpu_memory_ = std::max(bytes_available_gpu_memory_,
                                         GetDefaultAvailableGpuMemory());
  
  bytes_available_gpu_memory_ = std::min(bytes_available_gpu_memory_,
                                         GetMaximumTotalGpuMemory());
}
void GpuMemoryManager::UpdateUnmanagedMemoryLimits() {
  
  
  
  bytes_allocated_unmanaged_high_ = RoundUp(
      bytes_allocated_unmanaged_current_ + bytes_unmanaged_limit_step_ / 4,
      bytes_unmanaged_limit_step_);
  bytes_allocated_unmanaged_low_ = RoundDown(
      bytes_allocated_unmanaged_current_,
      bytes_unmanaged_limit_step_);
}
void GpuMemoryManager::ScheduleManage(
    ScheduleManageTime schedule_manage_time) {
  if (disable_schedule_manage_)
    return;
  if (manage_immediate_scheduled_)
    return;
  if (schedule_manage_time == kScheduleManageNow) {
    base::MessageLoop::current()->PostTask(
        FROM_HERE, base::Bind(&GpuMemoryManager::Manage, AsWeakPtr()));
    manage_immediate_scheduled_ = true;
    if (!delayed_manage_callback_.IsCancelled())
      delayed_manage_callback_.Cancel();
  } else {
    if (!delayed_manage_callback_.IsCancelled())
      return;
    delayed_manage_callback_.Reset(base::Bind(&GpuMemoryManager::Manage,
                                              AsWeakPtr()));
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        delayed_manage_callback_.callback(),
        base::TimeDelta::FromMilliseconds(kDelayedScheduleManageTimeoutMs));
  }
}
void GpuMemoryManager::TrackMemoryAllocatedChange(
    GpuMemoryTrackingGroup* tracking_group,
    uint64 old_size,
    uint64 new_size,
    gpu::gles2::MemoryTracker::Pool tracking_pool) {
  TrackValueChanged(old_size, new_size, &tracking_group->size_);
  switch (tracking_pool) {
    case gpu::gles2::MemoryTracker::kManaged:
      TrackValueChanged(old_size, new_size, &bytes_allocated_managed_current_);
      break;
    case gpu::gles2::MemoryTracker::kUnmanaged:
      TrackValueChanged(old_size,
                        new_size,
                        &bytes_allocated_unmanaged_current_);
      break;
    default:
      NOTREACHED();
      break;
  }
  if (new_size != old_size) {
    TRACE_COUNTER1("gpu",
                   "GpuMemoryUsage",
                   GetCurrentUsage());
  }
  
  
  if (bytes_allocated_unmanaged_current_ >= bytes_allocated_unmanaged_high_)
    ScheduleManage(kScheduleManageNow);
  if (bytes_allocated_unmanaged_current_ < bytes_allocated_unmanaged_low_)
    ScheduleManage(kScheduleManageLater);
  if (GetCurrentUsage() > bytes_allocated_historical_max_) {
      bytes_allocated_historical_max_ = GetCurrentUsage();
      
      
      SendUmaStatsToBrowser();
  }
}
bool GpuMemoryManager::EnsureGPUMemoryAvailable(uint64 ) {
  
  return true;
}
GpuMemoryManagerClientState* GpuMemoryManager::CreateClientState(
    GpuMemoryManagerClient* client,
    bool has_surface,
    bool visible) {
  TrackingGroupMap::iterator tracking_group_it =
      tracking_groups_.find(client->GetMemoryTracker());
  DCHECK(tracking_group_it != tracking_groups_.end());
  GpuMemoryTrackingGroup* tracking_group = tracking_group_it->second;
  GpuMemoryManagerClientState* client_state = new GpuMemoryManagerClientState(
      this, client, tracking_group, has_surface, visible);
  AddClientToList(client_state);
  ScheduleManage(kScheduleManageNow);
  return client_state;
}
void GpuMemoryManager::OnDestroyClientState(
    GpuMemoryManagerClientState* client_state) {
  RemoveClientFromList(client_state);
  ScheduleManage(kScheduleManageLater);
}
void GpuMemoryManager::SetClientStateVisible(
    GpuMemoryManagerClientState* client_state, bool visible) {
  DCHECK(client_state->has_surface_);
  if (client_state->visible_ == visible)
    return;
  RemoveClientFromList(client_state);
  client_state->visible_ = visible;
  AddClientToList(client_state);
  ScheduleManage(visible ? kScheduleManageNow : kScheduleManageLater);
}
void GpuMemoryManager::SetClientStateManagedMemoryStats(
    GpuMemoryManagerClientState* client_state,
    const ManagedMemoryStats& stats)
{
  client_state->managed_memory_stats_ = stats;
  
  
  if (!client_state->managed_memory_stats_received_) {
    client_state->managed_memory_stats_received_ = true;
    ScheduleManage(kScheduleManageNow);
    return;
  }
  
  
  if (client_state->managed_memory_stats_.bytes_nice_to_have >
      client_state->bytes_nicetohave_limit_high_) {
    ScheduleManage(kScheduleManageNow);
  } else if (client_state->managed_memory_stats_.bytes_nice_to_have <
             client_state->bytes_nicetohave_limit_low_) {
    ScheduleManage(kScheduleManageLater);
  }
}
uint64 GpuMemoryManager::GetClientMemoryUsage(
    const GpuMemoryManagerClient* client) const {
  TrackingGroupMap::const_iterator tracking_group_it =
      tracking_groups_.find(client->GetMemoryTracker());
  DCHECK(tracking_group_it != tracking_groups_.end());
  return tracking_group_it->second->GetSize();
}
GpuMemoryTrackingGroup* GpuMemoryManager::CreateTrackingGroup(
    base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker) {
  GpuMemoryTrackingGroup* tracking_group = new GpuMemoryTrackingGroup(
      pid, memory_tracker, this);
  DCHECK(!tracking_groups_.count(tracking_group->GetMemoryTracker()));
  tracking_groups_.insert(std::make_pair(tracking_group->GetMemoryTracker(),
                                         tracking_group));
  return tracking_group;
}
void GpuMemoryManager::OnDestroyTrackingGroup(
    GpuMemoryTrackingGroup* tracking_group) {
  DCHECK(tracking_groups_.count(tracking_group->GetMemoryTracker()));
  tracking_groups_.erase(tracking_group->GetMemoryTracker());
}
void GpuMemoryManager::GetVideoMemoryUsageStats(
    GPUVideoMemoryUsageStats* video_memory_usage_stats) const {
  
  video_memory_usage_stats->process_map.clear();
  for (TrackingGroupMap::const_iterator i =
       tracking_groups_.begin(); i != tracking_groups_.end(); ++i) {
    const GpuMemoryTrackingGroup* tracking_group = i->second;
    video_memory_usage_stats->process_map[
        tracking_group->GetPid()].video_memory += tracking_group->GetSize();
  }
  
  video_memory_usage_stats->process_map[
      base::GetCurrentProcId()].video_memory = GetCurrentUsage();
  video_memory_usage_stats->process_map[
      base::GetCurrentProcId()].has_duplicates = true;
  video_memory_usage_stats->bytes_allocated = GetCurrentUsage();
  video_memory_usage_stats->bytes_allocated_historical_max =
      bytes_allocated_historical_max_;
}
void GpuMemoryManager::Manage() {
  manage_immediate_scheduled_ = false;
  delayed_manage_callback_.Cancel();
  
  UpdateAvailableGpuMemory();
  
  UpdateUnmanagedMemoryLimits();
  
  
  
  SetClientsHibernatedState();
  
  AssignSurfacesAllocations();
  
  AssignNonSurfacesAllocations();
  SendUmaStatsToBrowser();
}
uint64 GpuMemoryManager::ComputeCap(
    std::vector<uint64> bytes, uint64 bytes_sum_limit)
{
  size_t bytes_size = bytes.size();
  uint64 bytes_sum = 0;
  if (bytes_size == 0)
    return std::numeric_limits<uint64>::max();
  
  std::sort(bytes.begin(), bytes.end());
  for (size_t i = 0; i < bytes_size; ++i)
    bytes_sum += bytes[i];
  
  
  uint64 bytes_partial_sum = bytes_sum;
  
  for (size_t i = 0; i < bytes_size; ++i) {
    
    uint64 test_cap = bytes[bytes_size - i - 1];
    uint64 bytes_sum_with_test_cap = i * test_cap + bytes_partial_sum;
    
    
    if (bytes_sum_with_test_cap <= bytes_sum_limit) {
      if (i == 0)
        return std::numeric_limits<uint64>::max();
      else
        return test_cap + (bytes_sum_limit - bytes_sum_with_test_cap) / i;
    } else {
      bytes_partial_sum -= test_cap;
    }
  }
  
  
  return bytes_sum_limit / bytes_size;
}
uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible(
    GpuMemoryManagerClientState* client_state,
    uint64 bytes_above_required_cap,
    uint64 bytes_above_minimum_cap,
    uint64 bytes_overall_cap) {
  ManagedMemoryStats* stats = &client_state->managed_memory_stats_;
  if (!client_state->managed_memory_stats_received_)
    return GetDefaultClientAllocation();
  uint64 bytes_required = 9 * stats->bytes_required / 8;
  bytes_required = std::min(bytes_required, GetMaximumClientAllocation());
  bytes_required = std::max(bytes_required, GetMinimumClientAllocation());
  uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3;
  bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation());
  bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation());
  bytes_nicetohave = std::max(bytes_nicetohave, bytes_required);
  uint64 allocation = GetMinimumClientAllocation();
  allocation += std::min(bytes_required - GetMinimumClientAllocation(),
                         bytes_above_minimum_cap);
  allocation += std::min(bytes_nicetohave - bytes_required,
                         bytes_above_required_cap);
  allocation = std::min(allocation,
                        bytes_overall_cap);
  return allocation;
}
void GpuMemoryManager::ComputeVisibleSurfacesAllocations() {
  uint64 bytes_available_total = GetAvailableGpuMemory();
  uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max();
  uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max();
  uint64 bytes_overall_cap_visible = GetMaximumClientAllocation();
  
  
  
  
  uint64 bytes_nicetohave_visible = 0;
  uint64 bytes_required_visible = 0;
  uint64 bytes_minimum_visible = 0;
  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
       it != clients_visible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    client_state->bytes_allocation_ideal_nicetohave_ =
        ComputeClientAllocationWhenVisible(
            client_state,
            bytes_above_required_cap,
            bytes_above_minimum_cap,
            bytes_overall_cap_visible);
    client_state->bytes_allocation_ideal_required_ =
        ComputeClientAllocationWhenVisible(
            client_state,
            0,
            bytes_above_minimum_cap,
            bytes_overall_cap_visible);
    client_state->bytes_allocation_ideal_minimum_ =
        ComputeClientAllocationWhenVisible(
            client_state,
            0,
            0,
            bytes_overall_cap_visible);
    bytes_nicetohave_visible +=
        client_state->bytes_allocation_ideal_nicetohave_;
    bytes_required_visible +=
        client_state->bytes_allocation_ideal_required_;
    bytes_minimum_visible +=
        client_state->bytes_allocation_ideal_minimum_;
  }
  
  
  
  if (bytes_minimum_visible > bytes_available_total) {
    bytes_above_required_cap = 0;
    bytes_above_minimum_cap = 0;
  } else if (bytes_required_visible > bytes_available_total) {
    std::vector<uint64> bytes_to_fit;
    for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
         it != clients_visible_mru_.end();
         ++it) {
      GpuMemoryManagerClientState* client_state = *it;
      bytes_to_fit.push_back(client_state->bytes_allocation_ideal_required_ -
                             client_state->bytes_allocation_ideal_minimum_);
    }
    bytes_above_required_cap = 0;
    bytes_above_minimum_cap = ComputeCap(
        bytes_to_fit, bytes_available_total - bytes_minimum_visible);
  } else if (bytes_nicetohave_visible > bytes_available_total) {
    std::vector<uint64> bytes_to_fit;
    for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
         it != clients_visible_mru_.end();
         ++it) {
      GpuMemoryManagerClientState* client_state = *it;
      bytes_to_fit.push_back(client_state->bytes_allocation_ideal_nicetohave_ -
                             client_state->bytes_allocation_ideal_required_);
    }
    bytes_above_required_cap = ComputeCap(
        bytes_to_fit, bytes_available_total - bytes_required_visible);
    bytes_above_minimum_cap = std::numeric_limits<uint64>::max();
  }
  
  
  
  uint64 bytes_allocated_visible = 0;
  uint64 bytes_allocated_max_client_allocation = 0;
  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
       it != clients_visible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    client_state->bytes_allocation_when_visible_ =
        ComputeClientAllocationWhenVisible(
            client_state,
            bytes_above_required_cap,
            bytes_above_minimum_cap,
            bytes_overall_cap_visible);
    bytes_allocated_visible += client_state->bytes_allocation_when_visible_;
    bytes_allocated_max_client_allocation = std::max(
        bytes_allocated_max_client_allocation,
        client_state->bytes_allocation_when_visible_);
  }
  
  
  
  
  uint64 bytes_overall_cap_nonvisible = bytes_allocated_max_client_allocation;
  if (bytes_available_total > bytes_allocated_visible) {
    bytes_overall_cap_nonvisible +=
        bytes_available_total - bytes_allocated_visible;
  }
  bytes_overall_cap_nonvisible = std::min(bytes_overall_cap_nonvisible,
                                          GetMaximumClientAllocation());
  for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
       it != clients_nonvisible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    client_state->bytes_allocation_when_visible_ =
        ComputeClientAllocationWhenVisible(
            client_state,
            bytes_above_required_cap,
            bytes_above_minimum_cap,
            bytes_overall_cap_nonvisible);
  }
}
void GpuMemoryManager::DistributeRemainingMemoryToVisibleSurfaces() {
  uint64 bytes_available_total = GetAvailableGpuMemory();
  uint64 bytes_allocated_total = 0;
  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
       it != clients_visible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    bytes_allocated_total += client_state->bytes_allocation_when_visible_;
  }
  if (bytes_allocated_total >= bytes_available_total)
    return;
  std::vector<uint64> bytes_extra_requests;
  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
       it != clients_visible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    CHECK(GetMaximumClientAllocation() >=
          client_state->bytes_allocation_when_visible_);
    uint64 bytes_extra = GetMaximumClientAllocation() -
                         client_state->bytes_allocation_when_visible_;
    bytes_extra_requests.push_back(bytes_extra);
  }
  uint64 bytes_extra_cap = ComputeCap(
      bytes_extra_requests, bytes_available_total - bytes_allocated_total);
  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
       it != clients_visible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    uint64 bytes_extra = GetMaximumClientAllocation() -
                         client_state->bytes_allocation_when_visible_;
    client_state->bytes_allocation_when_visible_ += std::min(
        bytes_extra, bytes_extra_cap);
  }
}
void GpuMemoryManager::AssignSurfacesAllocations() {
  
  ComputeVisibleSurfacesAllocations();
  
  DistributeRemainingMemoryToVisibleSurfaces();
  
  ClientStateList clients = clients_visible_mru_;
  clients.insert(clients.end(),
                 clients_nonvisible_mru_.begin(),
                 clients_nonvisible_mru_.end());
  for (ClientStateList::const_iterator it = clients.begin();
       it != clients.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    
    
    client_state->bytes_nicetohave_limit_high_ =
        5 * client_state->managed_memory_stats_.bytes_nice_to_have / 4;
    client_state->bytes_nicetohave_limit_low_ =
        3 * client_state->managed_memory_stats_.bytes_nice_to_have / 4;
    
    MemoryAllocation allocation;
    allocation.bytes_limit_when_visible =
        client_state->bytes_allocation_when_visible_;
    allocation.priority_cutoff_when_visible = priority_cutoff_;
    client_state->client_->SetMemoryAllocation(allocation);
    client_state->client_->SuggestHaveFrontBuffer(!client_state->hibernated_);
  }
}
void GpuMemoryManager::AssignNonSurfacesAllocations() {
  for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
       it != clients_nonsurface_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    MemoryAllocation allocation;
    if (!client_state->hibernated_) {
      allocation.bytes_limit_when_visible =
          GetMinimumClientAllocation();
      allocation.priority_cutoff_when_visible =
          MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
    }
    client_state->client_->SetMemoryAllocation(allocation);
  }
}
void GpuMemoryManager::SetClientsHibernatedState() const {
  
  for (TrackingGroupMap::const_iterator it = tracking_groups_.begin();
       it != tracking_groups_.end();
       ++it) {
    GpuMemoryTrackingGroup* tracking_group = it->second;
    tracking_group->hibernated_ = true;
  }
  
  uint64 non_hibernated_clients = 0;
  for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
       it != clients_visible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    client_state->hibernated_ = false;
    client_state->tracking_group_->hibernated_ = false;
    non_hibernated_clients++;
  }
  
  
  for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
       it != clients_nonvisible_mru_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    if (non_hibernated_clients < max_surfaces_with_frontbuffer_soft_limit_) {
      client_state->hibernated_ = false;
      client_state->tracking_group_->hibernated_ = false;
      non_hibernated_clients++;
    } else {
      client_state->hibernated_ = true;
    }
  }
  
  
  for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
       it != clients_nonsurface_.end();
       ++it) {
    GpuMemoryManagerClientState* client_state = *it;
    client_state->hibernated_ = client_state->tracking_group_->hibernated_;
  }
}
void GpuMemoryManager::SendUmaStatsToBrowser() {
  if (!channel_manager_)
    return;
  GPUMemoryUmaStats params;
  params.bytes_allocated_current = GetCurrentUsage();
  params.bytes_allocated_max = bytes_allocated_historical_max_;
  params.bytes_limit = bytes_available_gpu_memory_;
  params.client_count = clients_visible_mru_.size() +
                        clients_nonvisible_mru_.size() +
                        clients_nonsurface_.size();
  params.context_group_count = tracking_groups_.size();
  channel_manager_->Send(new GpuHostMsg_GpuMemoryUmaStats(params));
}
GpuMemoryManager::ClientStateList* GpuMemoryManager::GetClientList(
    GpuMemoryManagerClientState* client_state) {
  if (client_state->has_surface_) {
    if (client_state->visible_)
      return &clients_visible_mru_;
    else
      return &clients_nonvisible_mru_;
  }
  return &clients_nonsurface_;
}
void GpuMemoryManager::AddClientToList(
    GpuMemoryManagerClientState* client_state) {
  DCHECK(!client_state->list_iterator_valid_);
  ClientStateList* client_list = GetClientList(client_state);
  client_state->list_iterator_ = client_list->insert(
      client_list->begin(), client_state);
  client_state->list_iterator_valid_ = true;
}
void GpuMemoryManager::RemoveClientFromList(
    GpuMemoryManagerClientState* client_state) {
  DCHECK(client_state->list_iterator_valid_);
  ClientStateList* client_list = GetClientList(client_state);
  client_list->erase(client_state->list_iterator_);
  client_state->list_iterator_valid_ = false;
}
}