From 6b968c06b3641d5cb45917039de447f8337edd4c Mon Sep 17 00:00:00 2001 From: vmpstr Date: Mon, 29 Sep 2014 16:34:49 -0700 Subject: [PATCH] cc: Activate when going invisible. This patch ensures that we always activate when we become invisible. The reason being is that when we come back to being visible again, we don't need to rasterize both active and pending trees. We can just rasterize what used to be the pending tree. Since we set RequiresHighResToDraw on becoming visible, this also ensures that we don't checkerboard on becoming visible. BUG=410000, 417598 R=danakj, enne, brianderson Review URL: https://codereview.chromium.org/605823002 Cr-Commit-Position: refs/heads/master@{#297303} --- cc/scheduler/scheduler_state_machine.cc | 19 +++++---- cc/scheduler/scheduler_unittest.cc | 34 +++++++++++++++ cc/trees/layer_tree_host_unittest.cc | 55 +++++++------------------ 3 files changed, 60 insertions(+), 48 deletions(-) diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index d33922cf42941..a6904ae2c6781 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc @@ -280,23 +280,28 @@ bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { return true; // Additional states where we should abort draws. - // Note: We don't force activation in these cases because doing so would - // result in checkerboarding on resize, becoming visible, etc. if (!can_draw_) return true; - if (!visible_) - return true; return false; } bool SchedulerStateMachine::PendingActivationsShouldBeForced() const { - // These are all the cases where, if we do not force activations to make - // forward progress, we might deadlock with the main thread. - // There is no output surface to trigger our activations. + // If we do not force activations to make forward progress, we might deadlock + // with the main thread. if (output_surface_state_ == OUTPUT_SURFACE_LOST) return true; + // If we're not visible, we should force activation. + // Since we set RequiresHighResToDraw when becoming visible, we ensure that we + // don't checkerboard until all visible resources are done. Furthermore, if we + // do keep the pending tree around, when becoming visible we might activate + // prematurely causing RequiresHighResToDraw flag to be reset. In all cases, + // we can simply activate on becoming invisible since we don't need to draw + // the active tree when we're in this state. + if (!visible_) + return true; + return false; } diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 256acd5bd8f6a..0a08c5b7c038e 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc @@ -1909,5 +1909,39 @@ TEST(SchedulerTest, EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive()); } +TEST(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) { + FakeSchedulerClient client; + SchedulerSettings scheduler_settings; + scheduler_settings.impl_side_painting = true; + TestScheduler* scheduler = client.CreateScheduler(scheduler_settings); + scheduler->SetCanStart(); + scheduler->SetVisible(true); + scheduler->SetCanDraw(true); + + EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); + InitializeOutputSurfaceAndFirstCommit(scheduler, &client); + + // SetNeedsCommit should begin the frame. + client.Reset(); + scheduler->SetNeedsCommit(); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client); + + client.Reset(); + client.AdvanceFrame(); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); + + client.Reset(); + scheduler->NotifyBeginMainFrameStarted(); + scheduler->NotifyReadyToCommit(); + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); + + client.Reset(); + scheduler->SetVisible(false); + // Sync tree should be forced to activate. + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client); +} + } // namespace } // namespace cc diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 22bb9fdb5d45f..6db13267551de 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -5022,37 +5022,22 @@ class LayerTreeHostTestContinuousPainting : public LayerTreeHostTest { MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousPainting); -class LayerTreeHostTestInvisibleDoesntActivate : public LayerTreeHostTest { +class LayerTreeHostTestActivateOnInvisible : public LayerTreeHostTest { public: - LayerTreeHostTestInvisibleDoesntActivate() : activation_count_(0) {} + LayerTreeHostTestActivateOnInvisible() + : activation_count_(0), visible_(true) {} virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE { settings->impl_side_painting = true; } - virtual void SetupTree() OVERRIDE { - scoped_refptr root_layer = Layer::Create(); - root_layer->SetBounds(gfx::Size(1000, 1000)); - - // Set up a non-solid layer with a bunch of tiles. - client_.set_fill_with_nonsolid_color(true); - picture_layer_ = FakePictureLayer::Create(&client_); - picture_layer_->SetBounds(gfx::Size(1000, 1000)); - picture_layer_->SetIsDrawable(true); - picture_layer_->SetNeedsDisplayRect(gfx::Rect(1000, 1000)); - root_layer->AddChild(picture_layer_.get()); - - layer_tree_host()->SetRootLayer(root_layer); - LayerTreeHostTest::SetupTree(); - } - virtual void BeginTest() OVERRIDE { // Kick off the test with a commit. PostSetNeedsCommitToMainThread(); } virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { - // Make sure we don't activate before going invisible. + // Make sure we don't activate using the notify signal from tile manager. host_impl->BlockNotifyReadyToActivateForTesting(true); } @@ -5060,49 +5045,37 @@ class LayerTreeHostTestInvisibleDoesntActivate : public LayerTreeHostTest { virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl, bool visible) OVERRIDE { + visible_ = visible; + // Once invisible, we can go visible again. if (!visible) { - // Allow activation from now on. - host_impl->BlockNotifyReadyToActivateForTesting(false); PostSetVisibleToMainThread(true); + } else { + EXPECT_TRUE(host_impl->active_tree()->RequiresHighResToDraw()); + EndTest(); } } virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { ++activation_count_; - std::vector tiles = host_impl->tile_manager()->AllTilesForTesting(); - EXPECT_GT(tiles.size(), 0u); - // When activating, ensure that all tiles are ready to draw with a mode - // other than rasterize on demand. - int resource_tiles_count = 0; - for (std::vector::iterator it = tiles.begin(); it != tiles.end(); - ++it) { - Tile* tile = *it; - const ManagedTileState::DrawInfo& draw_info = tile->draw_info(); - EXPECT_TRUE(draw_info.IsReadyToDraw()); - EXPECT_NE(ManagedTileState::DrawInfo::PICTURE_PILE_MODE, - draw_info.mode()); - resource_tiles_count += - draw_info.mode() == ManagedTileState::DrawInfo::RESOURCE_MODE; - } - EXPECT_GT(resource_tiles_count, 0); - - EndTest(); + EXPECT_FALSE(visible_); } virtual void AfterTest() OVERRIDE { - // Double check that we activated once. + // Ensure we activated even though the signal was blocked. EXPECT_EQ(1, activation_count_); + EXPECT_TRUE(visible_); } private: int activation_count_; + bool visible_; FakeContentLayerClient client_; scoped_refptr picture_layer_; }; // TODO(vmpstr): Enable with single thread impl-side painting. -MULTI_THREAD_TEST_F(LayerTreeHostTestInvisibleDoesntActivate); +MULTI_THREAD_TEST_F(LayerTreeHostTestActivateOnInvisible); } // namespace cc