diff options
author | sunnyps <sunnyps@chromium.org> | 2015-04-02 13:26:13 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-02 20:26:42 +0000 |
commit | eab5ac980c7b7a5781dc18a1217911eb362698f0 (patch) | |
tree | 5a0ad1e2c9b4b64027432ba11b8ca8c70767e9c0 /android_webview | |
parent | b21a63a538aad2c53afd6aaf76a48ab92b15897a (diff) | |
download | chromium_src-eab5ac980c7b7a5781dc18a1217911eb362698f0.zip chromium_src-eab5ac980c7b7a5781dc18a1217911eb362698f0.tar.gz chromium_src-eab5ac980c7b7a5781dc18a1217911eb362698f0.tar.bz2 |
cc: Make scheduling be driven by vsync for android webview.
This CL makes android webview use the similar mechanisms for
scheduling as other platforms instead of using special
polling code in the scheduler.
Design Doc: https://docs.google.com/a/chromium.org/document/d/1w5UiuA2uZcAiU9-1Y23bxXaStUThkAK8wHI4ULqho2Y/edit#
BUG=439275
Committed: https://crrev.com/bf27da634790bb6eecf4b89f278cfd55c5e5d1f3
Cr-Commit-Position: refs/heads/master@{#323361}
Review URL: https://codereview.chromium.org/817603002
Cr-Commit-Position: refs/heads/master@{#323553}
Diffstat (limited to 'android_webview')
5 files changed, 73 insertions, 115 deletions
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc index 6b4ee92..928a62b7 100644 --- a/android_webview/browser/browser_view_renderer.cc +++ b/android_webview/browser/browser_view_renderer.cc @@ -98,8 +98,6 @@ BrowserViewRenderer::BrowserViewRenderer( on_new_picture_enable_(false), clear_view_(false), offscreen_pre_raster_(false), - compositor_needs_continuous_invalidate_(false), - block_invalidates_(false), fallback_tick_pending_(false) { } @@ -198,6 +196,7 @@ bool BrowserViewRenderer::CanOnDraw() { bool BrowserViewRenderer::OnDrawHardware() { TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnDrawHardware"); + shared_renderer_state_.InitializeHardwareDrawIfNeededOnUI(); if (!CanOnDraw()) { @@ -220,6 +219,8 @@ bool BrowserViewRenderer::OnDrawHardware() { } bool BrowserViewRenderer::CompositeHw() { + CancelFallbackTick(); + ReturnResourceFromParent(); compositor_->SetMemoryPolicy(CalculateDesiredMemoryPolicy()); @@ -263,7 +264,6 @@ bool BrowserViewRenderer::CompositeHw() { 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 @@ bool BrowserViewRenderer::CompositeHw() { } void BrowserViewRenderer::UpdateParentDrawConstraints() { - EnsureContinuousInvalidation(true); + PostInvalidateWithFallback(); ParentCompositorDrawConstraints parent_draw_constraints = shared_renderer_state_.GetParentDrawConstraintsOnUI(); client_->ParentDrawConstraintsUpdated(parent_draw_constraints); @@ -342,7 +342,7 @@ void BrowserViewRenderer::ClearView() { clear_view_ = true; // Always invalidate ignoring the compositor to actually clear the webview. - EnsureContinuousInvalidation(true); + PostInvalidateWithFallback(); } void BrowserViewRenderer::SetOffscreenPreRaster(bool enable) { @@ -357,7 +357,7 @@ void BrowserViewRenderer::SetIsPaused(bool paused) { "paused", paused); is_paused_ = paused; - EnsureContinuousInvalidation(false); + UpdateCompositorIsActive(); } void BrowserViewRenderer::SetViewVisibility(bool view_visible) { @@ -376,7 +376,7 @@ void BrowserViewRenderer::SetWindowVisibility(bool window_visible) { "window_visible", window_visible); window_visible_ = window_visible; - EnsureContinuousInvalidation(false); + UpdateCompositorIsActive(); } void BrowserViewRenderer::OnSizeChanged(int width, int height) { @@ -399,6 +399,7 @@ void BrowserViewRenderer::OnAttachedToWindow(int width, int height) { height); attached_to_window_ = true; size_.SetSize(width, height); + UpdateCompositorIsActive(); } void BrowserViewRenderer::OnDetachedFromWindow() { @@ -406,6 +407,7 @@ void BrowserViewRenderer::OnDetachedFromWindow() { shared_renderer_state_.ReleaseHardwareDrawIfNeededOnUI(); attached_to_window_ = false; DCHECK(!hardware_enabled_); + UpdateCompositorIsActive(); } void BrowserViewRenderer::ReleaseHardware() { @@ -437,6 +439,7 @@ void BrowserViewRenderer::DidInitializeCompositor( DCHECK(compositor); DCHECK(!compositor_); compositor_ = compositor; + UpdateCompositorIsActive(); } void BrowserViewRenderer::DidDestroyCompositor( @@ -446,20 +449,6 @@ void BrowserViewRenderer::DidDestroyCompositor( 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) { dip_scale_ = dip_scale; CHECK_GT(dip_scale_, 0.f); @@ -627,13 +616,13 @@ void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll, client_->DidOverscroll(rounded_overscroll_delta); } -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; +void BrowserViewRenderer::PostInvalidate() { + TRACE_EVENT_INSTANT0("android_webview", "BrowserViewRenderer::PostInvalidate", + TRACE_EVENT_SCOPE_THREAD); + PostInvalidateWithFallback(); +} +void BrowserViewRenderer::PostInvalidateWithFallback() { // 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(); @@ -646,63 +635,49 @@ void BrowserViewRenderer::EnsureContinuousInvalidation(bool force_invalidate) { // "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) - return; - block_invalidates_ = compositor_needs_continuous_invalidate_; - if (fallback_tick_pending_) + if (throttle_fallback_tick || fallback_tick_pending_) return; - // Unretained here is safe because the callbacks are cancelled when - // they are destroyed. + DCHECK(post_fallback_tick_.IsCancelled()); + DCHECK(fallback_tick_fired_.IsCancelled()); + 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))); - 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(); - } + ui_task_runner_->PostDelayedTask( + FROM_HERE, fallback_tick_fired_.callback(), + base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds)); } void BrowserViewRenderer::FallbackTickFired() { - TRACE_EVENT1("android_webview", - "BrowserViewRenderer::FallbackTickFired", - "compositor_needs_continuous_invalidate_", - compositor_needs_continuous_invalidate_); - + TRACE_EVENT0("android_webview", "BrowserViewRenderer::FallbackTickFired"); // This should only be called if OnDraw or DrawGL did not come in time, which - // means block_invalidates_ must still be true. - DCHECK(block_invalidates_); + // means fallback_tick_pending_ must still be true. + DCHECK(fallback_tick_pending_); + fallback_tick_fired_.Cancel(); fallback_tick_pending_ = false; - if (compositor_needs_continuous_invalidate_ && compositor_) { + if (compositor_) { if (hardware_enabled_) { CompositeHw(); } else { ForceFakeCompositeSW(); } - } else { - // Pretend we just composited to unblock further invalidates. - DidComposite(); } } @@ -717,18 +692,15 @@ void BrowserViewRenderer::ForceFakeCompositeSW() { bool BrowserViewRenderer::CompositeSW(SkCanvas* canvas) { DCHECK(compositor_); + CancelFallbackTick(); ReturnResourceFromParent(); - bool result = compositor_->DemandDrawSw(canvas); - DidComposite(); - return result; + return compositor_->DemandDrawSw(canvas); } -void BrowserViewRenderer::DidComposite() { - block_invalidates_ = false; - post_fallback_tick_.Cancel(); - fallback_tick_fired_.Cancel(); - fallback_tick_pending_ = false; - EnsureContinuousInvalidation(false); +void BrowserViewRenderer::UpdateCompositorIsActive() { + if (compositor_) + compositor_->SetIsActive(!is_paused_ && + (!attached_to_window_ || window_visible_)); } std::string BrowserViewRenderer::ToString() const { @@ -738,10 +710,8 @@ std::string BrowserViewRenderer::ToString() const { 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, - "compositor_needs_continuous_invalidate: %d ", - compositor_needs_continuous_invalidate_); - base::StringAppendF(&str, "block_invalidates: %d ", block_invalidates_); + base::StringAppendF(&str, "fallback_tick_pending: %d ", + fallback_tick_pending_); base::StringAppendF(&str, "view size: %s ", size_.ToString().c_str()); base::StringAppendF(&str, "attached_to_window: %d ", attached_to_window_); base::StringAppendF(&str, diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h index 843529b..308abd4 100644 --- a/android_webview/browser/browser_view_renderer.h +++ b/android_webview/browser/browser_view_renderer.h @@ -96,7 +96,7 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { content::SynchronousCompositor* compositor) override; void DidDestroyCompositor( content::SynchronousCompositor* compositor) override; - void SetContinuousInvalidate(bool invalidate) override; + void PostInvalidate() override; void DidUpdateContent() override; gfx::Vector2dF GetTotalRootLayerScrollOffset() override; void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset_dip, @@ -116,12 +116,13 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { private: void SetTotalRootLayerScrollOffset(gfx::Vector2dF new_value_dip); bool CanOnDraw(); - // Checks the continuous invalidate and block invalidate state, and schedule - // invalidates appropriately. If |force_invalidate| is true, then send a view - // invalidate regardless of compositor expectation. - void EnsureContinuousInvalidation(bool force_invalidate); + // Posts an invalidate with fallback tick. All invalidates posted while an + // invalidate is pending will be posted as a single invalidate after the + // pending invalidate is done. + void PostInvalidateWithFallback(); + void CancelFallbackTick(); + void UpdateCompositorIsActive(); bool CompositeSW(SkCanvas* canvas); - void DidComposite(); scoped_refptr<base::trace_event::ConvertableToTraceFormat> RootLayerStateAsValue(const gfx::Vector2dF& total_scroll_offset_dip, const gfx::SizeF& scrollable_size_dip); @@ -145,6 +146,7 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { gfx::Vector2d max_scroll_offset() const; size_t CalculateDesiredMemoryPolicy(); + // For debug tracing or logging. Return the string representation of this // view renderer's state. std::string ToString() const; @@ -170,14 +172,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { gfx::Vector2d last_on_draw_scroll_offset_; gfx::Rect last_on_draw_global_visible_rect_; - // When true, we should continuously invalidate and keep drawing, for example - // to drive animation. This value is set by the compositor and should always - // reflect the expectation of the compositor and not be reused for other - // states. - bool compositor_needs_continuous_invalidate_; - - // Used to block additional invalidates while one is already pending. - bool block_invalidates_; base::CancelableClosure post_fallback_tick_; base::CancelableClosure fallback_tick_fired_; diff --git a/android_webview/browser/browser_view_renderer_client.h b/android_webview/browser/browser_view_renderer_client.h index 4c2f36f..c4bf8f2 100644 --- a/android_webview/browser/browser_view_renderer_client.h +++ b/android_webview/browser/browser_view_renderer_client.h @@ -26,6 +26,8 @@ class BrowserViewRendererClient { virtual void OnNewPicture() = 0; // Called to trigger view invalidations. + // This calls postInvalidateOnAnimation if outside of a vsync, otherwise it + // calls invalidate. virtual void PostInvalidate() = 0; // Call postInvalidateOnAnimation for invalidations. This is only used to diff --git a/android_webview/browser/browser_view_renderer_unittest.cc b/android_webview/browser/browser_view_renderer_unittest.cc index e4c6eac..634e1f3 100644 --- a/android_webview/browser/browser_view_renderer_unittest.cc +++ b/android_webview/browser/browser_view_renderer_unittest.cc @@ -9,13 +9,7 @@ namespace android_webview { class SmokeTest : public RenderingTest { - void StartTest() override { - browser_view_renderer_->SetContinuousInvalidate(true); - } - - void WillOnDraw() override { - browser_view_renderer_->SetContinuousInvalidate(false); - } + void StartTest() override { browser_view_renderer_->PostInvalidate(); } void DidDrawOnRT(SharedRendererState* functor) override { EndTest(); @@ -26,25 +20,20 @@ RENDERING_TEST_F(SmokeTest); class ClearViewTest : public RenderingTest { public: - ClearViewTest() : on_draw_count_(0u) {} + ClearViewTest() : on_draw_count_(0) {} void StartTest() override { - browser_view_renderer_->SetContinuousInvalidate(true); + browser_view_renderer_->PostInvalidate(); browser_view_renderer_->ClearView(); } - void WillOnDraw() override { - on_draw_count_++; - if (on_draw_count_ == 2u) { - browser_view_renderer_->SetContinuousInvalidate(false); - } - } - void DidOnDraw(bool success) override { - if (on_draw_count_ == 1u) { + on_draw_count_++; + if (on_draw_count_ == 1) { // First OnDraw should be skipped due to ClearView. EXPECT_FALSE(success); browser_view_renderer_->DidUpdateContent(); // Unset ClearView. + browser_view_renderer_->PostInvalidate(); } else { // Following OnDraws should succeed. EXPECT_TRUE(success); @@ -55,25 +44,23 @@ class ClearViewTest : public RenderingTest { EndTest(); } private: - size_t on_draw_count_; + int on_draw_count_; }; RENDERING_TEST_F(ClearViewTest); class TestAnimateInAndOutOfScreen : public RenderingTest { public: - TestAnimateInAndOutOfScreen() - : on_draw_count_(0u), draw_gl_count_on_rt_(0u) {} + TestAnimateInAndOutOfScreen() : on_draw_count_(0), draw_gl_count_on_rt_(0) {} void StartTest() override { new_constraints_ = ParentCompositorDrawConstraints( false, gfx::Transform(), gfx::Rect(window_->surface_size())); new_constraints_.transform.Scale(2.0, 2.0); - browser_view_renderer_->SetContinuousInvalidate(true); + browser_view_renderer_->PostInvalidate(); } void WillOnDraw() override { - browser_view_renderer_->SetContinuousInvalidate(false); // Step 0: A single onDraw on screen. The parent draw constraints // of the BVR will updated to be the initial constraints. // Step 1: A single onDrraw off screen. The parent draw constraints of the @@ -81,7 +68,7 @@ class TestAnimateInAndOutOfScreen : public RenderingTest { // Step 2: This onDraw is to introduce the DrawGL that animates the // webview onto the screen on render thread. End the test when the parent // draw constraints of BVR is updated to initial constraints. - if (on_draw_count_ == 1u || on_draw_count_ == 2u) + if (on_draw_count_ == 1 || on_draw_count_ == 2) browser_view_renderer_->PrepareToDraw(gfx::Vector2d(), gfx::Rect()); } @@ -92,7 +79,7 @@ class TestAnimateInAndOutOfScreen : public RenderingTest { bool WillDrawOnRT(SharedRendererState* functor, AwDrawGLInfo* draw_info) override { - if (draw_gl_count_on_rt_ == 1u) { + if (draw_gl_count_on_rt_ == 1) { draw_gl_count_on_rt_++; ui_proxy_->PostTask(FROM_HERE, base::Bind(&RenderingTest::PostInvalidate, base::Unretained(this))); @@ -104,7 +91,7 @@ class TestAnimateInAndOutOfScreen : public RenderingTest { draw_info->is_layer = false; gfx::Transform transform; - if (draw_gl_count_on_rt_ == 0u) + if (draw_gl_count_on_rt_ == 0) transform = new_constraints_.transform; transform.matrix().asColMajorf(draw_info->transform); @@ -145,8 +132,8 @@ class TestAnimateInAndOutOfScreen : public RenderingTest { } private: - size_t on_draw_count_; - size_t draw_gl_count_on_rt_; + int on_draw_count_; + int draw_gl_count_on_rt_; ParentCompositorDrawConstraints initial_constraints_; ParentCompositorDrawConstraints new_constraints_; }; diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java index 9d3ae1a..a064d96 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/VisualStateTest.java @@ -22,6 +22,7 @@ import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.GraphicsTestUtils; import org.chromium.android_webview.test.util.JavascriptEventObserver; import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.content.browser.ContentViewCore; @@ -404,8 +405,12 @@ public class VisualStateTest extends AwTestBase { assertTrue(testFinishedSignal.await(AwTestBase.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); } + /* @Feature({"AndroidWebView"}) @SmallTest + http://crbug.com/472922 + */ + @DisabledTest public void testVisualStateCallbackFromJavaDuringFullscreenTransitions() throws Throwable { // This test checks that VisualStateCallbacks are delivered correctly during // fullscreen transitions. It loads a page, clicks a button to enter fullscreen, |