OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "android_webview/browser/hardware_renderer.h" | 5 #include "android_webview/browser/hardware_renderer.h" |
6 | 6 |
7 #include "android_webview/browser/aw_gl_surface.h" | 7 #include "android_webview/browser/aw_gl_surface.h" |
8 #include "android_webview/browser/browser_view_renderer_client.h" | 8 #include "android_webview/browser/browser_view_renderer_client.h" |
9 #include "android_webview/browser/gl_view_renderer_manager.h" | |
10 #include "android_webview/browser/scoped_app_gl_state_restore.h" | 9 #include "android_webview/browser/scoped_app_gl_state_restore.h" |
11 #include "android_webview/public/browser/draw_gl.h" | 10 #include "android_webview/public/browser/draw_gl.h" |
12 #include "base/command_line.h" | 11 #include "base/command_line.h" |
13 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
14 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
15 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
16 #include "content/public/common/content_switches.h" | 15 #include "content/public/common/content_switches.h" |
17 #include "gpu/command_buffer/service/shader_translator_cache.h" | 16 #include "gpu/command_buffer/service/shader_translator_cache.h" |
| 17 #include "third_party/skia/include/core/SkBitmap.h" |
| 18 #include "third_party/skia/include/core/SkCanvas.h" |
18 #include "ui/gfx/geometry/rect_conversions.h" | 19 #include "ui/gfx/geometry/rect_conversions.h" |
19 #include "ui/gfx/geometry/rect_f.h" | 20 #include "ui/gfx/geometry/rect_f.h" |
20 #include "ui/gfx/transform.h" | 21 #include "ui/gfx/transform.h" |
21 | 22 |
22 using content::BrowserThread; | 23 using content::BrowserThread; |
23 | 24 |
24 namespace android_webview { | 25 namespace android_webview { |
25 | 26 |
26 namespace { | 27 namespace { |
27 | 28 |
28 // Used to calculate memory and resource allocation. Determined experimentally. | 29 // Used to calculate memory and resource allocation. Determined experimentally. |
29 const size_t g_memory_multiplier = 10; | 30 const size_t g_memory_multiplier = 10; |
30 const size_t g_num_gralloc_limit = 150; | 31 const size_t g_num_gralloc_limit = 150; |
31 const size_t kBytesPerPixel = 4; | 32 const size_t kBytesPerPixel = 4; |
32 const size_t kMemoryAllocationStep = 5 * 1024 * 1024; | 33 const size_t kMemoryAllocationStep = 5 * 1024 * 1024; |
| 34 // HardwareRenderer needs |g_num_gralloc_limit| tiles to draw quickly, but it |
| 35 // will be resource hungry if it only gets allocated less than |
| 36 // |kGrallocHungryLimit|. |
| 37 const size_t kGrallocHungryLimit = 100; |
| 38 // HardwareRenderer becomes starved if the resource request cannot be granted |
| 39 // kStarvedTimes in a row. |
| 40 const size_t kStarvedTimes = 5; |
33 | 41 |
34 base::LazyInstance<scoped_refptr<internal::DeferredGpuCommandService> > | 42 base::LazyInstance<scoped_refptr<internal::DeferredGpuCommandService> > |
35 g_service = LAZY_INSTANCE_INITIALIZER; | 43 g_service = LAZY_INSTANCE_INITIALIZER; |
36 | 44 |
37 } // namespace | 45 } // namespace |
38 | 46 |
39 HardwareRenderer::HardwareRenderer(SharedRendererState* state) | 47 HardwareRenderer::HardwareRenderer(SharedRendererState* state) |
40 : shared_renderer_state_(state), | 48 : shared_renderer_state_(state), |
41 last_egl_context_(eglGetCurrentContext()), | 49 last_egl_context_(eglGetCurrentContext()), |
42 manager_key_(GLViewRendererManager::GetInstance()->PushBack( | 50 renderer_manager_key_(GLViewRendererManager::GetInstance()->PushBack( |
43 shared_renderer_state_)) { | 51 shared_renderer_state_)), |
| 52 tile_manager_key_(GlobalTileManager::GetInstance()->PushBack(this)), |
| 53 num_hungry_(0) { |
44 DCHECK(last_egl_context_); | 54 DCHECK(last_egl_context_); |
| 55 |
45 if (!g_service.Get()) { | 56 if (!g_service.Get()) { |
46 g_service.Get() = new internal::DeferredGpuCommandService; | 57 g_service.Get() = new internal::DeferredGpuCommandService; |
47 content::SynchronousCompositor::SetGpuService(g_service.Get()); | 58 content::SynchronousCompositor::SetGpuService(g_service.Get()); |
48 } | 59 } |
49 | 60 |
50 ScopedAppGLStateRestore state_restore( | 61 ScopedAppGLStateRestore state_restore( |
51 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | 62 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
52 internal::ScopedAllowGL allow_gl; | 63 internal::ScopedAllowGL allow_gl; |
53 | 64 |
54 gl_surface_ = new AwGLSurface; | 65 gl_surface_ = new AwGLSurface; |
55 bool success = | 66 bool success = |
56 shared_renderer_state_->GetCompositor()-> | 67 shared_renderer_state_->GetCompositor()-> |
57 InitializeHwDraw(gl_surface_); | 68 InitializeHwDraw(gl_surface_); |
58 DCHECK(success); | 69 DCHECK(success); |
59 } | 70 } |
60 | 71 |
61 HardwareRenderer::~HardwareRenderer() { | 72 HardwareRenderer::~HardwareRenderer() { |
62 GLViewRendererManager* mru = GLViewRendererManager::GetInstance(); | 73 GLViewRendererManager* render_manager = GLViewRendererManager::GetInstance(); |
63 mru->Remove(manager_key_); | 74 render_manager->Remove(renderer_manager_key_); |
| 75 |
| 76 GlobalTileManager* tile_manager = GlobalTileManager::GetInstance(); |
| 77 tile_manager->RequestTiles( |
| 78 memory_policy_.num_resources_limit, 0, IsStarved(), tile_manager_key_); |
| 79 tile_manager->Remove(tile_manager_key_); |
64 | 80 |
65 ScopedAppGLStateRestore state_restore( | 81 ScopedAppGLStateRestore state_restore( |
66 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | 82 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
67 internal::ScopedAllowGL allow_gl; | 83 internal::ScopedAllowGL allow_gl; |
68 | 84 |
69 shared_renderer_state_->GetCompositor()->ReleaseHwDraw(); | 85 shared_renderer_state_->GetCompositor()->ReleaseHwDraw(); |
70 gl_surface_ = NULL; | 86 gl_surface_ = NULL; |
71 } | 87 } |
72 | 88 |
73 bool HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info, DrawGLResult* result) { | 89 bool HardwareRenderer::DrawGL(AwDrawGLInfo* draw_info, DrawGLResult* result) { |
74 TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL"); | 90 TRACE_EVENT0("android_webview", "HardwareRenderer::DrawGL"); |
75 GLViewRendererManager::GetInstance()->DidDrawGL(manager_key_); | 91 GLViewRendererManager::GetInstance()->DidDrawGL(renderer_manager_key_); |
| 92 GlobalTileManager::GetInstance()->DidDrawGL(tile_manager_key_); |
76 const DrawGLInput input = shared_renderer_state_->GetDrawGLInput(); | 93 const DrawGLInput input = shared_renderer_state_->GetDrawGLInput(); |
77 | 94 |
78 // We need to watch if the current Android context has changed and enforce | 95 // We need to watch if the current Android context has changed and enforce |
79 // a clean-up in the compositor. | 96 // a clean-up in the compositor. |
80 EGLContext current_context = eglGetCurrentContext(); | 97 EGLContext current_context = eglGetCurrentContext(); |
81 if (!current_context) { | 98 if (!current_context) { |
82 DLOG(ERROR) << "DrawGL called without EGLContext"; | 99 DLOG(ERROR) << "DrawGL called without EGLContext"; |
83 return false; | 100 return false; |
84 } | 101 } |
85 | 102 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 | 177 |
161 if (!eglGetCurrentContext()) { | 178 if (!eglGetCurrentContext()) { |
162 NOTREACHED(); | 179 NOTREACHED(); |
163 return false; | 180 return false; |
164 } | 181 } |
165 | 182 |
166 DCHECK_EQ(last_egl_context_, eglGetCurrentContext()); | 183 DCHECK_EQ(last_egl_context_, eglGetCurrentContext()); |
167 | 184 |
168 // Just set the memory limit to 0 and drop all tiles. This will be reset to | 185 // Just set the memory limit to 0 and drop all tiles. This will be reset to |
169 // normal levels in the next DrawGL call. | 186 // normal levels in the next DrawGL call. |
170 content::SynchronousCompositorMemoryPolicy policy; | 187 content::SynchronousCompositorMemoryPolicy zero_policy; |
171 policy.bytes_limit = 0; | 188 if (memory_policy_ == zero_policy) |
172 policy.num_resources_limit = 0; | |
173 if (memory_policy_ == policy) | |
174 return false; | 189 return false; |
175 | 190 |
176 TRACE_EVENT0("android_webview", "HardwareRenderer::TrimMemory"); | 191 TRACE_EVENT0("android_webview", "HardwareRenderer::TrimMemory"); |
177 ScopedAppGLStateRestore state_restore( | 192 ScopedAppGLStateRestore state_restore( |
178 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); | 193 ScopedAppGLStateRestore::MODE_RESOURCE_MANAGEMENT); |
179 internal::ScopedAllowGL allow_gl; | 194 internal::ScopedAllowGL allow_gl; |
180 | 195 |
181 SetMemoryPolicy(policy); | 196 SetMemoryPolicy(zero_policy); |
182 return true; | 197 return true; |
183 } | 198 } |
184 | 199 |
185 void HardwareRenderer::SetMemoryPolicy( | 200 void HardwareRenderer::SetMemoryPolicy( |
186 content::SynchronousCompositorMemoryPolicy& new_policy) { | 201 content::SynchronousCompositorMemoryPolicy& new_policy) { |
187 if (memory_policy_ == new_policy) | 202 if (memory_policy_ == new_policy) |
188 return; | 203 return; |
189 | 204 |
| 205 GlobalTileManager* tile_manager = GlobalTileManager::GetInstance(); |
| 206 |
| 207 size_t num_tiles = tile_manager-> |
| 208 RequestTiles(memory_policy_.num_resources_limit, |
| 209 new_policy.num_resources_limit, IsStarved(), tile_manager_key_); |
| 210 |
| 211 if (num_tiles < |
| 212 std::min(kGrallocHungryLimit, new_policy.num_resources_limit)) |
| 213 num_hungry_++; |
| 214 else |
| 215 num_hungry_ = 0; |
| 216 |
| 217 |
| 218 new_policy.num_resources_limit = num_tiles; |
| 219 |
| 220 shared_renderer_state_->GetCompositor()-> |
| 221 SetMemoryPolicy(new_policy); |
190 memory_policy_ = new_policy; | 222 memory_policy_ = new_policy; |
| 223 } |
| 224 |
| 225 bool HardwareRenderer::IsStarved() { |
| 226 // If the hardware renderer is hungry for kStarvedTimes in a row, this |
| 227 // hardware renderer is considered starved. |
| 228 return (num_hungry_ >= kStarvedTimes); |
| 229 } |
| 230 |
| 231 size_t HardwareRenderer::ForceDropTiles() { |
| 232 size_t dropped_tiles = memory_policy_.num_resources_limit; |
| 233 content::SynchronousCompositorMemoryPolicy zero_policy; |
| 234 memory_policy_ = zero_policy; |
191 shared_renderer_state_->GetCompositor()-> | 235 shared_renderer_state_->GetCompositor()-> |
192 SetMemoryPolicy(memory_policy_); | 236 SetMemoryPolicy(zero_policy); |
| 237 |
| 238 |
| 239 // Now force a fake SW draw to make sure the tiles are dropped because the |
| 240 // tile manager only manages tiles after a Draw. |
| 241 // Making a fake SW draw is a hacky way to forcibly drop tiles. Maybe we can |
| 242 // find better implementations. |
| 243 SkBitmap bitmap; |
| 244 bitmap.allocN32Pixels(1, 1); |
| 245 bitmap.eraseColor(0); |
| 246 SkCanvas canvas(bitmap); |
| 247 |
| 248 shared_renderer_state_->GetCompositor()->DemandDrawSw(&canvas); |
| 249 return dropped_tiles; |
193 } | 250 } |
194 | 251 |
195 // static | 252 // static |
196 void HardwareRenderer::CalculateTileMemoryPolicy() { | 253 void HardwareRenderer::CalculateTileMemoryPolicy() { |
197 CommandLine* cl = CommandLine::ForCurrentProcess(); | 254 CommandLine* cl = CommandLine::ForCurrentProcess(); |
198 | 255 |
199 const char kDefaultTileSize[] = "384"; | 256 const char kDefaultTileSize[] = "384"; |
200 if (!cl->HasSwitch(switches::kDefaultTileWidth)) | 257 if (!cl->HasSwitch(switches::kDefaultTileWidth)) |
201 cl->AppendSwitchASCII(switches::kDefaultTileWidth, kDefaultTileSize); | 258 cl->AppendSwitchASCII(switches::kDefaultTileWidth, kDefaultTileSize); |
202 | 259 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); | 352 base::RefCountedThreadSafe<DeferredGpuCommandService>::AddRef(); |
296 } | 353 } |
297 | 354 |
298 void DeferredGpuCommandService::Release() const { | 355 void DeferredGpuCommandService::Release() const { |
299 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); | 356 base::RefCountedThreadSafe<DeferredGpuCommandService>::Release(); |
300 } | 357 } |
301 | 358 |
302 } // namespace internal | 359 } // namespace internal |
303 | 360 |
304 } // namespace android_webview | 361 } // namespace android_webview |
OLD | NEW |