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 SharedRendererState* shared_renderer_state, | 58 SharedRendererState* shared_renderer_state, |
72 content::WebContents* web_contents, | 59 content::WebContents* web_contents, |
73 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) | 60 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) |
74 : client_(client), | 61 : client_(client), |
75 shared_renderer_state_(shared_renderer_state), | 62 shared_renderer_state_(shared_renderer_state), |
76 web_contents_(web_contents), | 63 web_contents_(web_contents), |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because | 104 // Not urgent enough. TRIM_MEMORY_UI_HIDDEN is treated specially because |
118 // it does not indicate memory pressure, but merely that the app is | 105 // it does not indicate memory pressure, but merely that the app is |
119 // backgrounded. | 106 // backgrounded. |
120 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN) | 107 if (level < TRIM_MEMORY_RUNNING_LOW || level == TRIM_MEMORY_UI_HIDDEN) |
121 return; | 108 return; |
122 | 109 |
123 // Do not release resources on view we expect to get DrawGL soon. | 110 // Do not release resources on view we expect to get DrawGL soon. |
124 if (level < TRIM_MEMORY_BACKGROUND && visible) | 111 if (level < TRIM_MEMORY_BACKGROUND && visible) |
125 return; | 112 return; |
126 | 113 |
127 // Just set the memory limit to 0 and drop all tiles. This will be reset to | 114 // Nothing to drop. |
128 // normal levels in the next DrawGL call. | 115 if (!compositor_ || !hardware_enabled_) |
129 SynchronousCompositorMemoryPolicy zero_policy; | |
130 if (memory_policy_ == zero_policy) | |
131 return; | 116 return; |
132 | 117 |
133 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory"); | 118 TRACE_EVENT0("android_webview", "BrowserViewRenderer::TrimMemory"); |
134 DCHECK(hardware_enabled_); | |
135 DCHECK(compositor_); | |
136 | 119 |
137 RequestMemoryPolicy(zero_policy); | 120 // Just set the memory limit to 0 and drop all tiles. This will be reset to |
138 EnforceMemoryPolicyImmediately(zero_policy); | 121 // normal levels in the next DrawGL call. |
139 } | 122 compositor_->SetMemoryPolicy(0u); |
hush (inactive)
2014/10/24 23:36:37
do you need to enforce it immediately right here?
boliu
2014/10/24 23:37:53
It is enforce it once line below. There's just a h
hush (inactive)
2014/10/24 23:49:59
oops. Yes. Thanks!
| |
140 | |
141 SynchronousCompositorMemoryPolicy | |
142 BrowserViewRenderer::CalculateDesiredMemoryPolicy() { | |
143 SynchronousCompositorMemoryPolicy policy; | |
144 size_t width = last_on_draw_global_visible_rect_.width(); | |
145 size_t height = last_on_draw_global_visible_rect_.height(); | |
146 policy.bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height; | |
147 // Round up to a multiple of kMemoryAllocationStep. | |
148 policy.bytes_limit = | |
149 (policy.bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep; | |
150 | |
151 if (g_memory_override_in_bytes) | |
152 policy.bytes_limit = static_cast<size_t>(g_memory_override_in_bytes); | |
153 | |
154 size_t tiles = width * height * kTileMultiplier / kTileArea; | |
155 // Round up to a multiple of kTileAllocationStep. The minimum number of tiles | |
156 // is also kTileAllocationStep. | |
157 tiles = (tiles / kTileAllocationStep + 1) * kTileAllocationStep; | |
158 policy.num_resources_limit = tiles; | |
159 return policy; | |
160 } | |
161 | |
162 // This function updates the cached memory policy in shared renderer state, as | |
163 // well as the tile resource allocation in GlobalTileManager. | |
164 void BrowserViewRenderer::RequestMemoryPolicy( | |
165 SynchronousCompositorMemoryPolicy& new_policy) { | |
166 DCHECK(compositor_); | |
167 GlobalTileManager* manager = GlobalTileManager::GetInstance(); | |
168 | |
169 // The following line will call BrowserViewRenderer::SetMemoryPolicy(). | |
170 manager->RequestTiles(new_policy, tile_manager_key_); | |
171 } | |
172 | |
173 void BrowserViewRenderer::SetMemoryPolicy( | |
174 SynchronousCompositorMemoryPolicy new_policy, | |
175 bool effective_immediately) { | |
176 memory_policy_ = new_policy; | |
177 if (effective_immediately) | |
178 EnforceMemoryPolicyImmediately(memory_policy_); | |
179 } | |
180 | |
181 void BrowserViewRenderer::EnforceMemoryPolicyImmediately( | |
182 SynchronousCompositorMemoryPolicy new_policy) { | |
183 compositor_->SetMemoryPolicy(new_policy); | |
184 ForceFakeCompositeSW(); | 123 ForceFakeCompositeSW(); |
185 } | 124 } |
186 | 125 |
187 SynchronousCompositorMemoryPolicy BrowserViewRenderer::GetMemoryPolicy() const { | 126 size_t BrowserViewRenderer::CalculateDesiredMemoryPolicy() { |
188 return memory_policy_; | 127 if (g_memory_override_in_bytes) |
128 return static_cast<size_t>(g_memory_override_in_bytes); | |
129 | |
130 size_t width = last_on_draw_global_visible_rect_.width(); | |
131 size_t height = last_on_draw_global_visible_rect_.height(); | |
132 size_t bytes_limit = kMemoryMultiplier * kBytesPerPixel * width * height; | |
133 // Round up to a multiple of kMemoryAllocationStep. | |
134 bytes_limit = | |
135 (bytes_limit / kMemoryAllocationStep + 1) * kMemoryAllocationStep; | |
136 return bytes_limit; | |
189 } | 137 } |
190 | 138 |
191 bool BrowserViewRenderer::OnDraw(jobject java_canvas, | 139 bool BrowserViewRenderer::OnDraw(jobject java_canvas, |
192 bool is_hardware_canvas, | 140 bool is_hardware_canvas, |
193 const gfx::Vector2d& scroll, | 141 const gfx::Vector2d& scroll, |
194 const gfx::Rect& global_visible_rect) { | 142 const gfx::Rect& global_visible_rect) { |
195 last_on_draw_scroll_offset_ = scroll; | 143 last_on_draw_scroll_offset_ = scroll; |
196 last_on_draw_global_visible_rect_ = global_visible_rect; | 144 last_on_draw_global_visible_rect_ = global_visible_rect; |
197 | 145 |
198 if (clear_view_) | 146 if (clear_view_) |
(...skipping 10 matching lines...) Expand all Loading... | |
209 | 157 |
210 bool BrowserViewRenderer::OnDrawHardware(jobject java_canvas) { | 158 bool BrowserViewRenderer::OnDrawHardware(jobject java_canvas) { |
211 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware"); | 159 TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware"); |
212 if (!compositor_) | 160 if (!compositor_) |
213 return false; | 161 return false; |
214 | 162 |
215 shared_renderer_state_->SetScrollOffset(last_on_draw_scroll_offset_); | 163 shared_renderer_state_->SetScrollOffset(last_on_draw_scroll_offset_); |
216 | 164 |
217 if (!hardware_enabled_) { | 165 if (!hardware_enabled_) { |
218 hardware_enabled_ = compositor_->InitializeHwDraw(); | 166 hardware_enabled_ = compositor_->InitializeHwDraw(); |
219 if (hardware_enabled_) { | |
220 tile_manager_key_ = GlobalTileManager::GetInstance()->PushBack(this); | |
221 } | |
222 } | 167 } |
223 if (!hardware_enabled_) | 168 if (!hardware_enabled_) |
224 return false; | 169 return false; |
225 | 170 |
226 if (last_on_draw_global_visible_rect_.IsEmpty() && | 171 if (last_on_draw_global_visible_rect_.IsEmpty() && |
227 parent_draw_constraints_.surface_rect.IsEmpty()) { | 172 parent_draw_constraints_.surface_rect.IsEmpty()) { |
228 TRACE_EVENT_INSTANT0("android_webview", | 173 TRACE_EVENT_INSTANT0("android_webview", |
229 "EarlyOut_EmptyVisibleRect", | 174 "EarlyOut_EmptyVisibleRect", |
230 TRACE_EVENT_SCOPE_THREAD); | 175 TRACE_EVENT_SCOPE_THREAD); |
231 shared_renderer_state_->SetForceInvalidateOnNextDrawGL(true); | 176 shared_renderer_state_->SetForceInvalidateOnNextDrawGL(true); |
232 return client_->RequestDrawGL(java_canvas, false); | 177 return client_->RequestDrawGL(java_canvas, false); |
233 } | 178 } |
234 | 179 |
235 ReturnResourceFromParent(); | 180 ReturnResourceFromParent(); |
236 if (shared_renderer_state_->HasCompositorFrame()) { | 181 if (shared_renderer_state_->HasCompositorFrame()) { |
237 TRACE_EVENT_INSTANT0("android_webview", | 182 TRACE_EVENT_INSTANT0("android_webview", |
238 "EarlyOut_PreviousFrameUnconsumed", | 183 "EarlyOut_PreviousFrameUnconsumed", |
239 TRACE_EVENT_SCOPE_THREAD); | 184 TRACE_EVENT_SCOPE_THREAD); |
240 DidSkipCompositeInDraw(); | 185 DidSkipCompositeInDraw(); |
241 return client_->RequestDrawGL(java_canvas, false); | 186 return client_->RequestDrawGL(java_canvas, false); |
242 } | 187 } |
243 | 188 |
244 scoped_ptr<cc::CompositorFrame> frame = CompositeHw(); | 189 scoped_ptr<cc::CompositorFrame> frame = CompositeHw(); |
245 if (!frame.get()) | 190 if (!frame.get()) |
246 return false; | 191 return false; |
247 | 192 |
248 shared_renderer_state_->SetCompositorFrame(frame.Pass(), false); | 193 shared_renderer_state_->SetCompositorFrame(frame.Pass(), false); |
249 GlobalTileManager::GetInstance()->DidUse(tile_manager_key_); | |
250 return client_->RequestDrawGL(java_canvas, false); | 194 return client_->RequestDrawGL(java_canvas, false); |
251 } | 195 } |
252 | 196 |
253 scoped_ptr<cc::CompositorFrame> BrowserViewRenderer::CompositeHw() { | 197 scoped_ptr<cc::CompositorFrame> BrowserViewRenderer::CompositeHw() { |
254 SynchronousCompositorMemoryPolicy new_policy = CalculateDesiredMemoryPolicy(); | 198 compositor_->SetMemoryPolicy(CalculateDesiredMemoryPolicy()); |
255 RequestMemoryPolicy(new_policy); | |
256 compositor_->SetMemoryPolicy(memory_policy_); | |
257 | 199 |
258 parent_draw_constraints_ = shared_renderer_state_->ParentDrawConstraints(); | 200 parent_draw_constraints_ = shared_renderer_state_->ParentDrawConstraints(); |
259 gfx::Size surface_size(width_, height_); | 201 gfx::Size surface_size(width_, height_); |
260 gfx::Rect viewport(surface_size); | 202 gfx::Rect viewport(surface_size); |
261 gfx::Rect clip = viewport; | 203 gfx::Rect clip = viewport; |
262 gfx::Transform transform_for_tile_priority = | 204 gfx::Transform transform_for_tile_priority = |
263 parent_draw_constraints_.transform; | 205 parent_draw_constraints_.transform; |
264 | 206 |
265 // If the WebView is on a layer, WebView does not know what transform is | 207 // If the WebView is on a layer, WebView does not know what transform is |
266 // applied onto the layer so global visible rect does not make sense here. | 208 // applied onto the layer so global visible rect does not make sense here. |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 } | 386 } |
445 | 387 |
446 void BrowserViewRenderer::ReleaseHardware() { | 388 void BrowserViewRenderer::ReleaseHardware() { |
447 DCHECK(hardware_enabled_); | 389 DCHECK(hardware_enabled_); |
448 ReturnUnusedResource(shared_renderer_state_->PassCompositorFrame()); | 390 ReturnUnusedResource(shared_renderer_state_->PassCompositorFrame()); |
449 ReturnResourceFromParent(); | 391 ReturnResourceFromParent(); |
450 DCHECK(shared_renderer_state_->ReturnedResourcesEmpty()); | 392 DCHECK(shared_renderer_state_->ReturnedResourcesEmpty()); |
451 | 393 |
452 if (compositor_) { | 394 if (compositor_) { |
453 compositor_->ReleaseHwDraw(); | 395 compositor_->ReleaseHwDraw(); |
454 SynchronousCompositorMemoryPolicy zero_policy; | |
455 RequestMemoryPolicy(zero_policy); | |
456 } | 396 } |
457 | 397 |
458 hardware_enabled_ = false; | 398 hardware_enabled_ = false; |
459 GlobalTileManager::GetInstance()->Remove(tile_manager_key_); | |
460 } | 399 } |
461 | 400 |
462 bool BrowserViewRenderer::IsVisible() const { | 401 bool BrowserViewRenderer::IsVisible() const { |
463 // Ignore |window_visible_| if |attached_to_window_| is false. | 402 // Ignore |window_visible_| if |attached_to_window_| is false. |
464 return view_visible_ && (!attached_to_window_ || window_visible_); | 403 return view_visible_ && (!attached_to_window_ || window_visible_); |
465 } | 404 } |
466 | 405 |
467 gfx::Rect BrowserViewRenderer::GetScreenRect() const { | 406 gfx::Rect BrowserViewRenderer::GetScreenRect() const { |
468 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_)); | 407 return gfx::Rect(client_->GetLocationOnScreen(), gfx::Size(width_, height_)); |
469 } | 408 } |
470 | 409 |
471 void BrowserViewRenderer::DidInitializeCompositor( | 410 void BrowserViewRenderer::DidInitializeCompositor( |
472 content::SynchronousCompositor* compositor) { | 411 content::SynchronousCompositor* compositor) { |
473 TRACE_EVENT0("android_webview", | 412 TRACE_EVENT0("android_webview", |
474 "BrowserViewRenderer::DidInitializeCompositor"); | 413 "BrowserViewRenderer::DidInitializeCompositor"); |
475 DCHECK(compositor); | 414 DCHECK(compositor); |
476 DCHECK(!compositor_); | 415 DCHECK(!compositor_); |
477 compositor_ = compositor; | 416 compositor_ = compositor; |
478 } | 417 } |
479 | 418 |
480 void BrowserViewRenderer::DidDestroyCompositor( | 419 void BrowserViewRenderer::DidDestroyCompositor( |
481 content::SynchronousCompositor* compositor) { | 420 content::SynchronousCompositor* compositor) { |
482 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); | 421 TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); |
483 DCHECK(compositor_); | 422 DCHECK(compositor_); |
484 SynchronousCompositorMemoryPolicy zero_policy; | |
485 if (hardware_enabled_) { | |
486 RequestMemoryPolicy(zero_policy); | |
487 } | |
488 DCHECK(memory_policy_ == zero_policy); | |
489 compositor_ = NULL; | 423 compositor_ = NULL; |
490 } | 424 } |
491 | 425 |
492 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { | 426 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { |
493 if (compositor_needs_continuous_invalidate_ == invalidate) | 427 if (compositor_needs_continuous_invalidate_ == invalidate) |
494 return; | 428 return; |
495 | 429 |
496 TRACE_EVENT_INSTANT1("android_webview", | 430 TRACE_EVENT_INSTANT1("android_webview", |
497 "BrowserViewRenderer::SetContinuousInvalidate", | 431 "BrowserViewRenderer::SetContinuousInvalidate", |
498 TRACE_EVENT_SCOPE_THREAD, | 432 TRACE_EVENT_SCOPE_THREAD, |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
809 base::StringAppendF(&str, | 743 base::StringAppendF(&str, |
810 "overscroll_rounding_error_: %s ", | 744 "overscroll_rounding_error_: %s ", |
811 overscroll_rounding_error_.ToString().c_str()); | 745 overscroll_rounding_error_.ToString().c_str()); |
812 base::StringAppendF( | 746 base::StringAppendF( |
813 &str, "on_new_picture_enable: %d ", on_new_picture_enable_); | 747 &str, "on_new_picture_enable: %d ", on_new_picture_enable_); |
814 base::StringAppendF(&str, "clear_view: %d ", clear_view_); | 748 base::StringAppendF(&str, "clear_view: %d ", clear_view_); |
815 return str; | 749 return str; |
816 } | 750 } |
817 | 751 |
818 } // namespace android_webview | 752 } // namespace android_webview |
OLD | NEW |