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/browser_view_renderer.h" | 5 #include "android_webview/browser/browser_view_renderer.h" |
6 | 6 |
7 #include "android_webview/browser/browser_view_renderer_client.h" | 7 #include "android_webview/browser/browser_view_renderer_client.h" |
8 #include "android_webview/browser/shared_renderer_state.h" | 8 #include "android_webview/browser/shared_renderer_state.h" |
9 #include "android_webview/common/aw_switches.h" | 9 #include "android_webview/common/aw_switches.h" |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/debug/trace_event_argument.h" | 12 #include "base/debug/trace_event_argument.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "cc/output/compositor_frame.h" | 16 #include "cc/output/compositor_frame.h" |
17 #include "content/public/browser/web_contents.h" | 17 #include "content/public/browser/web_contents.h" |
18 #include "content/public/common/content_switches.h" | 18 #include "content/public/common/content_switches.h" |
19 #include "gpu/command_buffer/service/gpu_switches.h" | 19 #include "gpu/command_buffer/service/gpu_switches.h" |
20 #include "third_party/skia/include/core/SkBitmap.h" | 20 #include "third_party/skia/include/core/SkBitmap.h" |
21 #include "third_party/skia/include/core/SkCanvas.h" | 21 #include "third_party/skia/include/core/SkCanvas.h" |
22 #include "third_party/skia/include/core/SkPicture.h" | 22 #include "third_party/skia/include/core/SkPicture.h" |
23 #include "third_party/skia/include/core/SkPictureRecorder.h" | 23 #include "third_party/skia/include/core/SkPictureRecorder.h" |
24 #include "ui/gfx/geometry/vector2d_conversions.h" | 24 #include "ui/gfx/geometry/vector2d_conversions.h" |
25 | 25 |
26 using content::SynchronousCompositorMemoryPolicy; | |
27 | |
28 namespace android_webview { | 26 namespace android_webview { |
29 | 27 |
30 namespace { | 28 namespace { |
31 | 29 |
32 const int64 kFallbackTickTimeoutInMilliseconds = 100; | 30 const int64 kFallbackTickTimeoutInMilliseconds = 100; |
33 | 31 |
34 // Used to calculate memory allocation. Determined experimentally. | 32 // Used to calculate memory allocation. Determined experimentally. |
35 const size_t kMemoryMultiplier = 20; | 33 const size_t kMemoryMultiplier = 20; |
36 const size_t kBytesPerPixel = 4; | 34 const size_t kBytesPerPixel = 4; |
37 const size_t kMemoryAllocationStep = 5 * 1024 * 1024; | 35 const size_t kMemoryAllocationStep = 5 * 1024 * 1024; |
38 uint64 g_memory_override_in_bytes = 0u; | 36 uint64 g_memory_override_in_bytes = 0u; |
39 | 37 |
40 // Used to calculate tile allocation. Determined experimentally. | |
41 const size_t kTileMultiplier = 12; | |
42 const size_t kTileAllocationStep = 20; | |
43 // Use chrome's default tile size, which varies from 256 to 512. | |
44 // Be conservative here and use the smallest tile size possible. | |
45 const size_t kTileArea = 256 * 256; | |
46 | |
47 } // namespace | 38 } // namespace |
48 | 39 |
49 // static | 40 // static |
50 void BrowserViewRenderer::CalculateTileMemoryPolicy() { | 41 void BrowserViewRenderer::CalculateTileMemoryPolicy() { |
51 CommandLine* cl = CommandLine::ForCurrentProcess(); | 42 CommandLine* cl = CommandLine::ForCurrentProcess(); |
52 | 43 |
53 // If the value was overridden on the command line, use the specified value. | 44 // If the value was overridden on the command line, use the specified value. |
54 bool client_hard_limit_bytes_overridden = | 45 bool client_hard_limit_bytes_overridden = |
55 cl->HasSwitch(switches::kForceGpuMemAvailableMb); | 46 cl->HasSwitch(switches::kForceGpuMemAvailableMb); |
56 if (client_hard_limit_bytes_overridden) { | 47 if (client_hard_limit_bytes_overridden) { |
57 base::StringToUint64( | 48 base::StringToUint64( |
58 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 49 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
59 switches::kForceGpuMemAvailableMb), | 50 switches::kForceGpuMemAvailableMb), |
60 &g_memory_override_in_bytes); | 51 &g_memory_override_in_bytes); |
61 g_memory_override_in_bytes *= 1024 * 1024; | 52 g_memory_override_in_bytes *= 1024 * 1024; |
62 } | 53 } |
63 | |
64 // There is no need to limit number of tiles, so use an effectively unlimited | |
65 // value as the limit. | |
66 GlobalTileManager::GetInstance()->SetTileLimit(10 * 1000 * 1000); | |
67 } | 54 } |
68 | 55 |
69 BrowserViewRenderer::BrowserViewRenderer( | 56 BrowserViewRenderer::BrowserViewRenderer( |
70 BrowserViewRendererClient* client, | 57 BrowserViewRendererClient* client, |
71 content::WebContents* web_contents, | 58 content::WebContents* web_contents, |
72 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) | 59 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) |
73 : client_(client), | 60 : client_(client), |
74 shared_renderer_state_(ui_task_runner, this), | 61 shared_renderer_state_(ui_task_runner, this), |
75 web_contents_(web_contents), | 62 web_contents_(web_contents), |
76 ui_task_runner_(ui_task_runner), | 63 ui_task_runner_(ui_task_runner), |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because | 111 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because |
125 // it does not indicate memory pressure, but merely that the app is | 112 // it does not indicate memory pressure, but merely that the app is |
126 // backgrounded. | 113 // backgrounded. |
127 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN) | 114 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN) |
128 return; | 115 return; |
129 | 116 |
130 // Do not release resources on view we expect to get DrawGL soon. | 117 // Do not release resources on view we expect to get DrawGL soon. |
131 if (level < TRIM_MEMORY_BACKGROUND && visible) | 118 if (level < TRIM_MEMORY_BACKGROUND && visible) |
132 return; | 119 return; |
133 | 120 |
134 // Just set the memory limit to 0 and drop all tiles. This will be reset to | 121 // Nothing to drop. |
135 // normal levels in the next DrawGL call. | 122 if (!compositor_ || !hardware_enabled_) |
136 SynchronousCompositorMemoryPolicy zero_policy; | |
137 if (memory_policy_ == zero_policy) | |
138 return; | 123 return; |
139 | 124 |
140 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory"); | 125 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory"); |
141 DCHECK(hardware_enabled_); | |
142 DCHECK(compositor_); | |
143 | 126 |
144 RequestMemoryPolicy(zero_policy); | 127 // Just set the memory limit to 0 and drop all tiles. This will be reset to |
145 EnforceMemoryPolicyImmediately(zero_policy); | 128 // normal levels in the next DrawGL call. |
146 } | 129 compositor_->SetMemoryPolicy(0u); |
147 | |
148 SynchronousCompositorMemoryPolicy | |
149 BrowserViewRenderer::CalculateDesiredMemoryPolicy() { | |
150 SynchronousCompositorMemoryPolicy policy; | |
151 size_t width = last_on_draw_global_visible_rect_.width(); | |
152 size_t height = last_on_draw_global_visible_rect_.height(); | |
153 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height; | |
154 // Round up to a multiple of kMemoryAllocationStep. | |
155 policy.bytes_limit = | |
156 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep; | |
157 | |
158 if (g_memory_override_in_bytes) | |
159 policy.bytes_limit = static_cast<size_t>(g_memory_override_in_bytes); | |
160 | |
161 size_t tiles = width * height * kTileMultiplier / kTileArea; | |
162 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles | |
163 // is also kTileAllocationStep. | |
164 tiles = (tiles / kTileAllocationStep + 1) * kTileAllocationStep; | |
165 policy.num_resources_limit = tiles; | |
166 return policy; | |
167 } | |
168 | |
169 // This function updates the cached memory policy in shared renderer state, as | |
170 // well as the tile resource allocation in GlobalTileManager. | |
171 void BrowserViewRenderer::RequestMemoryPolicy( | |
172 SynchronousCompositorMemoryPolicy& new_policy) { | |
173 DCHECK(compositor_); | |
174 GlobalTileManager* manager = GlobalTileManager::GetInstance(); | |
175 | |
176 // The following line will call BrowserViewRenderer::SetMemoryPolicy(). | |
177 manager->RequestTiles(new_policy, tile_manager_key_); | |
178 } | |
179 | |
180 void BrowserViewRenderer::SetMemoryPolicy( | |
181 SynchronousCompositorMemoryPolicy new_policy, | |
182 bool effective_immediately) { | |
183 memory_policy_ = new_policy; | |
184 if (effective_immediately) | |
185 EnforceMemoryPolicyImmediately(memory_policy_); | |
186 } | |
187 | |
188 void BrowserViewRenderer::EnforceMemoryPolicyImmediately( | |
189 SynchronousCompositorMemoryPolicy new_policy) { | |
190 compositor_->SetMemoryPolicy(new_policy); | |
191 ForceFakeCompositeSW(); | 130 ForceFakeCompositeSW(); |
192 } | 131 } |
193 | 132 |
194 SynchronousCompositorMemoryPolicy BrowserViewRenderer::GetMemoryPolicy() const { | 133 size_t BrowserViewRenderer::CalculateDesiredMemoryPolicy() { |
195 return memory_policy_; | 134 if (g_memory_override_in_bytes) |
| 135 return static_cast<size_t>(g_memory_override_in_bytes); |
| 136 |
| 137 size_t width = last_on_draw_global_visible_rect_.width(); |
| 138 size_t height = last_on_draw_global_visible_rect_.height(); |
| 139 size_t bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height; |
| 140 // Round up to a multiple of kMemoryAllocationStep. |
| 141 bytes_limit = |
| 142 (bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep; |
| 143 return bytes_limit; |
196 } | 144 } |
197 | 145 |
198 bool BrowserViewRenderer::OnDraw(jobject java_canvas, | 146 bool BrowserViewRenderer::OnDraw(jobject java_canvas, |
199 bool is_hardware_canvas, | 147 bool is_hardware_canvas, |
200 const gfx::Vector2d& scroll, | 148 const gfx::Vector2d& scroll, |
201 const gfx::Rect& global_visible_rect) { | 149 const gfx::Rect& global_visible_rect) { |
202 last_on_draw_scroll_offset_ = scroll; | 150 last_on_draw_scroll_offset_ = scroll; |
203 last_on_draw_global_visible_rect_ = global_visible_rect; | 151 last_on_draw_global_visible_rect_ = global_visible_rect; |
204 | 152 |
205 if (clear_view_) | 153 if (clear_view_) |
(...skipping 10 matching lines...) Expand all Loading... |
216 | 164 |
217 bool BrowserViewRenderer::OnDrawHardware() { | 165 bool BrowserViewRenderer::OnDrawHardware() { |
218 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware"); | 166 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware"); |
219 if (!compositor_) | 167 if (!compositor_) |
220 return false; | 168 return false; |
221 | 169 |
222 shared_renderer_state_.SetScrollOffsetOnUI(last_on_draw_scroll_offset_); | 170 shared_renderer_state_.SetScrollOffsetOnUI(last_on_draw_scroll_offset_); |
223 | 171 |
224 if (!hardware_enabled_) { | 172 if (!hardware_enabled_) { |
225 hardware_enabled_ = compositor_->InitializeHwDraw(); | 173 hardware_enabled_ = compositor_->InitializeHwDraw(); |
226 if (hardware_enabled_) { | |
227 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this); | |
228 } | |
229 } | 174 } |
230 if (!hardware_enabled_) | 175 if (!hardware_enabled_) |
231 return false; | 176 return false; |
232 | 177 |
233 if (last_on_draw_global_visible_rect_.IsEmpty() && | 178 if (last_on_draw_global_visible_rect_.IsEmpty() && |
234 parent_draw_constraints_.surface_rect.IsEmpty()) { | 179 parent_draw_constraints_.surface_rect.IsEmpty()) { |
235 TRACE_EVENT_INSTANT0("android_webview", | 180 TRACE_EVENT_INSTANT0("android_webview", |
236 "EarlyOut_EmptyVisibleRect", | 181 "EarlyOut_EmptyVisibleRect", |
237 TRACE_EVENT_SCOPE_THREAD); | 182 TRACE_EVENT_SCOPE_THREAD); |
238 shared_renderer_state_.SetForceInvalidateOnNextDrawGLOnUI(true); | 183 shared_renderer_state_.SetForceInvalidateOnNextDrawGLOnUI(true); |
239 return true; | 184 return true; |
240 } | 185 } |
241 | 186 |
242 ReturnResourceFromParent(); | 187 ReturnResourceFromParent(); |
243 if (shared_renderer_state_.HasCompositorFrameOnUI()) { | 188 if (shared_renderer_state_.HasCompositorFrameOnUI()) { |
244 TRACE_EVENT_INSTANT0("android_webview", | 189 TRACE_EVENT_INSTANT0("android_webview", |
245 "EarlyOut_PreviousFrameUnconsumed", | 190 "EarlyOut_PreviousFrameUnconsumed", |
246 TRACE_EVENT_SCOPE_THREAD); | 191 TRACE_EVENT_SCOPE_THREAD); |
247 DidSkipCompositeInDraw(); | 192 DidSkipCompositeInDraw(); |
248 return true; | 193 return true; |
249 } | 194 } |
250 | 195 |
251 scoped_ptr<cc::CompositorFrame> frame = CompositeHw(); | 196 scoped_ptr<cc::CompositorFrame> frame = CompositeHw(); |
252 if (!frame.get()) | 197 if (!frame.get()) |
253 return false; | 198 return false; |
254 | 199 |
255 shared_renderer_state_.SetCompositorFrameOnUI(frame.Pass(), false); | 200 shared_renderer_state_.SetCompositorFrameOnUI(frame.Pass(), false); |
256 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_); | |
257 return true; | 201 return true; |
258 } | 202 } |
259 | 203 |
260 scoped_ptr<cc::CompositorFrame> BrowserViewRenderer::CompositeHw() { | 204 scoped_ptr<cc::CompositorFrame> BrowserViewRenderer::CompositeHw() { |
261 SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy(); | 205 compositor_->SetMemoryPolicy(CalculateDesiredMemoryPolicy()); |
262 RequestMemoryPolicy(new_policy); | |
263 compositor_->SetMemoryPolicy(memory_policy_); | |
264 | 206 |
265 parent_draw_constraints_ = | 207 parent_draw_constraints_ = |
266 shared_renderer_state_.GetParentDrawConstraintsOnUI(); | 208 shared_renderer_state_.GetParentDrawConstraintsOnUI(); |
267 gfx::Size surface_size(width_, height_); | 209 gfx::Size surface_size(width_, height_); |
268 gfx::Rect viewport(surface_size); | 210 gfx::Rect viewport(surface_size); |
269 gfx::Rect clip = viewport; | 211 gfx::Rect clip = viewport; |
270 gfx::Transform transform_for_tile_priority = | 212 gfx::Transform transform_for_tile_priority = |
271 parent_draw_constraints_.transform; | 213 parent_draw_constraints_.transform; |
272 | 214 |
273 // If the WebView is on a layer, WebView does not know what transform is | 215 // If the WebView is on a layer, WebView does not know what transform is |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 void BrowserViewRenderer::ReleaseHardware() { | 396 void BrowserViewRenderer::ReleaseHardware() { |
455 DCHECK(hardware_enabled_); | 397 DCHECK(hardware_enabled_); |
456 // TODO(hush): do this in somewhere else. Either in hardware render or in | 398 // TODO(hush): do this in somewhere else. Either in hardware render or in |
457 // shared renderer state. | 399 // shared renderer state. |
458 ReturnUnusedResource(shared_renderer_state_.PassCompositorFrame()); | 400 ReturnUnusedResource(shared_renderer_state_.PassCompositorFrame()); |
459 ReturnResourceFromParent(); | 401 ReturnResourceFromParent(); |
460 DCHECK(shared_renderer_state_.ReturnedResourcesEmpty()); | 402 DCHECK(shared_renderer_state_.ReturnedResourcesEmpty()); |
461 | 403 |
462 if (compositor_) { | 404 if (compositor_) { |
463 compositor_->ReleaseHwDraw(); | 405 compositor_->ReleaseHwDraw(); |
464 SynchronousCompositorMemoryPolicy zero_policy; | |
465 RequestMemoryPolicy(zero_policy); | |
466 } | 406 } |
467 | 407 |
468 hardware_enabled_ = false; | 408 hardware_enabled_ = false; |
469 GlobalTileManager::GetInstance()->Remove(tile_manager_key_); | |
470 } | 409 } |
471 | 410 |
472 bool BrowserViewRenderer::IsVisible() const { | 411 bool BrowserViewRenderer::IsVisible() const { |
473 // Ignore |window_visible_| if |attached_to_window_| is false. | 412 // Ignore |window_visible_| if |attached_to_window_| is false. |
474 return view_visible_ && (!attached_to_window_ || window_visible_); | 413 return view_visible_ && (!attached_to_window_ || window_visible_); |
475 } | 414 } |
476 | 415 |
477 gfx::Rect BrowserViewRenderer::GetScreenRect() const { | 416 gfx::Rect BrowserViewRenderer::GetScreenRect() const { |
478 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_)); | 417 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_)); |
479 } | 418 } |
480 | 419 |
481 void BrowserViewRenderer::DidInitializeCompositor( | 420 void BrowserViewRenderer::DidInitializeCompositor( |
482 content::SynchronousCompositor* compositor) { | 421 content::SynchronousCompositor* compositor) { |
483 TRACE_EVENT0("android_webview", | 422 TRACE_EVENT0("android_webview", |
484 "BrowserViewRenderer::DidInitializeCompositor"); | 423 "BrowserViewRenderer::DidInitializeCompositor"); |
485 DCHECK(compositor); | 424 DCHECK(compositor); |
486 DCHECK(!compositor_); | 425 DCHECK(!compositor_); |
487 compositor_ = compositor; | 426 compositor_ = compositor; |
488 } | 427 } |
489 | 428 |
490 void BrowserViewRenderer::DidDestroyCompositor( | 429 void BrowserViewRenderer::DidDestroyCompositor( |
491 content::SynchronousCompositor* compositor) { | 430 content::SynchronousCompositor* compositor) { |
492 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); | 431 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); |
493 DCHECK(compositor_); | 432 DCHECK(compositor_); |
494 SynchronousCompositorMemoryPolicy zero_policy; | |
495 if (hardware_enabled_) { | |
496 RequestMemoryPolicy(zero_policy); | |
497 } | |
498 DCHECK(memory_policy_ == zero_policy); | |
499 compositor_ = NULL; | 433 compositor_ = NULL; |
500 } | 434 } |
501 | 435 |
502 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { | 436 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { |
503 if (compositor_needs_continuous_invalidate_ == invalidate) | 437 if (compositor_needs_continuous_invalidate_ == invalidate) |
504 return; | 438 return; |
505 | 439 |
506 TRACE_EVENT_INSTANT1("android_webview", | 440 TRACE_EVENT_INSTANT1("android_webview", |
507 "BrowserViewRenderer::SetContinuousInvalidate", | 441 "BrowserViewRenderer::SetContinuousInvalidate", |
508 TRACE_EVENT_SCOPE_THREAD, | 442 TRACE_EVENT_SCOPE_THREAD, |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 base::StringAppendF(&str, | 753 base::StringAppendF(&str, |
820 "overscroll_rounding_error_: %s ", | 754 "overscroll_rounding_error_: %s ", |
821 overscroll_rounding_error_.ToString().c_str()); | 755 overscroll_rounding_error_.ToString().c_str()); |
822 base::StringAppendF( | 756 base::StringAppendF( |
823 &str, "on_new_picture_enable: %d ", on_new_picture_enable_); | 757 &str, "on_new_picture_enable: %d ", on_new_picture_enable_); |
824 base::StringAppendF(&str, "clear_view: %d ", clear_view_); | 758 base::StringAppendF(&str, "clear_view: %d ", clear_view_); |
825 return str; | 759 return str; |
826 } | 760 } |
827 | 761 |
828 } // namespace android_webview | 762 } // namespace android_webview |
OLD | NEW |