Chromium Code Reviews| 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" |
| 11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/process_util.h" | 13 #include "base/process_util.h" |
| 14 #include "base/string_number_conversions.h" | 14 #include "base/string_number_conversions.h" |
| 15 #include "base/sys_info.h" | |
| 16 #include "content/common/gpu/gpu_channel_manager.h" | 15 #include "content/common/gpu/gpu_channel_manager.h" |
| 17 #include "content/common/gpu/gpu_memory_allocation.h" | 16 #include "content/common/gpu/gpu_memory_allocation.h" |
| 18 #include "content/common/gpu/gpu_memory_manager_client.h" | 17 #include "content/common/gpu/gpu_memory_manager_client.h" |
| 19 #include "content/common/gpu/gpu_memory_tracking.h" | 18 #include "content/common/gpu/gpu_memory_tracking.h" |
| 20 #include "content/common/gpu/gpu_memory_uma_stats.h" | 19 #include "content/common/gpu/gpu_memory_uma_stats.h" |
| 21 #include "content/common/gpu/gpu_messages.h" | 20 #include "content/common/gpu/gpu_messages.h" |
| 22 #include "gpu/command_buffer/service/gpu_switches.h" | 21 #include "gpu/command_buffer/service/gpu_switches.h" |
| 23 | 22 |
| 24 namespace content { | 23 namespace content { |
| 25 namespace { | 24 namespace { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) | 143 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
| 145 return bytes_available_gpu_memory_; | 144 return bytes_available_gpu_memory_; |
| 146 #else | 145 #else |
| 147 // This is to avoid allowing a single page on to use a full 256MB of memory | 146 // This is to avoid allowing a single page on to use a full 256MB of memory |
| 148 // (the current total limit). Long-scroll pages will hit this limit, | 147 // (the current total limit). Long-scroll pages will hit this limit, |
| 149 // resulting in instability on some platforms (e.g, issue 141377). | 148 // resulting in instability on some platforms (e.g, issue 141377). |
| 150 return bytes_available_gpu_memory_ / 2; | 149 return bytes_available_gpu_memory_ / 2; |
| 151 #endif | 150 #endif |
| 152 } | 151 } |
| 153 | 152 |
| 154 uint64 GpuMemoryManager::CalcAvailableFromViewportArea(int viewport_area) { | |
| 155 // We can't query available GPU memory from the system on Android, but | |
| 156 // 18X the viewport and 50% of the dalvik heap size give us a good | |
| 157 // estimate of available GPU memory on a wide range of devices. | |
| 158 const int kViewportMultiplier = 18; | |
| 159 const unsigned int kComponentsPerPixel = 4; // GraphicsContext3D::RGBA | |
| 160 const unsigned int kBytesPerComponent = 1; // sizeof(GC3Dubyte) | |
| 161 uint64 viewport_limit = viewport_area * kViewportMultiplier * | |
| 162 kComponentsPerPixel * | |
| 163 kBytesPerComponent; | |
| 164 #if !defined(OS_ANDROID) | |
| 165 return viewport_limit; | |
| 166 #else | |
| 167 static uint64 dalvik_limit = 0; | |
| 168 if (!dalvik_limit) | |
| 169 dalvik_limit = (base::SysInfo::DalvikHeapSizeMB() / 2) * 1024 * 1024; | |
| 170 return std::min(viewport_limit, dalvik_limit); | |
| 171 #endif | |
| 172 } | |
| 173 | |
| 174 uint64 GpuMemoryManager::CalcAvailableFromGpuTotal(uint64 total_gpu_memory) { | 153 uint64 GpuMemoryManager::CalcAvailableFromGpuTotal(uint64 total_gpu_memory) { |
| 175 // Allow Chrome to use 75% of total GPU memory, or all-but-64MB of GPU | 154 // Allow Chrome to use 75% of total GPU memory, or all-but-64MB of GPU |
| 176 // memory, whichever is less. | 155 // memory, whichever is less. |
| 177 return std::min(3 * total_gpu_memory / 4, total_gpu_memory - 64*1024*1024); | 156 return std::min(3 * total_gpu_memory / 4, total_gpu_memory - 64*1024*1024); |
| 178 } | 157 } |
| 179 | 158 |
| 180 void GpuMemoryManager::UpdateAvailableGpuMemory() { | 159 void GpuMemoryManager::UpdateAvailableGpuMemory() { |
| 181 // If the amount of video memory to use was specified at the command | 160 // If the amount of video memory to use was specified at the command |
| 182 // line, never change it. | 161 // line, never change it. |
| 183 if (bytes_available_gpu_memory_overridden_) | 162 if (bytes_available_gpu_memory_overridden_) |
| 184 return; | 163 return; |
| 185 | 164 |
| 186 #if defined(OS_ANDROID) | |
| 187 // On Android we use the surface size, so this finds the largest visible | |
| 188 // surface size instead of lowest gpu's limit. | |
| 189 int max_surface_area = 0; | |
| 190 #else | |
| 191 // On non-Android, we use an operating system query when possible. | 165 // On non-Android, we use an operating system query when possible. |
| 192 // We do not have a reliable concept of multiple GPUs existing in | 166 // We do not have a reliable concept of multiple GPUs existing in |
| 193 // a system, so just be safe and go with the minimum encountered. | 167 // a system, so just be safe and go with the minimum encountered. |
| 194 uint64 bytes_min = 0; | 168 uint64 bytes_min = 0; |
| 195 #endif | |
| 196 | 169 |
| 197 // Only use the clients that are visible, because otherwise the set of clients | 170 // Only use the clients that are visible, because otherwise the set of clients |
| 198 // we are querying could become extremely large. | 171 // we are querying could become extremely large. |
| 199 for (ClientStateList::const_iterator it = clients_visible_mru_.begin(); | 172 for (ClientStateList::const_iterator it = clients_visible_mru_.begin(); |
| 200 it != clients_visible_mru_.end(); | 173 it != clients_visible_mru_.end(); |
| 201 ++it) { | 174 ++it) { |
| 202 const GpuMemoryManagerClientState* client_state = *it; | 175 const GpuMemoryManagerClientState* client_state = *it; |
| 203 if (!client_state->has_surface_) | 176 if (!client_state->has_surface_) |
| 204 continue; | 177 continue; |
| 205 if (!client_state->visible_) | 178 if (!client_state->visible_) |
| 206 continue; | 179 continue; |
| 207 | 180 |
| 208 #if defined(OS_ANDROID) | |
| 209 gfx::Size surface_size = client_state->client_->GetSurfaceSize(); | |
| 210 max_surface_area = std::max(max_surface_area, surface_size.width() * | |
| 211 surface_size.height()); | |
| 212 #else | |
| 213 uint64 bytes = 0; | 181 uint64 bytes = 0; |
| 214 if (client_state->client_->GetTotalGpuMemory(&bytes)) { | 182 if (client_state->client_->GetTotalGpuMemory(&bytes)) { |
| 215 if (!bytes_min || bytes < bytes_min) | 183 if (!bytes_min || bytes < bytes_min) |
| 216 bytes_min = bytes; | 184 bytes_min = bytes; |
| 217 } | 185 } |
| 218 #endif | |
| 219 } | 186 } |
| 220 | 187 |
| 221 #if defined(OS_ANDROID) | |
| 222 bytes_available_gpu_memory_ = CalcAvailableFromViewportArea(max_surface_area); | |
| 223 #else | |
| 224 if (!bytes_min) | 188 if (!bytes_min) |
| 225 return; | 189 return; |
| 226 | 190 |
| 191 #if defined(OS_ANDROID) | |
| 192 // We don't need to reduce the total on Android, since | |
|
ccameron
2013/02/12 01:56:23
Nit: can you put this #if inside CalcAvialbleFromG
| |
| 193 // the total is an estimate to begin with. | |
| 194 bytes_available_gpu_memory_ = bytes_min; | |
| 195 #else | |
| 227 bytes_available_gpu_memory_ = CalcAvailableFromGpuTotal(bytes_min); | 196 bytes_available_gpu_memory_ = CalcAvailableFromGpuTotal(bytes_min); |
| 228 #endif | 197 #endif |
| 229 | 198 |
| 230 // Never go below the default allocation | 199 // Never go below the default allocation |
| 231 bytes_available_gpu_memory_ = std::max(bytes_available_gpu_memory_, | 200 bytes_available_gpu_memory_ = std::max(bytes_available_gpu_memory_, |
| 232 GetDefaultAvailableGpuMemory()); | 201 GetDefaultAvailableGpuMemory()); |
| 233 | 202 |
| 234 // Never go above the maximum. | 203 // Never go above the maximum. |
| 235 bytes_available_gpu_memory_ = std::min(bytes_available_gpu_memory_, | 204 bytes_available_gpu_memory_ = std::min(bytes_available_gpu_memory_, |
| 236 GetMaximumTotalGpuMemory()); | 205 GetMaximumTotalGpuMemory()); |
| (...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1046 | 1015 |
| 1047 void GpuMemoryManager::RemoveClientFromList( | 1016 void GpuMemoryManager::RemoveClientFromList( |
| 1048 GpuMemoryManagerClientState* client_state) { | 1017 GpuMemoryManagerClientState* client_state) { |
| 1049 DCHECK(client_state->list_iterator_valid_); | 1018 DCHECK(client_state->list_iterator_valid_); |
| 1050 ClientStateList* client_list = GetClientList(client_state); | 1019 ClientStateList* client_list = GetClientList(client_state); |
| 1051 client_list->erase(client_state->list_iterator_); | 1020 client_list->erase(client_state->list_iterator_); |
| 1052 client_state->list_iterator_valid_ = false; | 1021 client_state->list_iterator_valid_ = false; |
| 1053 } | 1022 } |
| 1054 | 1023 |
| 1055 } // namespace content | 1024 } // namespace content |
| OLD | NEW |