| Index: content/common/gpu/gpu_memory_manager.cc
|
| diff --git a/content/common/gpu/gpu_memory_manager.cc b/content/common/gpu/gpu_memory_manager.cc
|
| index e5c8f559f28694021b5cfefa1f5e7794b6d8da3a..879e747be73c3e0606d5304d949acc8da1e0e407 100644
|
| --- a/content/common/gpu/gpu_memory_manager.cc
|
| +++ b/content/common/gpu/gpu_memory_manager.cc
|
| @@ -38,6 +38,7 @@ GpuMemoryManager::GpuMemoryManager(
|
| max_surfaces_with_frontbuffer_soft_limit),
|
| bytes_available_gpu_memory_(0),
|
| bytes_available_gpu_memory_overridden_(false),
|
| + bytes_backgrounded_available_gpu_memory_(0),
|
| bytes_allocated_current_(0),
|
| bytes_allocated_managed_visible_(0),
|
| bytes_allocated_managed_backgrounded_(0),
|
| @@ -54,6 +55,7 @@ GpuMemoryManager::GpuMemoryManager(
|
| bytes_available_gpu_memory_overridden_ = true;
|
| } else
|
| bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory();
|
| + UpdateBackgroundedAvailableGpuMemory();
|
| }
|
|
|
| GpuMemoryManager::~GpuMemoryManager() {
|
| @@ -68,6 +70,14 @@ size_t GpuMemoryManager::GetAvailableGpuMemory() const {
|
| return bytes_available_gpu_memory_;
|
| }
|
|
|
| +size_t GpuMemoryManager::GetCurrentBackgroundedAvailableGpuMemory() const {
|
| + if (bytes_allocated_managed_visible_ < GetAvailableGpuMemory()) {
|
| + return std::min(bytes_backgrounded_available_gpu_memory_,
|
| + GetAvailableGpuMemory() - bytes_allocated_managed_visible_);
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| size_t GpuMemoryManager::GetDefaultAvailableGpuMemory() const {
|
| #if defined(OS_ANDROID)
|
| return 32 * 1024 * 1024;
|
| @@ -190,6 +200,20 @@ void GpuMemoryManager::UpdateAvailableGpuMemory(
|
| // Never go above the maximum.
|
| bytes_available_gpu_memory_ = std::min(bytes_available_gpu_memory_,
|
| GetMaximumTotalGpuMemory());
|
| +
|
| + // Update the backgrounded available gpu memory because it depends on
|
| + // the available GPU memory.
|
| + UpdateBackgroundedAvailableGpuMemory();
|
| +}
|
| +
|
| +void GpuMemoryManager::UpdateBackgroundedAvailableGpuMemory() {
|
| + // Be conservative and disable saving backgrounded tabs' textures on Android
|
| + // for the moment
|
| +#if defined(OS_ANDROID)
|
| + bytes_backgrounded_available_gpu_memory_ = 0;
|
| +#else
|
| + bytes_backgrounded_available_gpu_memory_ = bytes_available_gpu_memory_ / 4;
|
| +#endif
|
| }
|
|
|
| bool GpuMemoryManager::ClientsComparator::operator()(
|
| @@ -278,6 +302,7 @@ void GpuMemoryManager::SetClientVisible(GpuMemoryManagerClient* client,
|
| if (client_state->visible == visible)
|
| return;
|
| client_state->visible = visible;
|
| + client_state->last_used_time = base::TimeTicks::Now();
|
| TrackValueChanged(client_state->managed_memory_stats.bytes_allocated, 0,
|
| client_state->visible ?
|
| &bytes_allocated_managed_backgrounded_ :
|
| @@ -303,6 +328,12 @@ void GpuMemoryManager::SetClientManagedMemoryStats(
|
| &bytes_allocated_managed_visible_ :
|
| &bytes_allocated_managed_backgrounded_);
|
| client_state->managed_memory_stats = stats;
|
| +
|
| + // If this allocation pushed our usage of backgrounded tabs memory over the
|
| + // limit, then schedule a drop of backgrounded memory.
|
| + if (bytes_allocated_managed_backgrounded_ >
|
| + GetCurrentBackgroundedAvailableGpuMemory())
|
| + ScheduleManage(false);
|
| }
|
|
|
| void GpuMemoryManager::TestingSetClientVisible(
|
| @@ -422,27 +453,58 @@ void GpuMemoryManager::Manage() {
|
| // surfaces).
|
| SetClientsHibernatedState(clients);
|
|
|
| - // Determine how much memory to assign to give to visible clients
|
| + // Determine how much memory to assign to give to visible and backgrounded
|
| + // clients.
|
| size_t bytes_limit_when_visible = GetVisibleClientAllocation(clients);
|
|
|
| // Now give out allocations to everyone.
|
| + size_t bytes_allocated_backgrounded = 0;
|
| for (ClientStateVector::iterator it = clients.begin();
|
| it != clients.end();
|
| ++it) {
|
| ClientState* client_state = *it;
|
| -
|
| GpuMemoryAllocation allocation;
|
| if (client_state->has_surface) {
|
| allocation.browser_allocation.suggest_have_frontbuffer =
|
| !client_state->hibernated;
|
| +
|
| + // Set the state when visible.
|
| allocation.renderer_allocation.bytes_limit_when_visible =
|
| bytes_limit_when_visible;
|
| allocation.renderer_allocation.priority_cutoff_when_visible =
|
| GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything;
|
| - allocation.renderer_allocation.bytes_limit_when_not_visible =
|
| - 0;
|
| - allocation.renderer_allocation.priority_cutoff_when_not_visible =
|
| - GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNothing;
|
| +
|
| + // Set the state when backgrounded.
|
| + bool allow_allocation_when_backgrounded = false;
|
| + if (client_state->visible) {
|
| + // If the client is visible, then allow it to keep its textures, should
|
| + // it be backgrounded, but only if all textures required to draw will
|
| + // fit in total backgrounded memory limit.
|
| + allow_allocation_when_backgrounded =
|
| + client_state->managed_memory_stats.bytes_required <
|
| + bytes_backgrounded_available_gpu_memory_;
|
| + } else {
|
| + // If the client is backgrounded, then allow it to keep its textures
|
| + // if everything required to draw fits in-budget.
|
| + allow_allocation_when_backgrounded =
|
| + client_state->managed_memory_stats.bytes_required +
|
| + bytes_allocated_backgrounded <
|
| + GetCurrentBackgroundedAvailableGpuMemory();
|
| + if (allow_allocation_when_backgrounded) {
|
| + bytes_allocated_backgrounded +=
|
| + client_state->managed_memory_stats.bytes_allocated;
|
| + }
|
| + }
|
| + if (allow_allocation_when_backgrounded) {
|
| + allocation.renderer_allocation.bytes_limit_when_not_visible =
|
| + GetCurrentBackgroundedAvailableGpuMemory();
|
| + allocation.renderer_allocation.priority_cutoff_when_not_visible =
|
| + GpuMemoryAllocationForRenderer::kPriorityCutoffAllowOnlyRequired;
|
| + } else {
|
| + allocation.renderer_allocation.bytes_limit_when_not_visible = 0;
|
| + allocation.renderer_allocation.priority_cutoff_when_not_visible =
|
| + GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNothing;
|
| + }
|
| } else {
|
| if (!client_state->hibernated) {
|
| allocation.renderer_allocation.bytes_limit_when_visible =
|
|
|