| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/gpu/gpu_memory_manager.h" | 5 #include "content/common/gpu/gpu_memory_manager.h" |
| 6 | 6 |
| 7 #if defined(ENABLE_GPU) | 7 #if defined(ENABLE_GPU) |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 } | 32 } |
| 33 | 33 |
| 34 GpuMemoryManager::GpuMemoryManager( | 34 GpuMemoryManager::GpuMemoryManager( |
| 35 size_t max_surfaces_with_frontbuffer_soft_limit) | 35 size_t max_surfaces_with_frontbuffer_soft_limit) |
| 36 : manage_immediate_scheduled_(false), | 36 : manage_immediate_scheduled_(false), |
| 37 max_surfaces_with_frontbuffer_soft_limit_( | 37 max_surfaces_with_frontbuffer_soft_limit_( |
| 38 max_surfaces_with_frontbuffer_soft_limit), | 38 max_surfaces_with_frontbuffer_soft_limit), |
| 39 bytes_available_gpu_memory_(0), | 39 bytes_available_gpu_memory_(0), |
| 40 bytes_available_gpu_memory_overridden_(false), | 40 bytes_available_gpu_memory_overridden_(false), |
| 41 bytes_backgrounded_available_gpu_memory_(0), |
| 41 bytes_allocated_current_(0), | 42 bytes_allocated_current_(0), |
| 42 bytes_allocated_managed_visible_(0), | 43 bytes_allocated_managed_visible_(0), |
| 43 bytes_allocated_managed_backgrounded_(0), | 44 bytes_allocated_managed_backgrounded_(0), |
| 44 window_count_has_been_received_(false), | 45 window_count_has_been_received_(false), |
| 45 window_count_(0), | 46 window_count_(0), |
| 46 disable_schedule_manage_(false) | 47 disable_schedule_manage_(false) |
| 47 { | 48 { |
| 48 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 49 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 49 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) { | 50 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) { |
| 50 base::StringToSizeT( | 51 base::StringToSizeT( |
| 51 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb), | 52 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb), |
| 52 &bytes_available_gpu_memory_); | 53 &bytes_available_gpu_memory_); |
| 53 bytes_available_gpu_memory_ *= 1024 * 1024; | 54 bytes_available_gpu_memory_ *= 1024 * 1024; |
| 54 bytes_available_gpu_memory_overridden_ = true; | 55 bytes_available_gpu_memory_overridden_ = true; |
| 55 } else | 56 } else |
| 56 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory(); | 57 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory(); |
| 58 UpdateBackgroundedAvailableGpuMemory(); |
| 57 } | 59 } |
| 58 | 60 |
| 59 GpuMemoryManager::~GpuMemoryManager() { | 61 GpuMemoryManager::~GpuMemoryManager() { |
| 60 DCHECK(tracking_groups_.empty()); | 62 DCHECK(tracking_groups_.empty()); |
| 61 DCHECK(clients_.empty()); | 63 DCHECK(clients_.empty()); |
| 62 DCHECK(!bytes_allocated_current_); | 64 DCHECK(!bytes_allocated_current_); |
| 63 DCHECK(!bytes_allocated_managed_visible_); | 65 DCHECK(!bytes_allocated_managed_visible_); |
| 64 DCHECK(!bytes_allocated_managed_backgrounded_); | 66 DCHECK(!bytes_allocated_managed_backgrounded_); |
| 65 } | 67 } |
| 66 | 68 |
| 67 size_t GpuMemoryManager::GetAvailableGpuMemory() const { | 69 size_t GpuMemoryManager::GetAvailableGpuMemory() const { |
| 68 return bytes_available_gpu_memory_; | 70 return bytes_available_gpu_memory_; |
| 69 } | 71 } |
| 70 | 72 |
| 73 size_t GpuMemoryManager::GetCurrentBackgroundedAvailableGpuMemory() const { |
| 74 if (bytes_allocated_managed_visible_ < GetAvailableGpuMemory()) { |
| 75 return std::min(bytes_backgrounded_available_gpu_memory_, |
| 76 GetAvailableGpuMemory() - bytes_allocated_managed_visible_); |
| 77 } |
| 78 return 0; |
| 79 } |
| 80 |
| 71 size_t GpuMemoryManager::GetDefaultAvailableGpuMemory() const { | 81 size_t GpuMemoryManager::GetDefaultAvailableGpuMemory() const { |
| 72 #if defined(OS_ANDROID) | 82 #if defined(OS_ANDROID) |
| 73 return 32 * 1024 * 1024; | 83 return 32 * 1024 * 1024; |
| 74 #elif defined(OS_CHROMEOS) | 84 #elif defined(OS_CHROMEOS) |
| 75 return 1024 * 1024 * 1024; | 85 return 1024 * 1024 * 1024; |
| 76 #else | 86 #else |
| 77 return 256 * 1024 * 1024; | 87 return 256 * 1024 * 1024; |
| 78 #endif | 88 #endif |
| 79 } | 89 } |
| 80 | 90 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 bytes_available_gpu_memory_ = CalcAvailableFromGpuTotal(bytes_min); | 193 bytes_available_gpu_memory_ = CalcAvailableFromGpuTotal(bytes_min); |
| 184 #endif | 194 #endif |
| 185 | 195 |
| 186 // Never go below the default allocation | 196 // Never go below the default allocation |
| 187 bytes_available_gpu_memory_ = std::max(bytes_available_gpu_memory_, | 197 bytes_available_gpu_memory_ = std::max(bytes_available_gpu_memory_, |
| 188 GetDefaultAvailableGpuMemory()); | 198 GetDefaultAvailableGpuMemory()); |
| 189 | 199 |
| 190 // Never go above the maximum. | 200 // Never go above the maximum. |
| 191 bytes_available_gpu_memory_ = std::min(bytes_available_gpu_memory_, | 201 bytes_available_gpu_memory_ = std::min(bytes_available_gpu_memory_, |
| 192 GetMaximumTotalGpuMemory()); | 202 GetMaximumTotalGpuMemory()); |
| 203 |
| 204 // Update the backgrounded available gpu memory because it depends on |
| 205 // the available GPU memory. |
| 206 UpdateBackgroundedAvailableGpuMemory(); |
| 207 } |
| 208 |
| 209 void GpuMemoryManager::UpdateBackgroundedAvailableGpuMemory() { |
| 210 // Be conservative and disable saving backgrounded tabs' textures on Android |
| 211 // for the moment |
| 212 #if defined(OS_ANDROID) |
| 213 bytes_backgrounded_available_gpu_memory_ = 0; |
| 214 #else |
| 215 bytes_backgrounded_available_gpu_memory_ = bytes_available_gpu_memory_ / 4; |
| 216 #endif |
| 193 } | 217 } |
| 194 | 218 |
| 195 bool GpuMemoryManager::ClientsComparator::operator()( | 219 bool GpuMemoryManager::ClientsComparator::operator()( |
| 196 ClientState* lhs, | 220 ClientState* lhs, |
| 197 ClientState* rhs) { | 221 ClientState* rhs) { |
| 198 if (lhs->has_surface != rhs->has_surface) | 222 if (lhs->has_surface != rhs->has_surface) |
| 199 return lhs->has_surface > rhs->has_surface; | 223 return lhs->has_surface > rhs->has_surface; |
| 200 if (lhs->visible != rhs->visible) | 224 if (lhs->visible != rhs->visible) |
| 201 return lhs->visible > rhs->visible; | 225 return lhs->visible > rhs->visible; |
| 202 if (lhs->last_used_time != rhs->last_used_time) | 226 if (lhs->last_used_time != rhs->last_used_time) |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 void GpuMemoryManager::SetClientVisible(GpuMemoryManagerClient* client, | 295 void GpuMemoryManager::SetClientVisible(GpuMemoryManagerClient* client, |
| 272 bool visible) | 296 bool visible) |
| 273 { | 297 { |
| 274 ClientMap::const_iterator it = clients_.find(client); | 298 ClientMap::const_iterator it = clients_.find(client); |
| 275 if (it == clients_.end()) | 299 if (it == clients_.end()) |
| 276 return; | 300 return; |
| 277 ClientState* client_state = it->second; | 301 ClientState* client_state = it->second; |
| 278 if (client_state->visible == visible) | 302 if (client_state->visible == visible) |
| 279 return; | 303 return; |
| 280 client_state->visible = visible; | 304 client_state->visible = visible; |
| 305 client_state->last_used_time = base::TimeTicks::Now(); |
| 281 TrackValueChanged(client_state->managed_memory_stats.bytes_allocated, 0, | 306 TrackValueChanged(client_state->managed_memory_stats.bytes_allocated, 0, |
| 282 client_state->visible ? | 307 client_state->visible ? |
| 283 &bytes_allocated_managed_backgrounded_ : | 308 &bytes_allocated_managed_backgrounded_ : |
| 284 &bytes_allocated_managed_visible_); | 309 &bytes_allocated_managed_visible_); |
| 285 TrackValueChanged(0, client_state->managed_memory_stats.bytes_allocated, | 310 TrackValueChanged(0, client_state->managed_memory_stats.bytes_allocated, |
| 286 client_state->visible ? | 311 client_state->visible ? |
| 287 &bytes_allocated_managed_visible_ : | 312 &bytes_allocated_managed_visible_ : |
| 288 &bytes_allocated_managed_backgrounded_); | 313 &bytes_allocated_managed_backgrounded_); |
| 289 ScheduleManage(visible); | 314 ScheduleManage(visible); |
| 290 } | 315 } |
| 291 | 316 |
| 292 void GpuMemoryManager::SetClientManagedMemoryStats( | 317 void GpuMemoryManager::SetClientManagedMemoryStats( |
| 293 GpuMemoryManagerClient* client, | 318 GpuMemoryManagerClient* client, |
| 294 const GpuManagedMemoryStats& stats) | 319 const GpuManagedMemoryStats& stats) |
| 295 { | 320 { |
| 296 ClientMap::const_iterator it = clients_.find(client); | 321 ClientMap::const_iterator it = clients_.find(client); |
| 297 if (it == clients_.end()) | 322 if (it == clients_.end()) |
| 298 return; | 323 return; |
| 299 ClientState* client_state = it->second; | 324 ClientState* client_state = it->second; |
| 300 TrackValueChanged(client_state->managed_memory_stats.bytes_allocated, | 325 TrackValueChanged(client_state->managed_memory_stats.bytes_allocated, |
| 301 stats.bytes_allocated, | 326 stats.bytes_allocated, |
| 302 client_state->visible ? | 327 client_state->visible ? |
| 303 &bytes_allocated_managed_visible_ : | 328 &bytes_allocated_managed_visible_ : |
| 304 &bytes_allocated_managed_backgrounded_); | 329 &bytes_allocated_managed_backgrounded_); |
| 305 client_state->managed_memory_stats = stats; | 330 client_state->managed_memory_stats = stats; |
| 331 |
| 332 // If this allocation pushed our usage of backgrounded tabs memory over the |
| 333 // limit, then schedule a drop of backgrounded memory. |
| 334 if (bytes_allocated_managed_backgrounded_ > |
| 335 GetCurrentBackgroundedAvailableGpuMemory()) |
| 336 ScheduleManage(false); |
| 306 } | 337 } |
| 307 | 338 |
| 308 void GpuMemoryManager::TestingSetClientVisible( | 339 void GpuMemoryManager::TestingSetClientVisible( |
| 309 GpuMemoryManagerClient* client, bool visible) { | 340 GpuMemoryManagerClient* client, bool visible) { |
| 310 DCHECK(clients_.count(client)); | 341 DCHECK(clients_.count(client)); |
| 311 clients_[client]->visible = visible; | 342 clients_[client]->visible = visible; |
| 312 } | 343 } |
| 313 | 344 |
| 314 void GpuMemoryManager::TestingSetClientLastUsedTime( | 345 void GpuMemoryManager::TestingSetClientLastUsedTime( |
| 315 GpuMemoryManagerClient* client, base::TimeTicks last_used_time) { | 346 GpuMemoryManagerClient* client, base::TimeTicks last_used_time) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 DCHECK(std::unique(clients.begin(), clients.end()) == clients.end()); | 446 DCHECK(std::unique(clients.begin(), clients.end()) == clients.end()); |
| 416 | 447 |
| 417 // Update the amount of GPU memory available on the system. | 448 // Update the amount of GPU memory available on the system. |
| 418 UpdateAvailableGpuMemory(clients); | 449 UpdateAvailableGpuMemory(clients); |
| 419 | 450 |
| 420 // Determine which clients are "hibernated" (which determines the | 451 // Determine which clients are "hibernated" (which determines the |
| 421 // distribution of frontbuffers and memory among clients that don't have | 452 // distribution of frontbuffers and memory among clients that don't have |
| 422 // surfaces). | 453 // surfaces). |
| 423 SetClientsHibernatedState(clients); | 454 SetClientsHibernatedState(clients); |
| 424 | 455 |
| 425 // Determine how much memory to assign to give to visible clients | 456 // Determine how much memory to assign to give to visible and backgrounded |
| 457 // clients. |
| 426 size_t bytes_limit_when_visible = GetVisibleClientAllocation(clients); | 458 size_t bytes_limit_when_visible = GetVisibleClientAllocation(clients); |
| 427 | 459 |
| 428 // Now give out allocations to everyone. | 460 // Now give out allocations to everyone. |
| 461 size_t bytes_allocated_backgrounded = 0; |
| 429 for (ClientStateVector::iterator it = clients.begin(); | 462 for (ClientStateVector::iterator it = clients.begin(); |
| 430 it != clients.end(); | 463 it != clients.end(); |
| 431 ++it) { | 464 ++it) { |
| 432 ClientState* client_state = *it; | 465 ClientState* client_state = *it; |
| 433 | |
| 434 GpuMemoryAllocation allocation; | 466 GpuMemoryAllocation allocation; |
| 435 if (client_state->has_surface) { | 467 if (client_state->has_surface) { |
| 436 allocation.browser_allocation.suggest_have_frontbuffer = | 468 allocation.browser_allocation.suggest_have_frontbuffer = |
| 437 !client_state->hibernated; | 469 !client_state->hibernated; |
| 470 |
| 471 // Set the state when visible. |
| 438 allocation.renderer_allocation.bytes_limit_when_visible = | 472 allocation.renderer_allocation.bytes_limit_when_visible = |
| 439 bytes_limit_when_visible; | 473 bytes_limit_when_visible; |
| 440 allocation.renderer_allocation.priority_cutoff_when_visible = | 474 allocation.renderer_allocation.priority_cutoff_when_visible = |
| 441 GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything; | 475 GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything; |
| 442 allocation.renderer_allocation.bytes_limit_when_not_visible = | 476 |
| 443 0; | 477 // Set the state when backgrounded. |
| 444 allocation.renderer_allocation.priority_cutoff_when_not_visible = | 478 bool allow_allocation_when_backgrounded = false; |
| 445 GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNothing; | 479 if (client_state->visible) { |
| 480 // If the client is visible, then allow it to keep its textures, should |
| 481 // it be backgrounded, but only if all textures required to draw will |
| 482 // fit in total backgrounded memory limit. |
| 483 allow_allocation_when_backgrounded = |
| 484 client_state->managed_memory_stats.bytes_required < |
| 485 bytes_backgrounded_available_gpu_memory_; |
| 486 } else { |
| 487 // If the client is backgrounded, then allow it to keep its textures |
| 488 // if everything required to draw fits in-budget. |
| 489 allow_allocation_when_backgrounded = |
| 490 client_state->managed_memory_stats.bytes_required + |
| 491 bytes_allocated_backgrounded < |
| 492 GetCurrentBackgroundedAvailableGpuMemory(); |
| 493 if (allow_allocation_when_backgrounded) { |
| 494 bytes_allocated_backgrounded += |
| 495 client_state->managed_memory_stats.bytes_allocated; |
| 496 } |
| 497 } |
| 498 if (allow_allocation_when_backgrounded) { |
| 499 allocation.renderer_allocation.bytes_limit_when_not_visible = |
| 500 GetCurrentBackgroundedAvailableGpuMemory(); |
| 501 allocation.renderer_allocation.priority_cutoff_when_not_visible = |
| 502 GpuMemoryAllocationForRenderer::kPriorityCutoffAllowOnlyRequired; |
| 503 } else { |
| 504 allocation.renderer_allocation.bytes_limit_when_not_visible = 0; |
| 505 allocation.renderer_allocation.priority_cutoff_when_not_visible = |
| 506 GpuMemoryAllocationForRenderer::kPriorityCutoffAllowNothing; |
| 507 } |
| 446 } else { | 508 } else { |
| 447 if (!client_state->hibernated) { | 509 if (!client_state->hibernated) { |
| 448 allocation.renderer_allocation.bytes_limit_when_visible = | 510 allocation.renderer_allocation.bytes_limit_when_visible = |
| 449 GetMinimumTabAllocation(); | 511 GetMinimumTabAllocation(); |
| 450 allocation.renderer_allocation.priority_cutoff_when_visible = | 512 allocation.renderer_allocation.priority_cutoff_when_visible = |
| 451 GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything; | 513 GpuMemoryAllocationForRenderer::kPriorityCutoffAllowEverything; |
| 452 } | 514 } |
| 453 } | 515 } |
| 454 client_state->client->SetMemoryAllocation(allocation); | 516 client_state->client->SetMemoryAllocation(allocation); |
| 455 } | 517 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 : client(client), | 604 : client(client), |
| 543 has_surface(has_surface), | 605 has_surface(has_surface), |
| 544 visible(visible), | 606 visible(visible), |
| 545 last_used_time(last_used_time), | 607 last_used_time(last_used_time), |
| 546 hibernated(false) { | 608 hibernated(false) { |
| 547 } | 609 } |
| 548 | 610 |
| 549 } // namespace content | 611 } // namespace content |
| 550 | 612 |
| 551 #endif | 613 #endif |
| OLD | NEW |