summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorsimonhong <simonhong@chromium.org>2015-01-29 15:02:39 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-29 23:04:51 +0000
commit1625b74468e4dd55f54ba209f8e91d05493875b9 (patch)
tree9dc54343e4893d16029a4387d935ba95940be7c0 /cc
parent48515fb7d095fd26c175999e2760ec4aa3db0e42 (diff)
downloadchromium_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.h3
-rw-r--r--cc/scheduler/scheduler.cc8
-rw-r--r--cc/scheduler/scheduler.h2
-rw-r--r--cc/scheduler/scheduler_state_machine.cc13
-rw-r--r--cc/scheduler/scheduler_state_machine.h3
-rw-r--r--cc/scheduler/scheduler_state_machine_unittest.cc23
-rw-r--r--cc/scheduler/scheduler_unittest.cc70
-rw-r--r--cc/test/layer_tree_test.cc105
-rw-r--r--cc/test/layer_tree_test.h4
-rw-r--r--cc/trees/layer_tree_host.cc2
-rw-r--r--cc/trees/layer_tree_host.h3
-rw-r--r--cc/trees/layer_tree_host_unittest.cc92
-rw-r--r--cc/trees/layer_tree_host_unittest_context.cc18
-rw-r--r--cc/trees/single_thread_proxy.cc13
-rw-r--r--cc/trees/single_thread_proxy.h4
-rw-r--r--cc/trees/thread_proxy.cc27
-rw-r--r--cc/trees/thread_proxy.h2
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;