summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorenne <enne@chromium.org>2016-03-17 12:50:26 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-17 19:52:56 +0000
commit061ea9c84412147d772b91e138413cfd2a515eab (patch)
treea6d6b94c4d1c96baf9a62e3464d2b2204005af00 /cc
parent4588b6b41a9356338c1c2a2eea3bf11fb8647a35 (diff)
downloadchromium_src-061ea9c84412147d772b91e138413cfd2a515eab.zip
chromium_src-061ea9c84412147d772b91e138413cfd2a515eab.tar.gz
chromium_src-061ea9c84412147d772b91e138413cfd2a515eab.tar.bz2
Allow cc::Scheduler begin frame source to be changed
Also, add back throttling tests to check changing the source. Depends on https://codereview.chromium.org/1765723002 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1774323003 Cr-Commit-Position: refs/heads/master@{#381779}
Diffstat (limited to 'cc')
-rw-r--r--cc/scheduler/scheduler.cc16
-rw-r--r--cc/scheduler/scheduler.h5
-rw-r--r--cc/scheduler/scheduler_unittest.cc188
-rw-r--r--cc/test/scheduler_test_common.h3
4 files changed, 197 insertions, 15 deletions
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index f5c6d60..7dcf738 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -49,7 +49,7 @@ Scheduler::Scheduler(
client_(client),
layer_tree_host_id_(layer_tree_host_id),
task_runner_(task_runner),
- begin_frame_source_(begin_frame_source),
+ begin_frame_source_(nullptr),
observing_begin_frame_source_(false),
compositor_timing_history_(std::move(compositor_timing_history)),
begin_impl_frame_deadline_mode_(
@@ -68,6 +68,7 @@ Scheduler::Scheduler(
begin_impl_frame_deadline_closure_ = base::Bind(
&Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
+ SetBeginFrameSource(begin_frame_source);
ProcessScheduledActions();
}
@@ -113,6 +114,17 @@ void Scheduler::NotifyReadyToDraw() {
ProcessScheduledActions();
}
+void Scheduler::SetBeginFrameSource(BeginFrameSource* source) {
+ DCHECK(source);
+ if (source == begin_frame_source_)
+ return;
+ if (begin_frame_source_ && observing_begin_frame_source_)
+ begin_frame_source_->RemoveObserver(this);
+ begin_frame_source_ = source;
+ if (observing_begin_frame_source_)
+ begin_frame_source_->AddObserver(this);
+}
+
void Scheduler::SetNeedsBeginMainFrame() {
state_machine_.SetNeedsBeginMainFrame();
ProcessScheduledActions();
@@ -744,7 +756,7 @@ void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const {
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
&frame_tracing_enabled);
- if (frame_tracing_enabled) {
+ if (frame_tracing_enabled && begin_frame_source_) {
state->BeginDictionary("begin_frame_source_");
begin_frame_source_->AsValueInto(state);
state->EndDictionary();
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 4828896..21c9d04 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -80,6 +80,7 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase {
void SetCanDraw(bool can_draw);
void NotifyReadyToActivate();
void NotifyReadyToDraw();
+ void SetBeginFrameSource(BeginFrameSource* source);
void SetNeedsBeginMainFrame();
// Requests a single impl frame (after the current frame if there is one
@@ -140,6 +141,10 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase {
void SetChildrenNeedBeginFrames(bool children_need_begin_frames);
void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
+ const BeginFrameSource* begin_frame_source() const {
+ return begin_frame_source_;
+ }
+
protected:
Scheduler(SchedulerClient* client,
const SchedulerSettings& scheduler_settings,
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index 37ab466..1ca9b69 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -257,18 +257,17 @@ class SchedulerTest : public testing::Test {
protected:
TestScheduler* CreateScheduler() {
BeginFrameSource* frame_source;
+ unthrottled_frame_source_ = TestBackToBackBeginFrameSource::Create(
+ now_src_.get(), task_runner_.get());
+ fake_external_begin_frame_source_.reset(
+ new FakeExternalBeginFrameSource(client_.get()));
+ synthetic_frame_source_ = TestSyntheticBeginFrameSource::Create(
+ now_src_.get(), task_runner_.get(), BeginFrameArgs::DefaultInterval());
if (!scheduler_settings_.throttle_frame_production) {
- unthrottled_frame_source_ = TestBackToBackBeginFrameSource::Create(
- now_src_.get(), task_runner_.get());
frame_source = unthrottled_frame_source_.get();
} else if (scheduler_settings_.use_external_begin_frame_source) {
- fake_external_begin_frame_source_.reset(
- new FakeExternalBeginFrameSource(client_.get()));
frame_source = fake_external_begin_frame_source_.get();
} else {
- synthetic_frame_source_ = TestSyntheticBeginFrameSource::Create(
- now_src_.get(), task_runner_.get(),
- BeginFrameArgs::DefaultInterval());
frame_source = synthetic_frame_source_.get();
}
@@ -396,8 +395,8 @@ class SchedulerTest : public testing::Test {
// Send the next BeginFrame message if using an external source, otherwise
// it will be already in the task queue.
- if (scheduler_->settings().use_external_begin_frame_source &&
- scheduler_->FrameProductionThrottled()) {
+ if (scheduler_->begin_frame_source() ==
+ fake_external_begin_frame_source_.get()) {
EXPECT_TRUE(scheduler_->begin_frames_expected());
SendNextBeginFrame();
}
@@ -411,7 +410,8 @@ class SchedulerTest : public testing::Test {
}
BeginFrameArgs SendNextBeginFrame() {
- DCHECK(scheduler_->settings().use_external_begin_frame_source);
+ DCHECK_EQ(scheduler_->begin_frame_source(),
+ fake_external_begin_frame_source_.get());
// Creep the time forward so that any BeginFrameArgs is not equal to the
// last one otherwise we violate the BeginFrameSource contract.
now_src_->Advance(BeginFrameArgs::DefaultInterval());
@@ -3055,6 +3055,174 @@ TEST_F(SchedulerTest, ScheduledActionActivateAfterBeginFrameSourcePaused) {
EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
}
+// Tests to ensure frame sources can be successfully changed while drawing.
+TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
+ scheduler_settings_.use_external_begin_frame_source = true;
+ SetUpScheduler(true);
+
+ // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsRedraw();
+ EXPECT_SINGLE_ACTION("AddObserver(this)", client_);
+ client_->Reset();
+
+ EXPECT_SCOPED(AdvanceFrame());
+ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1);
+ EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(scheduler_->begin_frames_expected());
+ client_->Reset();
+ task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
+ scheduler_->SetNeedsRedraw();
+
+ // Switch to an unthrottled frame source.
+ scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
+ client_->Reset();
+
+ // Unthrottled frame source will immediately begin a new frame.
+ task_runner().RunPendingTasks(); // Run posted BeginFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1);
+ EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
+ client_->Reset();
+
+ // If we don't swap on the deadline, we wait for the next BeginFrame.
+ task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
+ EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
+ client_->Reset();
+}
+
+// Tests to ensure frame sources can be successfully changed while a frame
+// deadline is pending.
+TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
+ scheduler_settings_.use_external_begin_frame_source = true;
+ SetUpScheduler(true);
+
+ // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsRedraw();
+ EXPECT_SINGLE_ACTION("AddObserver(this)", client_);
+ client_->Reset();
+
+ EXPECT_SCOPED(AdvanceFrame());
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
+
+ // Switch to an unthrottled frame source before the frame deadline is hit.
+ scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
+ client_->Reset();
+
+ EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(scheduler_->begin_frames_expected());
+ client_->Reset();
+
+ task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
+ client_->Reset();
+
+ // Unthrottled frame source will immediately begin a new frame.
+ task_runner().RunPendingTasks(); // Run BeginFrame.
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
+ scheduler_->SetNeedsRedraw();
+ client_->Reset();
+
+ task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
+ EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
+ client_->Reset();
+}
+
+// Tests to ensure that the active frame source can successfully be changed from
+// unthrottled to throttled.
+TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
+ scheduler_settings_.throttle_frame_production = false;
+ scheduler_settings_.use_external_begin_frame_source = true;
+ SetUpScheduler(true);
+
+ scheduler_->SetNeedsRedraw();
+ EXPECT_NO_ACTION(client_);
+ client_->Reset();
+
+ task_runner().RunPendingTasks(); // Run posted BeginFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1);
+ EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
+ client_->Reset();
+
+ task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
+ EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
+ client_->Reset();
+
+ // Switch to a throttled frame source.
+ scheduler_->SetBeginFrameSource(fake_external_begin_frame_source_.get());
+ client_->Reset();
+
+ // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsRedraw();
+ task_runner().RunPendingTasks();
+ EXPECT_NO_ACTION(client_);
+ client_->Reset();
+
+ EXPECT_SCOPED(AdvanceFrame());
+ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1);
+ EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(scheduler_->begin_frames_expected());
+ client_->Reset();
+ task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
+}
+
+// This test maskes sure that switching a frame source when not observing
+// such as when not visible also works.
+TEST_F(SchedulerTest, SwitchFrameSourceWhenNotObserving) {
+ scheduler_settings_.use_external_begin_frame_source = true;
+ SetUpScheduler(true);
+
+ // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_SINGLE_ACTION("AddObserver(this)", client_);
+ client_->Reset();
+
+ // Begin new frame.
+ EXPECT_SCOPED(AdvanceFrame());
+ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks());
+ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
+
+ client_->Reset();
+ scheduler_->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
+
+ client_->Reset();
+ scheduler_->NotifyReadyToActivate();
+ EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
+
+ // Scheduler loses output surface, and stops waiting for ready to draw signal.
+ client_->Reset();
+ scheduler_->DidLoseOutputSurface();
+ EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
+ task_runner().RunPendingTasks();
+ EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
+ EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3);
+ EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
+
+ // Changing begin frame source doesn't do anything.
+ // The unthrottled source doesn't print Add/RemoveObserver like the fake one.
+ client_->Reset();
+ scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get());
+ EXPECT_NO_ACTION(client_);
+
+ client_->Reset();
+ scheduler_->DidCreateAndInitializeOutputSurface();
+ EXPECT_NO_ACTION(client_);
+
+ client_->Reset();
+ scheduler_->SetNeedsBeginMainFrame();
+ EXPECT_NO_ACTION(client_);
+
+ client_->Reset();
+ EXPECT_SCOPED(AdvanceFrame());
+ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
+}
+
// Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
scheduler_settings_.use_external_begin_frame_source = true;
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 259e991..414f31f 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -233,9 +233,6 @@ class TestScheduler : public Scheduler {
}
BeginFrameSource& frame_source() { return *begin_frame_source_; }
- bool FrameProductionThrottled() {
- return settings_.throttle_frame_production;
- }
bool MainThreadMissedLastDeadline() const {
return state_machine_.main_thread_missed_last_deadline();