Index: android_webview/browser/browser_view_renderer.cc |
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc |
index 928a62b70e1dff1ec7db9ce44585c7422f879420..6b4ee929ec07988429f16de61e0a5c6adfcb112d 100644 |
--- a/android_webview/browser/browser_view_renderer.cc |
+++ b/android_webview/browser/browser_view_renderer.cc |
@@ -98,6 +98,8 @@ |
on_new_picture_enable_(false), |
clear_view_(false), |
offscreen_pre_raster_(false), |
+ compositor_needs_continuous_invalidate_(false), |
+ block_invalidates_(false), |
fallback_tick_pending_(false) { |
} |
@@ -196,7 +198,6 @@ |
bool BrowserViewRenderer::OnDrawHardware() { |
TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware"); |
- |
shared_renderer_state_.InitializeHardwareDrawIfNeededOnUI(); |
if (!CanOnDraw()) { |
@@ -219,8 +220,6 @@ |
} |
bool BrowserViewRenderer::CompositeHw() { |
- CancelFallbackTick(); |
- |
ReturnResourceFromParent(); |
compositor_->SetMemoryPolicy(CalculateDesiredMemoryPolicy()); |
@@ -264,6 +263,7 @@ |
transform_for_tile_priority, offscreen_pre_raster_, |
parent_draw_constraints.is_layer)); |
+ DidComposite(); |
// Uncommitted frame can happen with consecutive fallback ticks. |
ReturnUnusedResource(shared_renderer_state_.PassUncommittedFrameOnUI()); |
shared_renderer_state_.SetCompositorFrameOnUI(child_frame.Pass()); |
@@ -271,7 +271,7 @@ |
} |
void BrowserViewRenderer::UpdateParentDrawConstraints() { |
- PostInvalidateWithFallback(); |
+ EnsureContinuousInvalidation(true); |
ParentCompositorDrawConstraints parent_draw_constraints = |
shared_renderer_state_.GetParentDrawConstraintsOnUI(); |
client_->ParentDrawConstraintsUpdated(parent_draw_constraints); |
@@ -342,7 +342,7 @@ |
clear_view_ = true; |
// Always invalidate ignoring the compositor to actually clear the webview. |
- PostInvalidateWithFallback(); |
+ EnsureContinuousInvalidation(true); |
} |
void BrowserViewRenderer::SetOffscreenPreRaster(bool enable) { |
@@ -357,7 +357,7 @@ |
"paused", |
paused); |
is_paused_ = paused; |
- UpdateCompositorIsActive(); |
+ EnsureContinuousInvalidation(false); |
} |
void BrowserViewRenderer::SetViewVisibility(bool view_visible) { |
@@ -376,7 +376,7 @@ |
"window_visible", |
window_visible); |
window_visible_ = window_visible; |
- UpdateCompositorIsActive(); |
+ EnsureContinuousInvalidation(false); |
} |
void BrowserViewRenderer::OnSizeChanged(int width, int height) { |
@@ -399,7 +399,6 @@ |
height); |
attached_to_window_ = true; |
size_.SetSize(width, height); |
- UpdateCompositorIsActive(); |
} |
void BrowserViewRenderer::OnDetachedFromWindow() { |
@@ -407,7 +406,6 @@ |
shared_renderer_state_.ReleaseHardwareDrawIfNeededOnUI(); |
attached_to_window_ = false; |
DCHECK(!hardware_enabled_); |
- UpdateCompositorIsActive(); |
} |
void BrowserViewRenderer::ReleaseHardware() { |
@@ -439,7 +437,6 @@ |
DCHECK(compositor); |
DCHECK(!compositor_); |
compositor_ = compositor; |
- UpdateCompositorIsActive(); |
} |
void BrowserViewRenderer::DidDestroyCompositor( |
@@ -447,6 +444,20 @@ |
TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor"); |
DCHECK(compositor_); |
compositor_ = NULL; |
+} |
+ |
+void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) { |
+ if (compositor_needs_continuous_invalidate_ == invalidate) |
+ return; |
+ |
+ TRACE_EVENT_INSTANT1("android_webview", |
+ "BrowserViewRenderer::SetContinuousInvalidate", |
+ TRACE_EVENT_SCOPE_THREAD, |
+ "invalidate", |
+ invalidate); |
+ compositor_needs_continuous_invalidate_ = invalidate; |
+ |
+ EnsureContinuousInvalidation(false); |
} |
void BrowserViewRenderer::SetDipScale(float dip_scale) { |
@@ -616,13 +627,13 @@ |
client_->DidOverscroll(rounded_overscroll_delta); |
} |
-void BrowserViewRenderer::PostInvalidate() { |
- TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate", |
- TRACE_EVENT_SCOPE_THREAD); |
- PostInvalidateWithFallback(); |
-} |
- |
-void BrowserViewRenderer::PostInvalidateWithFallback() { |
+void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) { |
+ // This method should be called again when any of these conditions change. |
+ bool need_invalidate = |
+ compositor_needs_continuous_invalidate_ || force_invalidate; |
+ if (!need_invalidate || block_invalidates_) |
+ return; |
+ |
// Always call view invalidate. We rely the Android framework to ignore the |
// invalidate when it's not needed such as when view is not visible. |
client_->PostInvalidate(); |
@@ -635,49 +646,63 @@ |
// "on-screen" but that updates are not needed when in the background. |
bool throttle_fallback_tick = |
(is_paused_ && !clear_view_) || (attached_to_window_ && !window_visible_); |
- |
- if (throttle_fallback_tick || fallback_tick_pending_) |
- return; |
- |
- DCHECK(post_fallback_tick_.IsCancelled()); |
- DCHECK(fallback_tick_fired_.IsCancelled()); |
- |
+ if (throttle_fallback_tick) |
+ return; |
+ |
+ block_invalidates_ = compositor_needs_continuous_invalidate_; |
+ if (fallback_tick_pending_) |
+ return; |
+ |
+ // Unretained here is safe because the callbacks are cancelled when |
+ // they are destroyed. |
post_fallback_tick_.Reset(base::Bind(&BrowserViewRenderer::PostFallbackTick, |
base::Unretained(this))); |
- ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback()); |
- fallback_tick_pending_ = true; |
-} |
- |
-void BrowserViewRenderer::CancelFallbackTick() { |
- post_fallback_tick_.Cancel(); |
fallback_tick_fired_.Cancel(); |
fallback_tick_pending_ = false; |
+ |
+ // No need to reschedule fallback tick if compositor does not need to be |
+ // ticked. This can happen if this is reached because force_invalidate is |
+ // true. |
+ if (compositor_needs_continuous_invalidate_) { |
+ fallback_tick_pending_ = true; |
+ ui_task_runner_->PostTask(FROM_HERE, post_fallback_tick_.callback()); |
+ } |
} |
void BrowserViewRenderer::PostFallbackTick() { |
DCHECK(fallback_tick_fired_.IsCancelled()); |
- TRACE_EVENT0("android_webview", "BrowserViewRenderer::PostFallbackTick"); |
- post_fallback_tick_.Cancel(); |
fallback_tick_fired_.Reset(base::Bind(&BrowserViewRenderer::FallbackTickFired, |
base::Unretained(this))); |
- ui_task_runner_->PostDelayedTask( |
- FROM_HERE, fallback_tick_fired_.callback(), |
- base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds)); |
+ if (compositor_needs_continuous_invalidate_) { |
+ ui_task_runner_->PostDelayedTask( |
+ FROM_HERE, |
+ fallback_tick_fired_.callback(), |
+ base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds)); |
+ } else { |
+ // Pretend we just composited to unblock further invalidates. |
+ DidComposite(); |
+ } |
} |
void BrowserViewRenderer::FallbackTickFired() { |
- TRACE_EVENT0("android_webview", "BrowserViewRenderer::FallbackTickFired"); |
+ TRACE_EVENT1("android_webview", |
+ "BrowserViewRenderer::FallbackTickFired", |
+ "compositor_needs_continuous_invalidate_", |
+ compositor_needs_continuous_invalidate_); |
+ |
// This should only be called if OnDraw or DrawGL did not come in time, which |
- // means fallback_tick_pending_ must still be true. |
- DCHECK(fallback_tick_pending_); |
- fallback_tick_fired_.Cancel(); |
+ // means block_invalidates_ must still be true. |
+ DCHECK(block_invalidates_); |
fallback_tick_pending_ = false; |
- if (compositor_) { |
+ if (compositor_needs_continuous_invalidate_ && compositor_) { |
if (hardware_enabled_) { |
CompositeHw(); |
} else { |
ForceFakeCompositeSW(); |
} |
+ } else { |
+ // Pretend we just composited to unblock further invalidates. |
+ DidComposite(); |
} |
} |
@@ -692,15 +717,18 @@ |
bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) { |
DCHECK(compositor_); |
- CancelFallbackTick(); |
ReturnResourceFromParent(); |
- return compositor_->DemandDrawSw(canvas); |
-} |
- |
-void BrowserViewRenderer::UpdateCompositorIsActive() { |
- if (compositor_) |
- compositor_->SetIsActive(!is_paused_ && |
- (!attached_to_window_ || window_visible_)); |
+ bool result = compositor_->DemandDrawSw(canvas); |
+ DidComposite(); |
+ return result; |
+} |
+ |
+void BrowserViewRenderer::DidComposite() { |
+ block_invalidates_ = false; |
+ post_fallback_tick_.Cancel(); |
+ fallback_tick_fired_.Cancel(); |
+ fallback_tick_pending_ = false; |
+ EnsureContinuousInvalidation(false); |
} |
std::string BrowserViewRenderer::ToString() const { |
@@ -710,8 +738,10 @@ |
base::StringAppendF(&str, "window_visible: %d ", window_visible_); |
base::StringAppendF(&str, "dip_scale: %f ", dip_scale_); |
base::StringAppendF(&str, "page_scale_factor: %f ", page_scale_factor_); |
- base::StringAppendF(&str, "fallback_tick_pending: %d ", |
- fallback_tick_pending_); |
+ base::StringAppendF(&str, |
+ "compositor_needs_continuous_invalidate: %d ", |
+ compositor_needs_continuous_invalidate_); |
+ base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_); |
base::StringAppendF(&str, "view size: %s ", size_.ToString().c_str()); |
base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); |
base::StringAppendF(&str, |