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 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 GpuChannelManager* channel_manager, | 49 GpuChannelManager* channel_manager, |
50 uint64 max_surfaces_with_frontbuffer_soft_limit) | 50 uint64 max_surfaces_with_frontbuffer_soft_limit) |
51 : channel_manager_(channel_manager), | 51 : channel_manager_(channel_manager), |
52 use_nonuniform_memory_policy_(false), | 52 use_nonuniform_memory_policy_(false), |
53 manage_immediate_scheduled_(false), | 53 manage_immediate_scheduled_(false), |
54 max_surfaces_with_frontbuffer_soft_limit_( | 54 max_surfaces_with_frontbuffer_soft_limit_( |
55 max_surfaces_with_frontbuffer_soft_limit), | 55 max_surfaces_with_frontbuffer_soft_limit), |
56 bytes_available_gpu_memory_(0), | 56 bytes_available_gpu_memory_(0), |
57 bytes_available_gpu_memory_overridden_(false), | 57 bytes_available_gpu_memory_overridden_(false), |
58 bytes_minimum_per_client_(0), | 58 bytes_minimum_per_client_(0), |
59 bytes_minimum_per_client_overridden_(false), | 59 bytes_default_per_client_(0), |
60 bytes_nonvisible_available_gpu_memory_(0), | 60 bytes_nonvisible_available_gpu_memory_(0), |
61 bytes_allocated_managed_current_(0), | 61 bytes_allocated_managed_current_(0), |
62 bytes_allocated_managed_visible_(0), | 62 bytes_allocated_managed_visible_(0), |
63 bytes_allocated_managed_nonvisible_(0), | 63 bytes_allocated_managed_nonvisible_(0), |
64 bytes_allocated_unmanaged_current_(0), | 64 bytes_allocated_unmanaged_current_(0), |
65 bytes_allocated_historical_max_(0), | 65 bytes_allocated_historical_max_(0), |
66 bytes_allocated_unmanaged_high_(0), | 66 bytes_allocated_unmanaged_high_(0), |
67 bytes_allocated_unmanaged_low_(0), | 67 bytes_allocated_unmanaged_low_(0), |
68 bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep), | 68 bytes_unmanaged_limit_step_(kBytesAllocatedUnmanagedStep), |
69 window_count_has_been_received_(false), | 69 window_count_has_been_received_(false), |
70 window_count_(0), | 70 window_count_(0), |
71 disable_schedule_manage_(false) | 71 disable_schedule_manage_(false) |
72 { | 72 { |
73 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 73 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 74 |
| 75 #if defined(OS_ANDROID) |
| 76 bytes_default_per_client_ = 32 * 1024 * 1024; |
| 77 bytes_minimum_per_client_ = 32 * 1024 * 1024; |
| 78 #else |
| 79 bytes_default_per_client_ = 64 * 1024 * 1024; |
| 80 bytes_minimum_per_client_ = 64 * 1024 * 1024; |
| 81 #endif |
| 82 |
74 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) { | 83 if (command_line->HasSwitch(switches::kForceGpuMemAvailableMb)) { |
75 base::StringToUint64( | 84 base::StringToUint64( |
76 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb), | 85 command_line->GetSwitchValueASCII(switches::kForceGpuMemAvailableMb), |
77 &bytes_available_gpu_memory_); | 86 &bytes_available_gpu_memory_); |
78 bytes_available_gpu_memory_ *= 1024 * 1024; | 87 bytes_available_gpu_memory_ *= 1024 * 1024; |
79 bytes_available_gpu_memory_overridden_ = true; | 88 bytes_available_gpu_memory_overridden_ = true; |
80 } else | 89 } else |
81 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory(); | 90 bytes_available_gpu_memory_ = GetDefaultAvailableGpuMemory(); |
82 UpdateNonvisibleAvailableGpuMemory(); | 91 UpdateNonvisibleAvailableGpuMemory(); |
83 } | 92 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) | 140 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
132 return bytes_available_gpu_memory_; | 141 return bytes_available_gpu_memory_; |
133 #else | 142 #else |
134 // This is to avoid allowing a single page on to use a full 256MB of memory | 143 // This is to avoid allowing a single page on to use a full 256MB of memory |
135 // (the current total limit). Long-scroll pages will hit this limit, | 144 // (the current total limit). Long-scroll pages will hit this limit, |
136 // resulting in instability on some platforms (e.g, issue 141377). | 145 // resulting in instability on some platforms (e.g, issue 141377). |
137 return bytes_available_gpu_memory_ / 2; | 146 return bytes_available_gpu_memory_ / 2; |
138 #endif | 147 #endif |
139 } | 148 } |
140 | 149 |
141 uint64 GpuMemoryManager::GetMinimumClientAllocation() const { | |
142 if (bytes_minimum_per_client_overridden_) | |
143 return bytes_minimum_per_client_; | |
144 #if defined(OS_ANDROID) | |
145 return 32 * 1024 * 1024; | |
146 #elif defined(OS_CHROMEOS) | |
147 return 64 * 1024 * 1024; | |
148 #else | |
149 return 64 * 1024 * 1024; | |
150 #endif | |
151 } | |
152 | |
153 uint64 GpuMemoryManager::CalcAvailableFromViewportArea(int viewport_area) { | 150 uint64 GpuMemoryManager::CalcAvailableFromViewportArea(int viewport_area) { |
154 // We can't query available GPU memory from the system on Android, but | 151 // We can't query available GPU memory from the system on Android, but |
155 // 18X the viewport and 50% of the dalvik heap size give us a good | 152 // 18X the viewport and 50% of the dalvik heap size give us a good |
156 // estimate of available GPU memory on a wide range of devices. | 153 // estimate of available GPU memory on a wide range of devices. |
157 const int kViewportMultiplier = 18; | 154 const int kViewportMultiplier = 18; |
158 const unsigned int kComponentsPerPixel = 4; // GraphicsContext3D::RGBA | 155 const unsigned int kComponentsPerPixel = 4; // GraphicsContext3D::RGBA |
159 const unsigned int kBytesPerComponent = 1; // sizeof(GC3Dubyte) | 156 const unsigned int kBytesPerComponent = 1; // sizeof(GC3Dubyte) |
160 uint64 viewport_limit = viewport_area * kViewportMultiplier * | 157 uint64 viewport_limit = viewport_area * kViewportMultiplier * |
161 kComponentsPerPixel * | 158 kComponentsPerPixel * |
162 kBytesPerComponent; | 159 kBytesPerComponent; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 GpuMemoryManagerClientState* client_state, | 379 GpuMemoryManagerClientState* client_state, |
383 const GpuManagedMemoryStats& stats) | 380 const GpuManagedMemoryStats& stats) |
384 { | 381 { |
385 TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated, | 382 TrackValueChanged(client_state->managed_memory_stats_.bytes_allocated, |
386 stats.bytes_allocated, | 383 stats.bytes_allocated, |
387 client_state->visible_ ? | 384 client_state->visible_ ? |
388 &bytes_allocated_managed_visible_ : | 385 &bytes_allocated_managed_visible_ : |
389 &bytes_allocated_managed_nonvisible_); | 386 &bytes_allocated_managed_nonvisible_); |
390 client_state->managed_memory_stats_ = stats; | 387 client_state->managed_memory_stats_ = stats; |
391 | 388 |
| 389 // If this is the first time that stats have been received for this |
| 390 // client, use them immediately. |
| 391 if (!client_state->managed_memory_stats_received_) { |
| 392 client_state->managed_memory_stats_received_ = true; |
| 393 ScheduleManage(kScheduleManageNow); |
| 394 return; |
| 395 } |
| 396 |
392 if (use_nonuniform_memory_policy_) { | 397 if (use_nonuniform_memory_policy_) { |
393 // If these statistics sit outside of the range that we used in our | 398 // If these statistics sit outside of the range that we used in our |
394 // computation of memory allocations then recompute the allocations. | 399 // computation of memory allocations then recompute the allocations. |
395 if (client_state->managed_memory_stats_.bytes_nice_to_have > | 400 if (client_state->managed_memory_stats_.bytes_nice_to_have > |
396 client_state->bytes_nicetohave_limit_high_) { | 401 client_state->bytes_nicetohave_limit_high_) { |
397 ScheduleManage(kScheduleManageNow); | 402 ScheduleManage(kScheduleManageNow); |
398 } else if (client_state->managed_memory_stats_.bytes_nice_to_have < | 403 } else if (client_state->managed_memory_stats_.bytes_nice_to_have < |
399 client_state->bytes_nicetohave_limit_low_) { | 404 client_state->bytes_nicetohave_limit_low_) { |
400 ScheduleManage(kScheduleManageLater); | 405 ScheduleManage(kScheduleManageLater); |
401 } | 406 } |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 return bytes_sum_limit / bytes_size; | 559 return bytes_sum_limit / bytes_size; |
555 } | 560 } |
556 | 561 |
557 uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible( | 562 uint64 GpuMemoryManager::ComputeClientAllocationWhenVisible( |
558 GpuMemoryManagerClientState* client_state, | 563 GpuMemoryManagerClientState* client_state, |
559 uint64 bytes_above_required_cap, | 564 uint64 bytes_above_required_cap, |
560 uint64 bytes_above_minimum_cap, | 565 uint64 bytes_above_minimum_cap, |
561 uint64 bytes_overall_cap) { | 566 uint64 bytes_overall_cap) { |
562 GpuManagedMemoryStats* stats = &client_state->managed_memory_stats_; | 567 GpuManagedMemoryStats* stats = &client_state->managed_memory_stats_; |
563 | 568 |
| 569 if (!client_state->managed_memory_stats_received_) |
| 570 return GetDefaultClientAllocation(); |
| 571 |
564 uint64 bytes_required = 9 * stats->bytes_required / 8; | 572 uint64 bytes_required = 9 * stats->bytes_required / 8; |
565 bytes_required = std::min(bytes_required, GetMaximumClientAllocation()); | 573 bytes_required = std::min(bytes_required, GetMaximumClientAllocation()); |
566 bytes_required = std::max(bytes_required, GetMinimumClientAllocation()); | 574 bytes_required = std::max(bytes_required, GetMinimumClientAllocation()); |
567 | 575 |
568 uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3; | 576 uint64 bytes_nicetohave = 4 * stats->bytes_nice_to_have / 3; |
569 bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation()); | 577 bytes_nicetohave = std::min(bytes_nicetohave, GetMaximumClientAllocation()); |
570 bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation()); | 578 bytes_nicetohave = std::max(bytes_nicetohave, GetMinimumClientAllocation()); |
571 bytes_nicetohave = std::max(bytes_nicetohave, bytes_required); | 579 bytes_nicetohave = std::max(bytes_nicetohave, bytes_required); |
572 | 580 |
573 uint64 allocation = GetMinimumClientAllocation(); | 581 uint64 allocation = GetMinimumClientAllocation(); |
574 allocation += std::min(bytes_required - GetMinimumClientAllocation(), | 582 allocation += std::min(bytes_required - GetMinimumClientAllocation(), |
575 bytes_above_minimum_cap); | 583 bytes_above_minimum_cap); |
576 allocation += std::min(bytes_nicetohave - bytes_required, | 584 allocation += std::min(bytes_nicetohave - bytes_required, |
577 bytes_above_required_cap); | 585 bytes_above_required_cap); |
578 allocation = std::min(allocation, | 586 allocation = std::min(allocation, |
579 bytes_overall_cap); | 587 bytes_overall_cap); |
580 return allocation; | 588 return allocation; |
581 } | 589 } |
582 | 590 |
583 uint64 GpuMemoryManager::ComputeClientAllocationWhenNonvisible( | 591 uint64 GpuMemoryManager::ComputeClientAllocationWhenNonvisible( |
584 GpuMemoryManagerClientState* client_state) { | 592 GpuMemoryManagerClientState* client_state) { |
| 593 |
| 594 if (!client_state->managed_memory_stats_received_) |
| 595 return 0; |
| 596 |
585 return 9 * client_state->managed_memory_stats_.bytes_required / 8; | 597 return 9 * client_state->managed_memory_stats_.bytes_required / 8; |
586 } | 598 } |
587 | 599 |
588 void GpuMemoryManager::ComputeVisibleSurfacesAllocationsNonuniform() { | 600 void GpuMemoryManager::ComputeVisibleSurfacesAllocationsNonuniform() { |
589 uint64 bytes_available_total = GetAvailableGpuMemory(); | 601 uint64 bytes_available_total = GetAvailableGpuMemory(); |
590 uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max(); | 602 uint64 bytes_above_required_cap = std::numeric_limits<uint64>::max(); |
591 uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max(); | 603 uint64 bytes_above_minimum_cap = std::numeric_limits<uint64>::max(); |
592 uint64 bytes_overall_cap_visible = GetMaximumClientAllocation(); | 604 uint64 bytes_overall_cap_visible = GetMaximumClientAllocation(); |
593 | 605 |
594 // Compute memory usage at three levels | 606 // Compute memory usage at three levels |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 bytes_available_nonvisible_adjusted) | 760 bytes_available_nonvisible_adjusted) |
749 client_state->bytes_allocation_when_nonvisible_ = 0; | 761 client_state->bytes_allocation_when_nonvisible_ = 0; |
750 } | 762 } |
751 | 763 |
752 // Compute which currently nonvisible clients should keep their contents. | 764 // Compute which currently nonvisible clients should keep their contents. |
753 for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin(); | 765 for (ClientStateList::const_iterator it = clients_nonvisible_mru_.begin(); |
754 it != clients_nonvisible_mru_.end(); | 766 it != clients_nonvisible_mru_.end(); |
755 ++it) { | 767 ++it) { |
756 GpuMemoryManagerClientState* client_state = *it; | 768 GpuMemoryManagerClientState* client_state = *it; |
757 | 769 |
| 770 // If this client is nonvisible and has already had its contents discarded, |
| 771 // don't re-generate the contents until the client becomes visible again. |
| 772 if (!client_state->bytes_allocation_when_nonvisible_) |
| 773 continue; |
| 774 |
758 client_state->bytes_allocation_when_nonvisible_ = | 775 client_state->bytes_allocation_when_nonvisible_ = |
759 ComputeClientAllocationWhenNonvisible(client_state); | 776 ComputeClientAllocationWhenNonvisible(client_state); |
760 | 777 |
761 // Take into account all more recently used nonvisible clients, and only if | 778 // Take into account all more recently used nonvisible clients, and only if |
762 // this client still fits, all it to keep its contents. | 779 // this client still fits, all it to keep its contents. |
763 if (bytes_allocated_nonvisible + | 780 if (bytes_allocated_nonvisible + |
764 client_state->bytes_allocation_when_nonvisible_ > | 781 client_state->bytes_allocation_when_nonvisible_ > |
765 bytes_allocated_nonvisible) { | 782 bytes_available_nonvisible) { |
766 client_state->bytes_allocation_when_nonvisible_ = 0; | 783 client_state->bytes_allocation_when_nonvisible_ = 0; |
767 } | 784 } |
768 bytes_allocated_nonvisible += | 785 bytes_allocated_nonvisible += |
769 client_state->bytes_allocation_when_nonvisible_; | 786 client_state->bytes_allocation_when_nonvisible_; |
770 } | 787 } |
771 } | 788 } |
772 | 789 |
773 void GpuMemoryManager::AssignSurfacesAllocationsNonuniform() { | 790 void GpuMemoryManager::AssignSurfacesAllocationsNonuniform() { |
774 // Compute allocation when for all clients. | 791 // Compute allocation when for all clients. |
775 ComputeVisibleSurfacesAllocationsNonuniform(); | 792 ComputeVisibleSurfacesAllocationsNonuniform(); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 | 1042 |
1026 void GpuMemoryManager::RemoveClientFromList( | 1043 void GpuMemoryManager::RemoveClientFromList( |
1027 GpuMemoryManagerClientState* client_state) { | 1044 GpuMemoryManagerClientState* client_state) { |
1028 DCHECK(client_state->list_iterator_valid_); | 1045 DCHECK(client_state->list_iterator_valid_); |
1029 ClientStateList* client_list = GetClientList(client_state); | 1046 ClientStateList* client_list = GetClientList(client_state); |
1030 client_list->erase(client_state->list_iterator_); | 1047 client_list->erase(client_state->list_iterator_); |
1031 client_state->list_iterator_valid_ = false; | 1048 client_state->list_iterator_valid_ = false; |
1032 } | 1049 } |
1033 | 1050 |
1034 } // namespace content | 1051 } // namespace content |
OLD | NEW |