| 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 |