diff options
author | simonhong <simonhong@chromium.org> | 2015-01-29 15:02:39 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-29 23:04:51 +0000 |
commit | 1625b74468e4dd55f54ba209f8e91d05493875b9 (patch) | |
tree | 9dc54343e4893d16029a4387d935ba95940be7c0 /cc | |
parent | 48515fb7d095fd26c175999e2760ec4aa3db0e42 (diff) | |
download | chromium_src-1625b74468e4dd55f54ba209f8e91d05493875b9.zip chromium_src-1625b74468e4dd55f54ba209f8e91d05493875b9.tar.gz chromium_src-1625b74468e4dd55f54ba209f8e91d05493875b9.tar.bz2 |
cc: Control defer_commits logic by Scheduler
So far, EarlyOut_DeferCommits is controlled by Proxy.
Because Scheduler doesn't know about this deferring, it triggers next
BeginMainFrame when main thread want to defer a commit.
This CL moves the EarlyOut_DeferCommits logic from Proxy to
Scheduler so Scheduler can stop next BeginMainFrame until defer commit is off.
R=brianderson@chromium.org, danakj@chromium.org, skyostil@chromium.org
BUG=382572
TEST=cc_unittests
Review URL: https://codereview.chromium.org/337693005
Cr-Commit-Position: refs/heads/master@{#313816}
Diffstat (limited to 'cc')
-rw-r--r-- | cc/scheduler/commit_earlyout_reason.h | 3 | ||||
-rw-r--r-- | cc/scheduler/scheduler.cc | 8 | ||||
-rw-r--r-- | cc/scheduler/scheduler.h | 2 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine.cc | 13 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine.h | 3 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine_unittest.cc | 23 | ||||
-rw-r--r-- | cc/scheduler/scheduler_unittest.cc | 70 | ||||
-rw-r--r-- | cc/test/layer_tree_test.cc | 105 | ||||
-rw-r--r-- | cc/test/layer_tree_test.h | 4 | ||||
-rw-r--r-- | cc/trees/layer_tree_host.cc | 2 | ||||
-rw-r--r-- | cc/trees/layer_tree_host.h | 3 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest.cc | 92 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_context.cc | 18 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.cc | 13 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.h | 4 | ||||
-rw-r--r-- | cc/trees/thread_proxy.cc | 27 | ||||
-rw-r--r-- | cc/trees/thread_proxy.h | 2 |
17 files changed, 300 insertions, 92 deletions
diff --git a/cc/scheduler/commit_earlyout_reason.h b/cc/scheduler/commit_earlyout_reason.h index b45e96f..14aaeb3 100644 --- a/cc/scheduler/commit_earlyout_reason.h +++ b/cc/scheduler/commit_earlyout_reason.h @@ -12,6 +12,7 @@ namespace cc { enum class CommitEarlyOutReason { ABORTED_OUTPUT_SURFACE_LOST, ABORTED_NOT_VISIBLE, + ABORTED_DEFERRED_COMMIT, FINISHED_NO_UPDATES, }; @@ -21,6 +22,8 @@ inline const char* CommitEarlyOutReasonToString(CommitEarlyOutReason reason) { return "CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST"; case CommitEarlyOutReason::ABORTED_NOT_VISIBLE: return "CommitEarlyOutReason::ABORTED_NOT_VISIBLE"; + case CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT: + return "CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT"; case CommitEarlyOutReason::FINISHED_NO_UPDATES: return "CommitEarlyOutReason::FINISHED_NO_UPDATES"; } diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index b92b8a5..43812e8 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc @@ -671,6 +671,14 @@ void Scheduler::DrawAndSwapIfPossible() { state_machine_.DidDrawIfPossibleCompleted(result); } +void Scheduler::SetDeferCommits(bool defer_commits) { + TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", + "defer_commits", + defer_commits); + state_machine_.SetDeferCommits(defer_commits); + ProcessScheduledActions(); +} + void Scheduler::ProcessScheduledActions() { // We do not allow ProcessScheduledActions to be recursive. // The top-level call will iteratively execute the next action for us anyway. diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index faf4399..e06a133 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h @@ -162,6 +162,8 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn, base::TimeTicks LastBeginImplFrameTime(); + void SetDeferCommits(bool defer_commits); + scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const; void AsValueInto(base::debug::TracedValue* value) const override; diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index 71813ba..7bce7ee 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc @@ -48,7 +48,8 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) skip_begin_main_frame_to_reduce_latency_(false), continuous_painting_(false), impl_latency_takes_priority_on_battery_(false), - children_need_begin_frames_(false) { + children_need_begin_frames_(false), + defer_commits_(false) { } const char* SchedulerStateMachine::OutputSurfaceStateToString( @@ -238,6 +239,7 @@ void SchedulerStateMachine::AsValueInto(base::debug::TracedValue* state, state->SetBoolean("impl_latency_takes_priority_on_battery", impl_latency_takes_priority_on_battery_); state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); + state->SetBoolean("defer_commits", defer_commits_); state->EndDictionary(); } @@ -414,6 +416,10 @@ bool SchedulerStateMachine::CouldSendBeginMainFrame() const { if (!visible_) return false; + // Do not make a new commits when it is deferred. + if (defer_commits_) + return false; + return true; } @@ -769,6 +775,10 @@ void SchedulerStateMachine::SetChildrenNeedBeginFrames( children_need_begin_frames_ = children_need_begin_frames; } +void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { + defer_commits_ = defer_commits; +} + // These are the cases where we definitely (or almost definitely) have a // new frame to animate and/or draw and can draw. bool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const { @@ -1052,6 +1062,7 @@ void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) { switch (reason) { case CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST: case CommitEarlyOutReason::ABORTED_NOT_VISIBLE: + case CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT: commit_state_ = COMMIT_STATE_IDLE; SetNeedsCommit(); return; diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h index 9dc7817..aa153c6 100644 --- a/cc/scheduler/scheduler_state_machine.h +++ b/cc/scheduler/scheduler_state_machine.h @@ -259,6 +259,8 @@ class CC_EXPORT SchedulerStateMachine { impl_latency_takes_priority_on_battery; } + void SetDeferCommits(bool defer_commits); + // TODO(zmo): This is temporary for debugging crbug.com/393331. // We should remove it afterwards. std::string GetStatesForDebugging() const; @@ -341,6 +343,7 @@ class CC_EXPORT SchedulerStateMachine { bool continuous_painting_; bool impl_latency_takes_priority_on_battery_; bool children_need_begin_frames_; + bool defer_commits_; private: DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine); diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index 9d151d5..ca0e441 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc @@ -1813,5 +1813,28 @@ TEST(SchedulerStateMachineTest, TestForwardBeginFramesToChildren) { EXPECT_TRUE(state.BeginFrameNeeded()); } +TEST(SchedulerStateMachineTest, TestDeferCommit) { + SchedulerSettings settings; + StateMachine state(settings); + SET_UP_STATE(state) + + state.SetDeferCommits(true); + + state.SetNeedsCommit(); + EXPECT_TRUE(state.BeginFrameNeeded()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + + state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + + state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + + state.SetDeferCommits(false); + state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); +} + } // namespace } // namespace cc diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 5d58d2a..e4ce6b3 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc @@ -520,6 +520,76 @@ TEST_F(SchedulerTest, RequestCommit) { client_->Reset(); } +TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + scheduler_->SetCanStart(); + scheduler_->SetVisible(true); + scheduler_->SetCanDraw(true); + + scheduler_->SetDeferCommits(true); + + scheduler_->SetNeedsCommit(); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + + client_->Reset(); + AdvanceFrame(); + // BeginMainFrame is not sent during the defer commit is on. + EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); + + client_->Reset(); + task_runner().RunPendingTasks(); // Run posted deadline. + // There is no posted deadline. + EXPECT_NO_ACTION(client_); + EXPECT_TRUE(client_->needs_begin_frames()); + + client_->Reset(); + scheduler_->SetDeferCommits(false); + EXPECT_NO_ACTION(client_); + + // Start new BeginMainFrame after defer commit is off. + client_->Reset(); + AdvanceFrame(); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); + EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); +} + +TEST_F(SchedulerTest, DeferCommitWithRedraw) { + scheduler_settings_.use_external_begin_frame_source = true; + SetUpScheduler(true); + + scheduler_->SetCanStart(); + scheduler_->SetVisible(true); + scheduler_->SetCanDraw(true); + + scheduler_->SetDeferCommits(true); + + scheduler_->SetNeedsCommit(); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + + client_->Reset(); + scheduler_->SetNeedsRedraw(); + EXPECT_NO_ACTION(client_); + + client_->Reset(); + AdvanceFrame(); + // BeginMainFrame is not sent during the defer commit is on. + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2); + + client_->Reset(); + task_runner().RunPendingTasks(); // Run posted deadline. + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->needs_begin_frames()); + + client_->Reset(); + AdvanceFrame(); + EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); +} + TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index a40a8c7..d02b510 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc @@ -79,13 +79,14 @@ class ThreadProxyForTest : public ThreadProxy { ~ThreadProxyForTest() override {} - void test() { - test_hooks_->Layout(); - } - private: TestHooks* test_hooks_; + void WillBeginImplFrame(const BeginFrameArgs& args) override { + ThreadProxy::WillBeginImplFrame(args); + test_hooks_->WillBeginImplFrame(args); + } + void ScheduledActionSendBeginMainFrame() override { test_hooks_->ScheduledActionWillSendBeginMainFrame(); ThreadProxy::ScheduledActionSendBeginMainFrame(); @@ -130,6 +131,74 @@ class ThreadProxyForTest : public ThreadProxy { test_hooks_(test_hooks) {} }; +// Adapts ThreadProxy for test. Injects test hooks for testing. +class SingleThreadProxyForTest : public SingleThreadProxy { + public: + static scoped_ptr<Proxy> Create( + TestHooks* test_hooks, + LayerTreeHost* host, + LayerTreeHostSingleThreadClient* client, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) { + return make_scoped_ptr(new SingleThreadProxyForTest( + test_hooks, host, client, main_task_runner, + external_begin_frame_source.Pass())); + } + + ~SingleThreadProxyForTest() override {} + + private: + TestHooks* test_hooks_; + + void WillBeginImplFrame(const BeginFrameArgs& args) override { + SingleThreadProxy::WillBeginImplFrame(args); + test_hooks_->WillBeginImplFrame(args); + } + + void ScheduledActionSendBeginMainFrame() override { + test_hooks_->ScheduledActionWillSendBeginMainFrame(); + SingleThreadProxy::ScheduledActionSendBeginMainFrame(); + test_hooks_->ScheduledActionSendBeginMainFrame(); + } + + DrawResult ScheduledActionDrawAndSwapIfPossible() override { + DrawResult result = + SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible(); + test_hooks_->ScheduledActionDrawAndSwapIfPossible(); + return result; + } + + void ScheduledActionAnimate() override { + SingleThreadProxy::ScheduledActionAnimate(); + test_hooks_->ScheduledActionAnimate(); + } + + void ScheduledActionCommit() override { + SingleThreadProxy::ScheduledActionCommit(); + test_hooks_->ScheduledActionCommit(); + } + + void ScheduledActionBeginOutputSurfaceCreation() override { + SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation(); + test_hooks_->ScheduledActionBeginOutputSurfaceCreation(); + } + + void ScheduledActionPrepareTiles() override { + SingleThreadProxy::ScheduledActionPrepareTiles(); + test_hooks_->ScheduledActionPrepareTiles(); + } + + SingleThreadProxyForTest( + TestHooks* test_hooks, + LayerTreeHost* host, + LayerTreeHostSingleThreadClient* client, + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_ptr<BeginFrameSource> external_begin_frame_source) + : SingleThreadProxy(host, client, main_task_runner, + external_begin_frame_source.Pass()), + test_hooks_(test_hooks) {} +}; + // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks. class LayerTreeHostImplForTesting : public LayerTreeHostImpl { public: @@ -402,11 +471,13 @@ class LayerTreeHostForTesting : public LayerTreeHost { impl_task_runner, external_begin_frame_source.Pass())); } else { - layer_tree_host->InitializeForTesting(SingleThreadProxy::Create( - layer_tree_host.get(), - client, - main_task_runner, - external_begin_frame_source.Pass())); + layer_tree_host->InitializeForTesting( + SingleThreadProxyForTest::Create( + test_hooks, + layer_tree_host.get(), + client, + main_task_runner, + external_begin_frame_source.Pass())); } return layer_tree_host.Pass(); } @@ -431,8 +502,6 @@ class LayerTreeHostForTesting : public LayerTreeHost { void set_test_started(bool started) { test_started_ = started; } - void DidDeferCommit() override { test_hooks_->DidDeferCommit(); } - private: LayerTreeHostForTesting(TestHooks* test_hooks, LayerTreeHostClient* client, @@ -524,6 +593,13 @@ void LayerTreeTest::PostAddLongAnimationToMainThread( 1.0)); } +void LayerTreeTest::PostSetDeferCommitsToMainThread(bool defer_commits) { + main_task_runner_->PostTask( + FROM_HERE, + base::Bind(&LayerTreeTest::DispatchSetDeferCommits, + main_thread_weak_ptr_, defer_commits)); +} + void LayerTreeTest::PostSetNeedsCommitToMainThread() { main_task_runner_->PostTask(FROM_HERE, base::Bind(&LayerTreeTest::DispatchSetNeedsCommit, @@ -655,6 +731,13 @@ void LayerTreeTest::DispatchAddAnimation(Layer* layer_to_receive_animation, } } +void LayerTreeTest::DispatchSetDeferCommits(bool defer_commits) { + DCHECK(!proxy() || proxy()->IsMainThread()); + + if (layer_tree_host_) + layer_tree_host_->SetDeferCommits(defer_commits); +} + void LayerTreeTest::DispatchSetNeedsCommit() { DCHECK(!proxy() || proxy()->IsMainThread()); diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 4e38ae6..4abedd7 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h @@ -84,13 +84,13 @@ class TestHooks : public AnimationDelegate { virtual void DidCommit() {} virtual void DidCommitAndDrawFrame() {} virtual void DidCompleteSwapBuffers() {} - virtual void DidDeferCommit() {} virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl, bool visible) {} virtual void ScheduleComposite() {} virtual void SendBeginFramesToChildren(const BeginFrameArgs& args) {} // Hooks for SchedulerClient. + virtual void WillBeginImplFrame(const BeginFrameArgs& args) {} virtual void ScheduledActionWillSendBeginMainFrame() {} virtual void ScheduledActionSendBeginMainFrame() {} virtual void ScheduledActionDrawAndSwapIfPossible() {} @@ -137,6 +137,7 @@ class LayerTreeTest : public testing::Test, public TestHooks { void PostAddAnimationToMainThread(Layer* layer_to_receive_animation); void PostAddInstantAnimationToMainThread(Layer* layer_to_receive_animation); void PostAddLongAnimationToMainThread(Layer* layer_to_receive_animation); + void PostSetDeferCommitsToMainThread(bool defer_commits); void PostSetNeedsCommitToMainThread(); void PostSetNeedsUpdateLayersToMainThread(); void PostSetNeedsRedrawToMainThread(); @@ -162,6 +163,7 @@ class LayerTreeTest : public testing::Test, public TestHooks { virtual void DispatchAddAnimation(Layer* layer_to_receive_animation, double animation_duration); + void DispatchSetDeferCommits(bool defer_commits); void DispatchSetNeedsCommit(); void DispatchSetNeedsUpdateLayers(); void DispatchSetNeedsRedraw(); diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 30b4275..0f48cb2 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -480,8 +480,6 @@ void LayerTreeHost::SetDeferCommits(bool defer_commits) { proxy_->SetDeferCommits(defer_commits); } -void LayerTreeHost::DidDeferCommit() {} - void LayerTreeHost::SetNeedsDisplayOnAllLayers() { std::stack<Layer*> layer_stack; layer_stack.push(root_layer()); diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 68bc1eb..7db722f 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h @@ -151,9 +151,6 @@ class CC_EXPORT LayerTreeHost { void SetDeferCommits(bool defer_commits); - // Test only hook - virtual void DidDeferCommit(); - int source_frame_number() const { return source_frame_number_; } void SetNeedsDisplayOnAllLayers(); diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index ab1224e..7378694 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -2029,22 +2029,33 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousInvalidate); class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { public: LayerTreeHostTestDeferCommits() - : num_commits_deferred_(0), num_complete_commits_(0) {} + : num_will_begin_impl_frame_(0), + num_send_begin_main_frame_(0) {} void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void DidDeferCommit() override { - num_commits_deferred_++; - layer_tree_host()->SetDeferCommits(false); + void WillBeginImplFrame(const BeginFrameArgs& args) override { + num_will_begin_impl_frame_++; + switch (num_will_begin_impl_frame_) { + case 1: + break; + case 2: + PostSetNeedsCommitToMainThread(); + break; + case 3: + PostSetDeferCommitsToMainThread(false); + break; + default: + NOTREACHED(); + break; + } } - void DidCommit() override { - num_complete_commits_++; - switch (num_complete_commits_) { + void ScheduledActionSendBeginMainFrame() override { + num_send_begin_main_frame_++; + switch (num_send_begin_main_frame_) { case 1: - EXPECT_EQ(0, num_commits_deferred_); - layer_tree_host()->SetDeferCommits(true); - PostSetNeedsCommitToMainThread(); + PostSetDeferCommitsToMainThread(true); break; case 2: EndTest(); @@ -2056,13 +2067,13 @@ class LayerTreeHostTestDeferCommits : public LayerTreeHostTest { } void AfterTest() override { - EXPECT_EQ(1, num_commits_deferred_); - EXPECT_EQ(2, num_complete_commits_); + EXPECT_GE(3, num_will_begin_impl_frame_); + EXPECT_EQ(2, num_send_begin_main_frame_); } private: - int num_commits_deferred_; - int num_complete_commits_; + int num_will_begin_impl_frame_; + int num_send_begin_main_frame_; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeferCommits); @@ -4798,22 +4809,24 @@ class LayerTreeHostTestKeepSwapPromise : public LayerTreeTest { SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestKeepSwapPromise); -class LayerTreeHostTestBreakSwapPromiseForVisibilityAbortedCommit +class LayerTreeHostTestBreakSwapPromiseForVisibility : public LayerTreeHostTest { protected: void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void DidCommit() override { - layer_tree_host()->SetDeferCommits(true); - layer_tree_host()->SetNeedsCommit(); - } - - void DidDeferCommit() override { + void SetVisibleFalseAndQueueSwapPromise() { layer_tree_host()->SetVisible(false); scoped_ptr<SwapPromise> swap_promise( new TestSwapPromise(&swap_promise_result_)); layer_tree_host()->QueueSwapPromise(swap_promise.Pass()); - layer_tree_host()->SetDeferCommits(false); + } + + void ScheduledActionWillSendBeginMainFrame() override { + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&LayerTreeHostTestBreakSwapPromiseForVisibility + ::SetVisibleFalseAndQueueSwapPromise, + base::Unretained(this))); } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -4834,27 +4847,33 @@ class LayerTreeHostTestBreakSwapPromiseForVisibilityAbortedCommit TestSwapPromiseResult swap_promise_result_; }; -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeHostTestBreakSwapPromiseForVisibilityAbortedCommit); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestBreakSwapPromiseForVisibility); -class LayerTreeHostTestBreakSwapPromiseForContextAbortedCommit - : public LayerTreeHostTest { +class LayerTreeHostTestBreakSwapPromiseForContext : public LayerTreeHostTest { protected: - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void DidCommit() override { - if (TestEnded()) - return; - layer_tree_host()->SetDeferCommits(true); - layer_tree_host()->SetNeedsCommit(); + LayerTreeHostTestBreakSwapPromiseForContext() + : output_surface_lost_triggered_(false) { } - void DidDeferCommit() override { + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void LoseOutputSurfaceAndQueueSwapPromise() { layer_tree_host()->DidLoseOutputSurface(); scoped_ptr<SwapPromise> swap_promise( new TestSwapPromise(&swap_promise_result_)); layer_tree_host()->QueueSwapPromise(swap_promise.Pass()); - layer_tree_host()->SetDeferCommits(false); + } + + void ScheduledActionWillSendBeginMainFrame() override { + if (output_surface_lost_triggered_) + return; + output_surface_lost_triggered_ = true; + + MainThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&LayerTreeHostTestBreakSwapPromiseForContext + ::LoseOutputSurfaceAndQueueSwapPromise, + base::Unretained(this))); } void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, @@ -4874,11 +4893,12 @@ class LayerTreeHostTestBreakSwapPromiseForContextAbortedCommit } } + bool output_surface_lost_triggered_; TestSwapPromiseResult swap_promise_result_; }; SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeHostTestBreakSwapPromiseForContextAbortedCommit); + LayerTreeHostTestBreakSwapPromiseForContext); class SimpleSwapPromiseMonitor : public SwapPromiseMonitor { public: diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index af9c7a6..56e52ad 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc @@ -1770,12 +1770,7 @@ class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame deferred_ = true; // Defer commits before the BeginFrame arrives, causing it to be delayed. - MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame:: - DeferCommitsOnMainThread, - base::Unretained(this), - true)); + PostSetDeferCommitsToMainThread(true); // Meanwhile, lose the context while we are in defer commits. ImplThreadTaskRunner()->PostTask( FROM_HERE, @@ -1788,16 +1783,7 @@ class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame LoseContext(); // After losing the context, stop deferring commits. - MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame:: - DeferCommitsOnMainThread, - base::Unretained(this), - false)); - } - - void DeferCommitsOnMainThread(bool defer_commits) { - layer_tree_host()->SetDeferCommits(defer_commits); + PostSetDeferCommitsToMainThread(false); } void WillBeginMainFrame() override { diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index c8eb6b0..dc58d39 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc @@ -45,7 +45,6 @@ SingleThreadProxy::SingleThreadProxy( next_frame_is_newly_committed_frame_(false), inside_draw_(false), defer_commits_(false), - commit_was_deferred_(false), commit_requested_(false), inside_synchronous_composite_(false), output_surface_creation_requested_(false), @@ -313,10 +312,7 @@ void SingleThreadProxy::SetDeferCommits(bool defer_commits) { TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this); defer_commits_ = defer_commits; - if (!defer_commits_ && commit_was_deferred_) { - commit_was_deferred_ = false; - BeginMainFrame(); - } + scheduler_on_impl_thread_->SetDeferCommits(defer_commits); } bool SingleThreadProxy::CommitRequested() const { @@ -680,9 +676,10 @@ void SingleThreadProxy::ScheduledActionSendBeginMainFrame() { void SingleThreadProxy::BeginMainFrame() { if (defer_commits_) { - DCHECK(!commit_was_deferred_); - commit_was_deferred_ = true; - layer_tree_host_->DidDeferCommit(); + TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit", + TRACE_EVENT_SCOPE_THREAD); + BeginMainFrameAbortedOnImplThread( + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT); return; } diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index a6c348a..132610a 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -114,13 +114,14 @@ class CC_EXPORT SingleThreadProxy : public Proxy, // Called by the legacy path where RenderWidget does the scheduling. void CompositeImmediately(base::TimeTicks frame_begin_time); - private: + protected: SingleThreadProxy( LayerTreeHost* layer_tree_host, LayerTreeHostSingleThreadClient* client, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, scoped_ptr<BeginFrameSource> external_begin_frame_source); + private: void BeginMainFrame(); void BeginMainFrameAbortedOnImplThread(CommitEarlyOutReason reason); void DoAnimate(); @@ -154,7 +155,6 @@ class CC_EXPORT SingleThreadProxy : public Proxy, bool inside_draw_; bool defer_commits_; - bool commit_was_deferred_; bool commit_requested_; bool inside_synchronous_composite_; diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index c343c97..88f1314 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -452,13 +452,16 @@ void ThreadProxy::SetDeferCommits(bool defer_commits) { else TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this); - if (!main().defer_commits && main().pending_deferred_commit) { - Proxy::MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::BeginMainFrame, - main_thread_weak_ptr_, - base::Passed(&main().pending_deferred_commit))); - } + Proxy::ImplThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&ThreadProxy::SetDeferCommitsOnImplThread, + impl_thread_weak_ptr_, + defer_commits)); +} + +void ThreadProxy::SetDeferCommitsOnImplThread(bool defer_commits) const { + DCHECK(IsImplThread()); + impl().scheduler->SetDeferCommits(defer_commits); } bool ThreadProxy::CommitRequested() const { @@ -701,10 +704,12 @@ void ThreadProxy::BeginMainFrame( DCHECK(IsMainThread()); if (main().defer_commits) { - main().pending_deferred_commit = begin_main_frame_state.Pass(); - layer_tree_host()->DidDeferCommit(); - TRACE_EVENT_INSTANT0( - "cc", "EarlyOut_DeferCommits", TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit", + TRACE_EVENT_SCOPE_THREAD); + Proxy::ImplThreadTaskRunner()->PostTask( + FROM_HERE, base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread, + impl_thread_weak_ptr_, + CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT)); return; } diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index 0d15b5a..b4050bd 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -79,7 +79,6 @@ class CC_EXPORT ThreadProxy : public Proxy, RendererCapabilities renderer_capabilities_main_thread_copy; - scoped_ptr<BeginMainFrameAndCommitState> pending_deferred_commit; base::WeakPtrFactory<ThreadProxy> weak_factory; }; @@ -283,6 +282,7 @@ class CC_EXPORT ThreadProxy : public Proxy, void MainThreadHasStoppedFlingingOnImplThread(); void SetInputThrottledUntilCommitOnImplThread(bool is_throttled); void SetDebugStateOnImplThread(const LayerTreeDebugState& debug_state); + void SetDeferCommitsOnImplThread(bool defer_commits) const; LayerTreeHost* layer_tree_host(); const LayerTreeHost* layer_tree_host() const; |