Home | History | Annotate | Download | only in gpu
      1 // 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 
      7 #include <algorithm>
      8 
      9 #include "base/bind.h"
     10 #include "base/command_line.h"
     11 #include "base/debug/trace_event.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/process/process_handle.h"
     14 #include "base/strings/string_number_conversions.h"
     15 #include "content/common/gpu/gpu_channel_manager.h"
     16 #include "content/common/gpu/gpu_memory_manager_client.h"
     17 #include "content/common/gpu/gpu_memory_tracking.h"
     18 #include "content/common/gpu/gpu_memory_uma_stats.h"
     19 #include "content/common/gpu/gpu_messages.h"
     20 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
     21 #include "gpu/command_buffer/service/gpu_switches.h"
     22 
     23 using gpu::ManagedMemoryStats;
     24 using gpu::MemoryAllocation;
     25 
     26 namespace content {
     27 namespace {
     28 
     29 const int kDelayedScheduleManageTimeoutMs = 67;
     30 
     31 const uint64 kBytesAllocatedUnmanagedStep = 16 * 1024 * 1024;
     32 
     33 void TrackValueChanged(uint64 old_size, uint64 new_size, uint64* total_size) {
     34   DCHECK(new_size > old_size || *total_size >= (old_size - new_size));
     35   *total_size += (new_size - old_size);
     36 }
     37 
     38 template<typename T>
     39 T RoundUp(T n, T mul) {
     40   return ((n + mul - 1) / mul) * mul;
     41 }
     42 
     43 template<typename T>
     44 T RoundDown(T n, T mul) {
     45   return (n / mul) * mul;
     46 }
     47 
     48 }
     49 
     50 GpuMemoryManager::GpuMemoryManager(
     51     GpuChannelManager* channel_manager,
     52     uint64 max_surfaces_with_frontbuffer_soft_limit)
     53     : channel_manager_(channel_manager),
     54       manage_immediate_scheduled_(false),
     55       max_surfaces_with_frontbuffer_soft_limit_(
     56           max_surfaces_with_frontbuffer_soft_limit),
     57       priority_cutoff_(MemoryAllocation::CUTOFF_ALLOW_EVERYTHING),
     58       bytes_available_gpu_memory_(0),
     59       bytes_available_gpu_memory_overridden_(false),
     60       bytes_minimum_per_client_(0),
     61       bytes_default_per_client_(0),
     62       bytes_allocated_managed_current_(0),
     63       bytes_allocated_unmanaged_current_(0),
     64       bytes_allocated_historical_max_(0),
     65       bytes_allocated_unmanaged_high_(0),
     66       bytes_allocated_unmanaged_low_(0),
     67       bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep),
     68       disable_schedule_manage_(false)
     69 {
     70   CommandLine* command_line = CommandLine::ForCurrentProcess();
     71 
     72   // Use a more conservative memory allocation policy on Linux and Mac because
     73   // the platform is unstable when under memory pressure.
     74   // http://crbug.com/145600 (Linux)
     75   // http://crbug.com/141377 (Mac)
     76 #if defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
     77   priority_cutoff_ = MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
     78 #endif
     79 
     80 #if defined(OS_ANDROID)
     81   bytes_default_per_client_ = 8 * 1024 * 1024;
     82   bytes_minimum_per_client_ = 8 * 1024 * 1024;
     83 #elif defined(OS_CHROMEOS)
     84   bytes_default_per_client_ = 64 * 1024 * 1024;
     85   bytes_minimum_per_client_ = 4 * 1024 * 1024;
     86 #elif defined(OS_MACOSX)
     87   bytes_default_per_client_ = 128 * 1024 * 1024;
     88   bytes_minimum_per_client_ = 128 * 1024 * 1024;
     89 #else
     90   bytes_default_per_client_ = 64 * 1024 * 1024;
     91   bytes_minimum_per_client_ = 64 * 1024 * 1024;
     92 #endif
     93 
     94   if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) {
     95     base::StringToUint64(
     96         command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb),
     97         &bytes_available_gpu_memory_);
     98     bytes_available_gpu_memory_ *= 1024 * 1024;
     99     bytes_available_gpu_memory_overridden_ = true;
    100   } else
    101     bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory();
    102 }
    103 
    104 GpuMemoryManager::~GpuMemoryManager() {
    105   DCHECK(tracking_groups_.empty());
    106   DCHECK(clients_visible_mru_.empty());
    107   DCHECK(clients_nonvisible_mru_.empty());
    108   DCHECK(clients_nonsurface_.empty());
    109   DCHECK(!bytes_allocated_managed_current_);
    110   DCHECK(!bytes_allocated_unmanaged_current_);
    111 }
    112 
    113 uint64 GpuMemoryManager::GetAvailableGpuMemory() const {
    114   // Allow unmanaged allocations to over-subscribe by at most (high_ - low_)
    115   // before restricting managed (compositor) memory based on unmanaged usage.
    116   if (bytes_allocated_unmanaged_low_ > bytes_available_gpu_memory_)
    117     return 0;
    118   return bytes_available_gpu_memory_ - bytes_allocated_unmanaged_low_;
    119 }
    120 
    121 uint64 GpuMemoryManager::GetDefaultAvailableGpuMemory() const {
    122 #if defined(OS_ANDROID)
    123   return 16 * 1024 * 1024;
    124 #elif defined(OS_CHROMEOS)
    125   return 1024 * 1024 * 1024;
    126 #else
    127   return 256 * 1024 * 1024;
    128 #endif
    129 }
    130 
    131 uint64 GpuMemoryManager::GetMaximumTotalGpuMemory() const {
    132 #if defined(OS_ANDROID)
    133   return 256 * 1024 * 1024;
    134 #else
    135   return 1024 * 1024 * 1024;
    136 #endif
    137 }
    138 
    139 uint64 GpuMemoryManager::GetMaximumClientAllocation() const {
    140 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
    141   return bytes_available_gpu_memory_;
    142 #else
    143   // This is to avoid allowing a single page on to use a full 256MB of memory
    144   // (the current total limit). Long-scroll pages will hit this limit,
    145   // resulting in instability on some platforms (e.g, issue 141377).
    146   return bytes_available_gpu_memory_ / 2;
    147 #endif
    148 }
    149 
    150 uint64 GpuMemoryManager::CalcAvailableFromGpuTotal(uint64 total_gpu_memory) {
    151 #if defined(OS_ANDROID)
    152   // We don't need to reduce the total on Android, since
    153   // the total is an estimate to begin with.
    154   return total_gpu_memory;
    155 #else
    156   // Allow Chrome to use 75% of total GPU memory, or all-but-64MB of GPU
    157   // memory, whichever is less.
    158   return std::min(3 * total_gpu_memory / 4, total_gpu_memory - 64*1024*1024);
    159 #endif
    160 }
    161 
    162 void GpuMemoryManager::UpdateAvailableGpuMemory() {
    163   // If the amount of video memory to use was specified at the command
    164   // line, never change it.
    165   if (bytes_available_gpu_memory_overridden_)
    166     return;
    167 
    168   // On non-Android, we use an operating system query when possible.
    169   // We do not have a reliable concept of multiple GPUs existing in
    170   // a system, so just be safe and go with the minimum encountered.
    171   uint64 bytes_min = 0;
    172 
    173   // Only use the clients that are visible, because otherwise the set of clients
    174   // we are querying could become extremely large.
    175   for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    176       it != clients_visible_mru_.end();
    177       ++it) {
    178     const GpuMemoryManagerClientState* client_state = *it;
    179     if (!client_state->has_surface_)
    180       continue;
    181     if (!client_state->visible_)
    182       continue;
    183 
    184     uint64 bytes = 0;
    185     if (client_state->client_->GetTotalGpuMemory(&bytes)) {
    186       if (!bytes_min || bytes < bytes_min)
    187         bytes_min = bytes;
    188     }
    189   }
    190 
    191   if (!bytes_min)
    192     return;
    193 
    194   bytes_available_gpu_memory_ = CalcAvailableFromGpuTotal(bytes_min);
    195 
    196   // Never go below the default allocation
    197   bytes_available_gpu_memory_ = std::max(bytes_available_gpu_memory_,
    198                                          GetDefaultAvailableGpuMemory());
    199 
    200   // Never go above the maximum.
    201   bytes_available_gpu_memory_ = std::min(bytes_available_gpu_memory_,
    202                                          GetMaximumTotalGpuMemory());
    203 }
    204 
    205 void GpuMemoryManager::UpdateUnmanagedMemoryLimits() {
    206   // Set the limit to be [current_, current_ + step_ / 4), with the endpoints
    207   // of the intervals rounded down and up to the nearest step_, to avoid
    208   // thrashing the interval.
    209   bytes_allocated_unmanaged_high_ = RoundUp(
    210       bytes_allocated_unmanaged_current_ + bytes_unmanaged_limit_step_ / 4,
    211       bytes_unmanaged_limit_step_);
    212   bytes_allocated_unmanaged_low_ = RoundDown(
    213       bytes_allocated_unmanaged_current_,
    214       bytes_unmanaged_limit_step_);
    215 }
    216 
    217 void GpuMemoryManager::ScheduleManage(
    218     ScheduleManageTime schedule_manage_time) {
    219   if (disable_schedule_manage_)
    220     return;
    221   if (manage_immediate_scheduled_)
    222     return;
    223   if (schedule_manage_time == kScheduleManageNow) {
    224     base::MessageLoop::current()->PostTask(
    225         FROM_HERE, base::Bind(&GpuMemoryManager::Manage, AsWeakPtr()));
    226     manage_immediate_scheduled_ = true;
    227     if (!delayed_manage_callback_.IsCancelled())
    228       delayed_manage_callback_.Cancel();
    229   } else {
    230     if (!delayed_manage_callback_.IsCancelled())
    231       return;
    232     delayed_manage_callback_.Reset(base::Bind(&GpuMemoryManager::Manage,
    233                                               AsWeakPtr()));
    234     base::MessageLoop::current()->PostDelayedTask(
    235         FROM_HERE,
    236         delayed_manage_callback_.callback(),
    237         base::TimeDelta::FromMilliseconds(kDelayedScheduleManageTimeoutMs));
    238   }
    239 }
    240 
    241 void GpuMemoryManager::TrackMemoryAllocatedChange(
    242     GpuMemoryTrackingGroup* tracking_group,
    243     uint64 old_size,
    244     uint64 new_size,
    245     gpu::gles2::MemoryTracker::Pool tracking_pool) {
    246   TrackValueChanged(old_size, new_size, &tracking_group->size_);
    247   switch (tracking_pool) {
    248     case gpu::gles2::MemoryTracker::kManaged:
    249       TrackValueChanged(old_size, new_size, &bytes_allocated_managed_current_);
    250       break;
    251     case gpu::gles2::MemoryTracker::kUnmanaged:
    252       TrackValueChanged(old_size,
    253                         new_size,
    254                         &bytes_allocated_unmanaged_current_);
    255       break;
    256     default:
    257       NOTREACHED();
    258       break;
    259   }
    260   if (new_size != old_size) {
    261     TRACE_COUNTER1("gpu",
    262                    "GpuMemoryUsage",
    263                    GetCurrentUsage());
    264   }
    265 
    266   // If we've gone past our current limit on unmanaged memory, schedule a
    267   // re-manage to take int account the unmanaged memory.
    268   if (bytes_allocated_unmanaged_current_ >= bytes_allocated_unmanaged_high_)
    269     ScheduleManage(kScheduleManageNow);
    270   if (bytes_allocated_unmanaged_current_ < bytes_allocated_unmanaged_low_)
    271     ScheduleManage(kScheduleManageLater);
    272 
    273   if (GetCurrentUsage() > bytes_allocated_historical_max_) {
    274       bytes_allocated_historical_max_ = GetCurrentUsage();
    275       // If we're blowing into new memory usage territory, spam the browser
    276       // process with the most up-to-date information about our memory usage.
    277       SendUmaStatsToBrowser();
    278   }
    279 }
    280 
    281 bool GpuMemoryManager::EnsureGPUMemoryAvailable(uint64 /* size_needed */) {
    282   // TODO: Check if there is enough space. Lose contexts until there is.
    283   return true;
    284 }
    285 
    286 GpuMemoryManagerClientState* GpuMemoryManager::CreateClientState(
    287     GpuMemoryManagerClient* client,
    288     bool has_surface,
    289     bool visible) {
    290   TrackingGroupMap::iterator tracking_group_it =
    291       tracking_groups_.find(client->GetMemoryTracker());
    292   DCHECK(tracking_group_it != tracking_groups_.end());
    293   GpuMemoryTrackingGroup* tracking_group = tracking_group_it->second;
    294 
    295   GpuMemoryManagerClientState* client_state = new GpuMemoryManagerClientState(
    296       this, client, tracking_group, has_surface, visible);
    297   AddClientToList(client_state);
    298   ScheduleManage(kScheduleManageNow);
    299   return client_state;
    300 }
    301 
    302 void GpuMemoryManager::OnDestroyClientState(
    303     GpuMemoryManagerClientState* client_state) {
    304   RemoveClientFromList(client_state);
    305   ScheduleManage(kScheduleManageLater);
    306 }
    307 
    308 void GpuMemoryManager::SetClientStateVisible(
    309     GpuMemoryManagerClientState* client_state, bool visible) {
    310   DCHECK(client_state->has_surface_);
    311   if (client_state->visible_ == visible)
    312     return;
    313 
    314   RemoveClientFromList(client_state);
    315   client_state->visible_ = visible;
    316   AddClientToList(client_state);
    317   ScheduleManage(visible ? kScheduleManageNow : kScheduleManageLater);
    318 }
    319 
    320 void GpuMemoryManager::SetClientStateManagedMemoryStats(
    321     GpuMemoryManagerClientState* client_state,
    322     const ManagedMemoryStats& stats)
    323 {
    324   client_state->managed_memory_stats_ = stats;
    325 
    326   // If this is the first time that stats have been received for this
    327   // client, use them immediately.
    328   if (!client_state->managed_memory_stats_received_) {
    329     client_state->managed_memory_stats_received_ = true;
    330     ScheduleManage(kScheduleManageNow);
    331     return;
    332   }
    333 
    334   // If these statistics sit outside of the range that we used in our
    335   // computation of memory allocations then recompute the allocations.
    336   if (client_state->managed_memory_stats_.bytes_nice_to_have >
    337       client_state->bytes_nicetohave_limit_high_) {
    338     ScheduleManage(kScheduleManageNow);
    339   } else if (client_state->managed_memory_stats_.bytes_nice_to_have <
    340              client_state->bytes_nicetohave_limit_low_) {
    341     ScheduleManage(kScheduleManageLater);
    342   }
    343 }
    344 
    345 uint64 GpuMemoryManager::GetClientMemoryUsage(
    346     const GpuMemoryManagerClient* client) const{
    347   TrackingGroupMap::const_iterator tracking_group_it =
    348       tracking_groups_.find(client->GetMemoryTracker());
    349   DCHECK(tracking_group_it != tracking_groups_.end());
    350   return tracking_group_it->second->GetSize();
    351 }
    352 
    353 GpuMemoryTrackingGroup* GpuMemoryManager::CreateTrackingGroup(
    354     base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker) {
    355   GpuMemoryTrackingGroup* tracking_group = new GpuMemoryTrackingGroup(
    356       pid, memory_tracker, this);
    357   DCHECK(!tracking_groups_.count(tracking_group->GetMemoryTracker()));
    358   tracking_groups_.insert(std::make_pair(tracking_group->GetMemoryTracker(),
    359                                          tracking_group));
    360   return tracking_group;
    361 }
    362 
    363 void GpuMemoryManager::OnDestroyTrackingGroup(
    364     GpuMemoryTrackingGroup* tracking_group) {
    365   DCHECK(tracking_groups_.count(tracking_group->GetMemoryTracker()));
    366   tracking_groups_.erase(tracking_group->GetMemoryTracker());
    367 }
    368 
    369 void GpuMemoryManager::GetVideoMemoryUsageStats(
    370     GPUVideoMemoryUsageStats* video_memory_usage_stats) const {
    371   // For each context group, assign its memory usage to its PID
    372   video_memory_usage_stats->process_map.clear();
    373   for (TrackingGroupMap::const_iterator i =
    374        tracking_groups_.begin(); i != tracking_groups_.end(); ++i) {
    375     const GpuMemoryTrackingGroup* tracking_group = i->second;
    376     video_memory_usage_stats->process_map[
    377         tracking_group->GetPid()].video_memory += tracking_group->GetSize();
    378   }
    379 
    380   // Assign the total across all processes in the GPU process
    381   video_memory_usage_stats->process_map[
    382       base::GetCurrentProcId()].video_memory = GetCurrentUsage();
    383   video_memory_usage_stats->process_map[
    384       base::GetCurrentProcId()].has_duplicates = true;
    385 
    386   video_memory_usage_stats->bytes_allocated = GetCurrentUsage();
    387   video_memory_usage_stats->bytes_allocated_historical_max =
    388       bytes_allocated_historical_max_;
    389 }
    390 
    391 void GpuMemoryManager::Manage() {
    392   manage_immediate_scheduled_ = false;
    393   delayed_manage_callback_.Cancel();
    394 
    395   // Update the amount of GPU memory available on the system.
    396   UpdateAvailableGpuMemory();
    397 
    398   // Update the limit on unmanaged memory.
    399   UpdateUnmanagedMemoryLimits();
    400 
    401   // Determine which clients are "hibernated" (which determines the
    402   // distribution of frontbuffers and memory among clients that don't have
    403   // surfaces).
    404   SetClientsHibernatedState();
    405 
    406   // Assign memory allocations to clients that have surfaces.
    407   AssignSurfacesAllocations();
    408 
    409   // Assign memory allocations to clients that don't have surfaces.
    410   AssignNonSurfacesAllocations();
    411 
    412   SendUmaStatsToBrowser();
    413 }
    414 
    415 // static
    416 uint64 GpuMemoryManager::ComputeCap(
    417     std::vector<uint64> bytes, uint64 bytes_sum_limit)
    418 {
    419   size_t bytes_size = bytes.size();
    420   uint64 bytes_sum = 0;
    421 
    422   if (bytes_size == 0)
    423     return std::numeric_limits<uint64>::max();
    424 
    425   // Sort and add up all entries
    426   std::sort(bytes.begin(), bytes.end());
    427   for (size_t i = 0; i < bytes_size; ++i)
    428     bytes_sum += bytes[i];
    429 
    430   // As we go through the below loop, let bytes_partial_sum be the
    431   // sum of bytes[0] + ... + bytes[bytes_size - i - 1]
    432   uint64 bytes_partial_sum = bytes_sum;
    433 
    434   // Try using each entry as a cap, and see where we get cut off.
    435   for (size_t i = 0; i < bytes_size; ++i) {
    436     // Try limiting cap to bytes[bytes_size - i - 1]
    437     uint64 test_cap = bytes[bytes_size - i - 1];
    438     uint64 bytes_sum_with_test_cap = i * test_cap + bytes_partial_sum;
    439 
    440     // If that fits, raise test_cap to give an even distribution to the
    441     // last i entries.
    442     if (bytes_sum_with_test_cap <= bytes_sum_limit) {
    443       if (i == 0)
    444         return std::numeric_limits<uint64>::max();
    445       else
    446         return test_cap + (bytes_sum_limit - bytes_sum_with_test_cap) / i;
    447     } else {
    448       bytes_partial_sum -= test_cap;
    449     }
    450   }
    451 
    452   // If we got here, then we can't fully accommodate any of the clients,
    453   // so distribute bytes_sum_limit evenly.
    454   return bytes_sum_limit / bytes_size;
    455 }
    456 
    457 uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible(
    458     GpuMemoryManagerClientState* client_state,
    459     uint64 bytes_above_required_cap,
    460     uint64 bytes_above_minimum_cap,
    461     uint64 bytes_overall_cap) {
    462   ManagedMemoryStats* stats = &client_state->managed_memory_stats_;
    463 
    464   if (!client_state->managed_memory_stats_received_)
    465     return GetDefaultClientAllocation();
    466 
    467   uint64 bytes_required = 9 * stats->bytes_required / 8;
    468   bytes_required = std::min(bytes_required, GetMaximumClientAllocation());
    469   bytes_required = std::max(bytes_required, GetMinimumClientAllocation());
    470 
    471   uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3;
    472   bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation());
    473   bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation());
    474   bytes_nicetohave = std::max(bytes_nicetohave, bytes_required);
    475 
    476   uint64 allocation = GetMinimumClientAllocation();
    477   allocation += std::min(bytes_required - GetMinimumClientAllocation(),
    478                          bytes_above_minimum_cap);
    479   allocation += std::min(bytes_nicetohave - bytes_required,
    480                          bytes_above_required_cap);
    481   allocation = std::min(allocation,
    482                         bytes_overall_cap);
    483   return allocation;
    484 }
    485 
    486 void GpuMemoryManager::ComputeVisibleSurfacesAllocations() {
    487   uint64 bytes_available_total = GetAvailableGpuMemory();
    488   uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max();
    489   uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max();
    490   uint64 bytes_overall_cap_visible = GetMaximumClientAllocation();
    491 
    492   // Compute memory usage at three levels
    493   // - painting everything that is nicetohave for visible clients
    494   // - painting only what that is visible
    495   // - giving every client the minimum allocation
    496   uint64 bytes_nicetohave_visible = 0;
    497   uint64 bytes_required_visible = 0;
    498   uint64 bytes_minimum_visible = 0;
    499   for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    500        it != clients_visible_mru_.end();
    501        ++it) {
    502     GpuMemoryManagerClientState* client_state = *it;
    503     client_state->bytes_allocation_ideal_nicetohave_ =
    504         ComputeClientAllocationWhenVisible(
    505             client_state,
    506             bytes_above_required_cap,
    507             bytes_above_minimum_cap,
    508             bytes_overall_cap_visible);
    509     client_state->bytes_allocation_ideal_required_ =
    510         ComputeClientAllocationWhenVisible(
    511             client_state,
    512             0,
    513             bytes_above_minimum_cap,
    514             bytes_overall_cap_visible);
    515     client_state->bytes_allocation_ideal_minimum_ =
    516         ComputeClientAllocationWhenVisible(
    517             client_state,
    518             0,
    519             0,
    520             bytes_overall_cap_visible);
    521 
    522     bytes_nicetohave_visible +=
    523         client_state->bytes_allocation_ideal_nicetohave_;
    524     bytes_required_visible +=
    525         client_state->bytes_allocation_ideal_required_;
    526     bytes_minimum_visible +=
    527         client_state->bytes_allocation_ideal_minimum_;
    528   }
    529 
    530   // Determine which of those three points we can satisfy, and limit
    531   // bytes_above_required_cap and bytes_above_minimum_cap to not go
    532   // over the limit.
    533   if (bytes_minimum_visible > bytes_available_total) {
    534     bytes_above_required_cap = 0;
    535     bytes_above_minimum_cap = 0;
    536   } else if (bytes_required_visible > bytes_available_total) {
    537     std::vector<uint64> bytes_to_fit;
    538     for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    539          it != clients_visible_mru_.end();
    540          ++it) {
    541       GpuMemoryManagerClientState* client_state = *it;
    542       bytes_to_fit.push_back(client_state->bytes_allocation_ideal_required_ -
    543                              client_state->bytes_allocation_ideal_minimum_);
    544     }
    545     bytes_above_required_cap = 0;
    546     bytes_above_minimum_cap = ComputeCap(
    547         bytes_to_fit, bytes_available_total - bytes_minimum_visible);
    548   } else if (bytes_nicetohave_visible > bytes_available_total) {
    549     std::vector<uint64> bytes_to_fit;
    550     for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    551          it != clients_visible_mru_.end();
    552          ++it) {
    553       GpuMemoryManagerClientState* client_state = *it;
    554       bytes_to_fit.push_back(client_state->bytes_allocation_ideal_nicetohave_ -
    555                              client_state->bytes_allocation_ideal_required_);
    556     }
    557     bytes_above_required_cap = ComputeCap(
    558         bytes_to_fit, bytes_available_total - bytes_required_visible);
    559     bytes_above_minimum_cap = std::numeric_limits<uint64>::max();
    560   }
    561 
    562   // Given those computed limits, set the actual memory allocations for the
    563   // visible clients, tracking the largest allocation and the total allocation
    564   // for future use.
    565   uint64 bytes_allocated_visible = 0;
    566   uint64 bytes_allocated_max_client_allocation = 0;
    567   for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    568        it != clients_visible_mru_.end();
    569        ++it) {
    570     GpuMemoryManagerClientState* client_state = *it;
    571     client_state->bytes_allocation_when_visible_ =
    572         ComputeClientAllocationWhenVisible(
    573             client_state,
    574             bytes_above_required_cap,
    575             bytes_above_minimum_cap,
    576             bytes_overall_cap_visible);
    577     bytes_allocated_visible += client_state->bytes_allocation_when_visible_;
    578     bytes_allocated_max_client_allocation = std::max(
    579         bytes_allocated_max_client_allocation,
    580         client_state->bytes_allocation_when_visible_);
    581   }
    582 
    583   // Set the limit for nonvisible clients for when they become visible.
    584   // Use the same formula, with a lowered overall cap in case any of the
    585   // currently-nonvisible clients are much more resource-intensive than any
    586   // of the existing clients.
    587   uint64 bytes_overall_cap_nonvisible = bytes_allocated_max_client_allocation;
    588   if (bytes_available_total > bytes_allocated_visible) {
    589     bytes_overall_cap_nonvisible +=
    590         bytes_available_total - bytes_allocated_visible;
    591   }
    592   bytes_overall_cap_nonvisible = std::min(bytes_overall_cap_nonvisible,
    593                                           GetMaximumClientAllocation());
    594   for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
    595        it != clients_nonvisible_mru_.end();
    596        ++it) {
    597     GpuMemoryManagerClientState* client_state = *it;
    598     client_state->bytes_allocation_when_visible_ =
    599         ComputeClientAllocationWhenVisible(
    600             client_state,
    601             bytes_above_required_cap,
    602             bytes_above_minimum_cap,
    603             bytes_overall_cap_nonvisible);
    604   }
    605 }
    606 
    607 void GpuMemoryManager::DistributeRemainingMemoryToVisibleSurfaces() {
    608   uint64 bytes_available_total = GetAvailableGpuMemory();
    609   uint64 bytes_allocated_total = 0;
    610 
    611   for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    612        it != clients_visible_mru_.end();
    613        ++it) {
    614     GpuMemoryManagerClientState* client_state = *it;
    615     bytes_allocated_total += client_state->bytes_allocation_when_visible_;
    616   }
    617 
    618   if (bytes_allocated_total >= bytes_available_total)
    619     return;
    620 
    621   std::vector<uint64> bytes_extra_requests;
    622   for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    623        it != clients_visible_mru_.end();
    624        ++it) {
    625     GpuMemoryManagerClientState* client_state = *it;
    626     CHECK(GetMaximumClientAllocation() >=
    627           client_state->bytes_allocation_when_visible_);
    628     uint64 bytes_extra = GetMaximumClientAllocation() -
    629                          client_state->bytes_allocation_when_visible_;
    630     bytes_extra_requests.push_back(bytes_extra);
    631   }
    632   uint64 bytes_extra_cap = ComputeCap(
    633       bytes_extra_requests, bytes_available_total - bytes_allocated_total);
    634   for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    635        it != clients_visible_mru_.end();
    636        ++it) {
    637     GpuMemoryManagerClientState* client_state = *it;
    638     uint64 bytes_extra = GetMaximumClientAllocation() -
    639                          client_state->bytes_allocation_when_visible_;
    640     client_state->bytes_allocation_when_visible_ += std::min(
    641         bytes_extra, bytes_extra_cap);
    642   }
    643 }
    644 
    645 void GpuMemoryManager::AssignSurfacesAllocations() {
    646   // Compute allocation when for all clients.
    647   ComputeVisibleSurfacesAllocations();
    648 
    649   // Distribute the remaining memory to visible clients.
    650   DistributeRemainingMemoryToVisibleSurfaces();
    651 
    652   // Send that allocation to the clients.
    653   ClientStateList clients = clients_visible_mru_;
    654   clients.insert(clients.end(),
    655                  clients_nonvisible_mru_.begin(),
    656                  clients_nonvisible_mru_.end());
    657   for (ClientStateList::const_iterator it = clients.begin();
    658        it != clients.end();
    659        ++it) {
    660     GpuMemoryManagerClientState* client_state = *it;
    661 
    662     // Re-assign memory limits to this client when its "nice to have" bucket
    663     // grows or shrinks by 1/4.
    664     client_state->bytes_nicetohave_limit_high_ =
    665         5 * client_state->managed_memory_stats_.bytes_nice_to_have / 4;
    666     client_state->bytes_nicetohave_limit_low_ =
    667         3 * client_state->managed_memory_stats_.bytes_nice_to_have / 4;
    668 
    669     // Populate and send the allocation to the client
    670     MemoryAllocation allocation;
    671 
    672     allocation.bytes_limit_when_visible =
    673         client_state->bytes_allocation_when_visible_;
    674     allocation.priority_cutoff_when_visible = priority_cutoff_;
    675 
    676     client_state->client_->SetMemoryAllocation(allocation);
    677     client_state->client_->SuggestHaveFrontBuffer(!client_state->hibernated_);
    678   }
    679 }
    680 
    681 void GpuMemoryManager::AssignNonSurfacesAllocations() {
    682   for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
    683        it != clients_nonsurface_.end();
    684        ++it) {
    685     GpuMemoryManagerClientState* client_state = *it;
    686     MemoryAllocation allocation;
    687 
    688     if (!client_state->hibernated_) {
    689       allocation.bytes_limit_when_visible =
    690           GetMinimumClientAllocation();
    691       allocation.priority_cutoff_when_visible =
    692           MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
    693     }
    694 
    695     client_state->client_->SetMemoryAllocation(allocation);
    696   }
    697 }
    698 
    699 void GpuMemoryManager::SetClientsHibernatedState() const {
    700   // Re-set all tracking groups as being hibernated.
    701   for (TrackingGroupMap::const_iterator it = tracking_groups_.begin();
    702        it != tracking_groups_.end();
    703        ++it) {
    704     GpuMemoryTrackingGroup* tracking_group = it->second;
    705     tracking_group->hibernated_ = true;
    706   }
    707   // All clients with surfaces that are visible are non-hibernated.
    708   uint64 non_hibernated_clients = 0;
    709   for (ClientStateList::const_iterator it = clients_visible_mru_.begin();
    710        it != clients_visible_mru_.end();
    711        ++it) {
    712     GpuMemoryManagerClientState* client_state = *it;
    713     client_state->hibernated_ = false;
    714     client_state->tracking_group_->hibernated_ = false;
    715     non_hibernated_clients++;
    716   }
    717   // Then an additional few clients with surfaces are non-hibernated too, up to
    718   // a fixed limit.
    719   for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin();
    720        it != clients_nonvisible_mru_.end();
    721        ++it) {
    722     GpuMemoryManagerClientState* client_state = *it;
    723     if (non_hibernated_clients < max_surfaces_with_frontbuffer_soft_limit_) {
    724       client_state->hibernated_ = false;
    725       client_state->tracking_group_->hibernated_ = false;
    726       non_hibernated_clients++;
    727     } else {
    728       client_state->hibernated_ = true;
    729     }
    730   }
    731   // Clients that don't have surfaces are non-hibernated if they are
    732   // in a GL share group with a non-hibernated surface.
    733   for (ClientStateList::const_iterator it = clients_nonsurface_.begin();
    734        it != clients_nonsurface_.end();
    735        ++it) {
    736     GpuMemoryManagerClientState* client_state = *it;
    737     client_state->hibernated_ = client_state->tracking_group_->hibernated_;
    738   }
    739 }
    740 
    741 void GpuMemoryManager::SendUmaStatsToBrowser() {
    742   if (!channel_manager_)
    743     return;
    744   GPUMemoryUmaStats params;
    745   params.bytes_allocated_current = GetCurrentUsage();
    746   params.bytes_allocated_max = bytes_allocated_historical_max_;
    747   params.bytes_limit = bytes_available_gpu_memory_;
    748   params.client_count = clients_visible_mru_.size() +
    749                         clients_nonvisible_mru_.size() +
    750                         clients_nonsurface_.size();
    751   params.context_group_count = tracking_groups_.size();
    752   channel_manager_->Send(new GpuHostMsg_GpuMemoryUmaStats(params));
    753 }
    754 
    755 GpuMemoryManager::ClientStateList* GpuMemoryManager::GetClientList(
    756     GpuMemoryManagerClientState* client_state) {
    757   if (client_state->has_surface_) {
    758     if (client_state->visible_)
    759       return &clients_visible_mru_;
    760     else
    761       return &clients_nonvisible_mru_;
    762   }
    763   return &clients_nonsurface_;
    764 }
    765 
    766 void GpuMemoryManager::AddClientToList(
    767     GpuMemoryManagerClientState* client_state) {
    768   DCHECK(!client_state->list_iterator_valid_);
    769   ClientStateList* client_list = GetClientList(client_state);
    770   client_state->list_iterator_ = client_list->insert(
    771       client_list->begin(), client_state);
    772   client_state->list_iterator_valid_ = true;
    773 }
    774 
    775 void GpuMemoryManager::RemoveClientFromList(
    776     GpuMemoryManagerClientState* client_state) {
    777   DCHECK(client_state->list_iterator_valid_);
    778   ClientStateList* client_list = GetClientList(client_state);
    779   client_list->erase(client_state->list_iterator_);
    780   client_state->list_iterator_valid_ = false;
    781 }
    782 
    783 }  // namespace content
    784