summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-28 05:35:54 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-28 05:35:54 +0000
commit1120afabccebfc07f6d6990b2696508f4a2f5ccc (patch)
tree87c7bb2c6aa8d53a763b2a0e4784c35197de8a3d /cc
parentccf251570a3e16fa1cebc24ac8f8a3a3f05aabd1 (diff)
downloadchromium_src-1120afabccebfc07f6d6990b2696508f4a2f5ccc.zip
chromium_src-1120afabccebfc07f6d6990b2696508f4a2f5ccc.tar.gz
chromium_src-1120afabccebfc07f6d6990b2696508f4a2f5ccc.tar.bz2
Make SingleThreadProxy a SchedulerClient
This makes ui::Compositor no longer in charge of scheduling commits and draws, deferring it to cc::Scheduler. BUG=329552, 287250 Review URL: https://codereview.chromium.org/134623005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@280493 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/scheduler/scheduler.cc27
-rw-r--r--cc/scheduler/scheduler.h15
-rw-r--r--cc/scheduler/scheduler_state_machine.cc4
-rw-r--r--cc/test/fake_layer_tree_host_client.h2
-rw-r--r--cc/test/layer_tree_test.cc48
-rw-r--r--cc/test/layer_tree_test.h6
-rw-r--r--cc/trees/layer_tree_host.cc2
-rw-r--r--cc/trees/layer_tree_host_single_thread_client.h4
-rw-r--r--cc/trees/layer_tree_host_unittest.cc6
-rw-r--r--cc/trees/layer_tree_host_unittest_animation.cc9
-rw-r--r--cc/trees/layer_tree_host_unittest_context.cc80
-rw-r--r--cc/trees/layer_tree_host_unittest_no_message_loop.cc2
-rw-r--r--cc/trees/layer_tree_settings.cc1
-rw-r--r--cc/trees/layer_tree_settings.h1
-rw-r--r--cc/trees/single_thread_proxy.cc339
-rw-r--r--cc/trees/single_thread_proxy.h48
-rw-r--r--cc/trees/thread_proxy.cc5
17 files changed, 388 insertions, 211 deletions
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 4a682cd..8f127e9 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -77,11 +77,11 @@ Scheduler::Scheduler(
SchedulerClient* client,
const SchedulerSettings& scheduler_settings,
int layer_tree_host_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner)
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
: settings_(scheduler_settings),
client_(client),
layer_tree_host_id_(layer_tree_host_id),
- impl_task_runner_(impl_task_runner),
+ task_runner_(task_runner),
vsync_interval_(BeginFrameArgs::DefaultInterval()),
last_set_needs_begin_frame_(false),
begin_unthrottled_frame_posted_(false),
@@ -126,7 +126,7 @@ Scheduler::~Scheduler() {
void Scheduler::SetupSyntheticBeginFrames() {
DCHECK(!synthetic_begin_frame_source_);
synthetic_begin_frame_source_.reset(
- new SyntheticBeginFrameSource(this, impl_task_runner_.get()));
+ new SyntheticBeginFrameSource(this, task_runner_.get()));
}
void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
@@ -272,6 +272,9 @@ base::TimeTicks Scheduler::LastBeginImplFrameTime() {
}
void Scheduler::SetupNextBeginFrameIfNeeded() {
+ if (!task_runner_)
+ return;
+
bool needs_begin_frame = state_machine_.BeginFrameNeeded();
if (settings_.throttle_frame_production) {
@@ -326,7 +329,7 @@ void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled(
}
begin_unthrottled_frame_posted_ = true;
- impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
+ task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
}
// BeginUnthrottledFrame is used when we aren't throttling frame production.
@@ -360,7 +363,7 @@ void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) {
base::TimeDelta delay = begin_impl_frame_args_.IsValid()
? begin_impl_frame_args_.interval
: BeginFrameArgs::DefaultInterval();
- impl_task_runner_->PostDelayedTask(
+ task_runner_->PostDelayedTask(
FROM_HERE, poll_for_draw_triggers_task_.callback(), delay);
}
} else {
@@ -385,9 +388,9 @@ void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) {
// Since we'd rather get a BeginImplFrame by the normal mechanism, we
// set the interval to twice the interval from the previous frame.
advance_commit_state_task_.Reset(advance_commit_state_closure_);
- impl_task_runner_->PostDelayedTask(FROM_HERE,
- advance_commit_state_task_.callback(),
- begin_impl_frame_args_.interval * 2);
+ task_runner_->PostDelayedTask(FROM_HERE,
+ advance_commit_state_task_.callback(),
+ begin_impl_frame_args_.interval * 2);
}
} else {
advance_commit_state_task_.Cancel();
@@ -489,7 +492,7 @@ void Scheduler::PostBeginRetroFrameIfNeeded() {
return;
begin_retro_frame_posted_ = true;
- impl_task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_);
+ task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_);
}
// BeginImplFrame starts a compositor frame that will wait up until a deadline
@@ -497,8 +500,8 @@ void Scheduler::PostBeginRetroFrameIfNeeded() {
// any asynchronous animation and scroll/pinch updates.
void Scheduler::BeginImplFrame(const BeginFrameArgs& args) {
TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", ToTrace(args));
- DCHECK(state_machine_.begin_impl_frame_state() ==
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
+ DCHECK_EQ(state_machine_.begin_impl_frame_state(),
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
DCHECK(state_machine_.HasInitializedOutputSurface());
advance_commit_state_task_.Cancel();
@@ -565,7 +568,7 @@ void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) {
base::TimeDelta delta = deadline - gfx::FrameTime::Now();
if (delta <= base::TimeDelta())
delta = base::TimeDelta();
- impl_task_runner_->PostDelayedTask(
+ task_runner_->PostDelayedTask(
FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
}
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 3de06ac..f392047 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -54,9 +54,9 @@ class CC_EXPORT Scheduler {
SchedulerClient* client,
const SchedulerSettings& scheduler_settings,
int layer_tree_host_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner) {
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
return make_scoped_ptr(new Scheduler(
- client, scheduler_settings, layer_tree_host_id, impl_task_runner));
+ client, scheduler_settings, layer_tree_host_id, task_runner));
}
virtual ~Scheduler();
@@ -170,16 +170,15 @@ class CC_EXPORT Scheduler {
scoped_refptr<DelayBasedTimeSource> time_source_;
};
- Scheduler(
- SchedulerClient* client,
- const SchedulerSettings& scheduler_settings,
- int layer_tree_host_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner);
+ Scheduler(SchedulerClient* client,
+ const SchedulerSettings& scheduler_settings,
+ int layer_tree_host_id,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
const SchedulerSettings settings_;
SchedulerClient* client_;
int layer_tree_host_id_;
- scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::TimeDelta vsync_interval_;
base::TimeDelta estimated_parent_draw_time_;
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index dea25b40..e2e8168 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -1006,7 +1006,9 @@ void SchedulerStateMachine::DidDrawIfPossibleCompleted(DrawResult result) {
}
}
-void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
+void SchedulerStateMachine::SetNeedsCommit() {
+ needs_commit_ = true;
+}
void SchedulerStateMachine::NotifyReadyToCommit() {
DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << *AsValue();
diff --git a/cc/test/fake_layer_tree_host_client.h b/cc/test/fake_layer_tree_host_client.h
index f928453..7f7bd35 100644
--- a/cc/test/fake_layer_tree_host_client.h
+++ b/cc/test/fake_layer_tree_host_client.h
@@ -42,8 +42,6 @@ class FakeLayerTreeHostClient : public LayerTreeHostClient,
virtual void DidCompleteSwapBuffers() OVERRIDE {}
// LayerTreeHostSingleThreadClient implementation.
- virtual void ScheduleComposite() OVERRIDE {}
- virtual void ScheduleAnimation() OVERRIDE {}
virtual void DidPostSwapBuffers() OVERRIDE {}
virtual void DidAbortSwapBuffers() OVERRIDE {}
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 3437f8c..a680441 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -321,14 +321,6 @@ class LayerTreeHostClientForTesting : public LayerTreeHostClient,
test_hooks_->DidCompleteSwapBuffers();
}
- virtual void ScheduleComposite() OVERRIDE {
- test_hooks_->ScheduleComposite();
- }
-
- virtual void ScheduleAnimation() OVERRIDE {
- test_hooks_->ScheduleAnimation();
- }
-
virtual void DidPostSwapBuffers() OVERRIDE {}
virtual void DidAbortSwapBuffers() OVERRIDE {}
@@ -401,7 +393,6 @@ LayerTreeTest::LayerTreeTest()
end_when_begin_returns_(false),
timed_out_(false),
scheduled_(false),
- schedule_when_set_visible_true_(false),
started_(false),
ended_(false),
delegating_renderer_(false),
@@ -564,15 +555,6 @@ void LayerTreeTest::Timeout() {
EndTest();
}
-void LayerTreeTest::ScheduleComposite() {
- if (!started_ || scheduled_)
- return;
- scheduled_ = true;
- main_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&LayerTreeTest::DispatchComposite, main_thread_weak_ptr_));
-}
-
void LayerTreeTest::RealEndTest() {
if (layer_tree_host_ && proxy()->CommitPendingForTesting()) {
main_task_runner_->PostTask(
@@ -624,16 +606,8 @@ void LayerTreeTest::DispatchSetNeedsRedrawRect(const gfx::Rect& damage_rect) {
void LayerTreeTest::DispatchSetVisible(bool visible) {
DCHECK(!proxy() || proxy()->IsMainThread());
-
- if (!layer_tree_host_)
- return;
-
- layer_tree_host_->SetVisible(visible);
-
- // If the LTH is being made visible and a previous ScheduleComposite() was
- // deferred because the LTH was not visible, re-schedule the composite now.
- if (layer_tree_host_->visible() && schedule_when_set_visible_true_)
- ScheduleComposite();
+ if (layer_tree_host_)
+ layer_tree_host_->SetVisible(visible);
}
void LayerTreeTest::DispatchSetNextCommitForcesRedraw() {
@@ -643,24 +617,6 @@ void LayerTreeTest::DispatchSetNextCommitForcesRedraw() {
layer_tree_host_->SetNextCommitForcesRedraw();
}
-void LayerTreeTest::DispatchComposite() {
- scheduled_ = false;
-
- if (!layer_tree_host_)
- return;
-
- // If the LTH is not visible, defer the composite until the LTH is made
- // visible.
- if (!layer_tree_host_->visible()) {
- schedule_when_set_visible_true_ = true;
- return;
- }
-
- schedule_when_set_visible_true_ = false;
- base::TimeTicks now = gfx::FrameTime::Now();
- layer_tree_host_->Composite(now);
-}
-
void LayerTreeTest::RunTest(bool threaded,
bool delegating_renderer,
bool impl_side_painting) {
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 8f38dda..619ae96 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -71,8 +71,6 @@ class TestHooks : public AnimationDelegate {
virtual void DidCommit() {}
virtual void DidCommitAndDrawFrame() {}
virtual void DidCompleteSwapBuffers() {}
- virtual void ScheduleComposite() {}
- virtual void ScheduleAnimation() {}
virtual void DidDeferCommit() {}
virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
bool visible) {}
@@ -139,8 +137,6 @@ class LayerTreeTest : public testing::Test, public TestHooks {
virtual void InitializeSettings(LayerTreeSettings* settings) {}
- virtual void ScheduleComposite() OVERRIDE;
-
void RealEndTest();
virtual void DispatchAddAnimation(Layer* layer_to_receive_animation,
@@ -151,7 +147,6 @@ class LayerTreeTest : public testing::Test, public TestHooks {
void DispatchSetNeedsRedrawRect(const gfx::Rect& damage_rect);
void DispatchSetVisible(bool visible);
void DispatchSetNextCommitForcesRedraw();
- void DispatchComposite();
void DispatchDidAddAnimation();
virtual void AfterTest() = 0;
@@ -204,7 +199,6 @@ class LayerTreeTest : public testing::Test, public TestHooks {
bool end_when_begin_returns_;
bool timed_out_;
bool scheduled_;
- bool schedule_when_set_visible_true_;
bool started_;
bool ended_;
bool delegating_renderer_;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 51b9b4f..6f995d8 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -677,6 +677,8 @@ void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) {
DCHECK(!proxy_->HasImplThread());
SingleThreadProxy* proxy = static_cast<SingleThreadProxy*>(proxy_.get());
+ SetLayerTreeHostClientReady();
+
if (output_surface_lost_)
proxy->CreateAndInitializeOutputSurface();
if (output_surface_lost_)
diff --git a/cc/trees/layer_tree_host_single_thread_client.h b/cc/trees/layer_tree_host_single_thread_client.h
index cb61450..dbca28c 100644
--- a/cc/trees/layer_tree_host_single_thread_client.h
+++ b/cc/trees/layer_tree_host_single_thread_client.h
@@ -10,10 +10,10 @@ namespace cc {
class LayerTreeHostSingleThreadClient {
public:
// Request that the client schedule a composite.
- virtual void ScheduleComposite() = 0;
+ virtual void ScheduleComposite() {}
// Request that the client schedule a composite now, and calculate appropriate
// delay for potential future frame.
- virtual void ScheduleAnimation() = 0;
+ virtual void ScheduleAnimation() {}
// Called whenever the compositor posts a SwapBuffers (either full or
// partial). After DidPostSwapBuffers(), exactly one of
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index b194491..95c44bcf 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -91,8 +91,8 @@ class LayerTreeHostTestSetNeedsCommit1 : public LayerTreeHostTest {
}
virtual void AfterTest() OVERRIDE {
- EXPECT_GE(1, num_commits_);
- EXPECT_GE(1, num_draws_);
+ EXPECT_LE(1, num_commits_);
+ EXPECT_LE(1, num_draws_);
}
private:
@@ -1967,7 +1967,7 @@ class LayerTreeHostTestDeferCommits : public LayerTreeHostTest {
int num_complete_commits_;
};
-MULTI_THREAD_TEST_F(LayerTreeHostTestDeferCommits);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDeferCommits);
class LayerTreeHostWithProxy : public LayerTreeHost {
public:
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index 1542a14..3b2de64 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -726,9 +726,7 @@ class LayerTreeHostAnimationTestContinuousAnimate
: public LayerTreeHostAnimationTest {
public:
LayerTreeHostAnimationTestContinuousAnimate()
- : num_commit_complete_(0),
- num_draw_layers_(0) {
- }
+ : num_commit_complete_(0), num_draw_layers_(0), have_animated_(false) {}
virtual void SetupTree() OVERRIDE {
LayerTreeHostAnimationTest::SetupTree();
@@ -747,6 +745,7 @@ class LayerTreeHostAnimationTestContinuousAnimate
if (num_draw_layers_ == 2)
return;
layer_tree_host()->SetNeedsAnimate();
+ have_animated_ = true;
}
virtual void Layout() OVERRIDE {
@@ -767,16 +766,18 @@ class LayerTreeHostAnimationTestContinuousAnimate
virtual void AfterTest() OVERRIDE {
// Check that we didn't commit twice between first and second draw.
EXPECT_EQ(1, num_commit_complete_);
+ EXPECT_TRUE(have_animated_);
}
private:
int num_commit_complete_;
int num_draw_layers_;
+ bool have_animated_;
FakeContentLayerClient client_;
scoped_refptr<FakeContentLayer> content_;
};
-MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestContinuousAnimate);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestContinuousAnimate);
class LayerTreeHostAnimationTestCancelAnimateCommit
: public LayerTreeHostAnimationTest {
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
index 879e534..548ff36 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -65,6 +65,9 @@ class LayerTreeHostContextTest : public LayerTreeTest {
}
void LoseContext() {
+ // For sanity-checking tests, they should only call this when the
+ // context is not lost.
+ CHECK(context3d_);
context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
GL_INNOCENT_CONTEXT_RESET_ARB);
context3d_ = NULL;
@@ -200,45 +203,53 @@ class LayerTreeHostContextTestLostContextSucceeds
static const TestCase kTests[] = {
// Losing the context and failing to recreate it (or losing it again
// immediately) a small number of times should succeed.
- {1, // times_to_lose_during_commit
+ {
+ 1, // times_to_lose_during_commit
0, // times_to_lose_during_draw
0, // times_to_fail_recreate
false, // fallback_context_works
},
- {0, // times_to_lose_during_commit
+ {
+ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
0, // times_to_fail_recreate
false, // fallback_context_works
},
- {1, // times_to_lose_during_commit
+ {
+ 1, // times_to_lose_during_commit
0, // times_to_lose_during_draw
3, // times_to_fail_recreate
false, // fallback_context_works
},
- {0, // times_to_lose_during_commit
+ {
+ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
3, // times_to_fail_recreate
false, // fallback_context_works
},
// Losing the context and recreating it any number of times should
// succeed.
- {10, // times_to_lose_during_commit
+ {
+ 10, // times_to_lose_during_commit
0, // times_to_lose_during_draw
0, // times_to_fail_recreate
false, // fallback_context_works
},
- {0, // times_to_lose_during_commit
+ {
+ 0, // times_to_lose_during_commit
10, // times_to_lose_during_draw
0, // times_to_fail_recreate
false, // fallback_context_works
},
// Losing the context, failing to reinitialize it, and making a fallback
// context should work.
- {0, // times_to_lose_during_commit
+ {
+ 0, // times_to_lose_during_commit
1, // times_to_lose_during_draw
0, // times_to_fail_recreate
true, // fallback_context_works
- }, };
+ },
+ };
if (test_case_ >= arraysize(kTests))
return false;
@@ -300,7 +311,8 @@ class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
}
};
-MULTI_THREAD_TEST_F(LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
class LayerTreeHostContextTestLostContextSucceedsWithContent
: public LayerTreeHostContextTestLostContextSucceeds {
@@ -358,10 +370,11 @@ class LayerTreeHostContextTestCreateOutputSurfaceFails
: times_to_fail_(times_to_fail),
expect_fallback_attempt_(expect_fallback_attempt),
did_attempt_fallback_(false),
- times_initialized_(0) {}
+ times_initialized_(0) {
+ times_to_fail_create_ = times_to_fail_;
+ }
virtual void BeginTest() OVERRIDE {
- times_to_fail_create_ = times_to_fail_;
PostSetNeedsCommitToMainThread();
}
@@ -975,12 +988,6 @@ class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
EXPECT_EQ(2, scrollbar_layer_->update_count());
EndTest();
break;
- case 3:
- // Single thread proxy issues extra commits after context lost.
- // http://crbug.com/287250
- if (HasImplThread())
- NOTREACHED();
- break;
default:
NOTREACHED();
}
@@ -1024,12 +1031,10 @@ class UIResourceLostTest : public LayerTreeHostContextTest {
void PostLoseContextToImplThread() {
EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
- base::SingleThreadTaskRunner* task_runner =
- HasImplThread() ? ImplThreadTaskRunner()
- : base::MessageLoopProxy::current();
- task_runner->PostTask(FROM_HERE,
- base::Bind(&LayerTreeHostContextTest::LoseContext,
- base::Unretained(this)));
+ ImplThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&LayerTreeHostContextTest::LoseContext,
+ base::Unretained(this)));
}
protected:
@@ -1084,13 +1089,8 @@ class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
EndTest();
break;
case 5:
- // Single thread proxy issues extra commits after context lost.
- // http://crbug.com/287250
- if (HasImplThread())
- NOTREACHED();
- break;
- case 6:
NOTREACHED();
+ break;
}
}
@@ -1178,13 +1178,8 @@ class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
EndTest();
break;
case 6:
- // Single thread proxy issues extra commits after context lost.
- // http://crbug.com/287250
- if (HasImplThread())
- NOTREACHED();
- break;
- case 8:
NOTREACHED();
+ break;
}
}
@@ -1205,15 +1200,8 @@ class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
// Sequence 2 (continued):
// The previous resource should have been deleted.
EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
- if (HasImplThread()) {
- // The second resource should have been created.
- EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
- } else {
- // The extra commit that happens at context lost in the single thread
- // proxy changes the timing so that the resource has been destroyed.
- // http://crbug.com/287250
- EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id1_));
- }
+ // The second resource should have been created.
+ EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
// The second resource called the resource callback once and since the
// context is lost, a "resource lost" callback was also issued.
EXPECT_EQ(2, ui_resource_->resource_create_count);
@@ -1529,8 +1517,8 @@ class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
bool deferred_;
};
-// TODO(danakj): We don't use scheduler with SingleThreadProxy yet.
-MULTI_THREAD_TEST_F(LayerTreeHostContextTestLoseAfterSendingBeginMainFrame);
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostContextTestLoseAfterSendingBeginMainFrame);
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
index 4c6796f..f687efb 100644
--- a/cc/trees/layer_tree_host_unittest_no_message_loop.cc
+++ b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
@@ -74,8 +74,6 @@ class LayerTreeHostNoMessageLoopTest
virtual void DidCompleteSwapBuffers() OVERRIDE {}
// LayerTreeHostSingleThreadClient overrides.
- virtual void ScheduleComposite() OVERRIDE {}
- virtual void ScheduleAnimation() OVERRIDE {}
virtual void DidPostSwapBuffers() OVERRIDE {}
virtual void DidAbortSwapBuffers() OVERRIDE {}
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 4b56d7c..5193b2d 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -16,6 +16,7 @@ LayerTreeSettings::LayerTreeSettings()
: impl_side_painting(false),
allow_antialiasing(true),
throttle_frame_production(true),
+ single_thread_proxy_scheduler(true),
begin_frame_scheduling_enabled(false),
main_frame_before_draw_enabled(true),
main_frame_before_activation_enabled(false),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 21d72c9..ef2a4955 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -21,6 +21,7 @@ class CC_EXPORT LayerTreeSettings {
bool impl_side_painting;
bool allow_antialiasing;
bool throttle_frame_production;
+ bool single_thread_proxy_scheduler;
bool begin_frame_scheduling_enabled;
bool main_frame_before_draw_enabled;
bool main_frame_before_activation_enabled;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index c254311..46d0814 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -33,7 +33,11 @@ SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
layer_tree_host_(layer_tree_host),
client_(client),
next_frame_is_newly_committed_frame_(false),
- inside_draw_(false) {
+ inside_draw_(false),
+ defer_commits_(false),
+ commit_was_deferred_(false),
+ commit_requested_(false),
+ weak_factory_(this) {
TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
DCHECK(Proxy::IsMainThread());
DCHECK(layer_tree_host);
@@ -73,13 +77,26 @@ void SingleThreadProxy::SetLayerTreeHostClientReady() {
TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
// Scheduling is controlled by the embedder in the single thread case, so
// nothing to do.
+ DCHECK(Proxy::IsMainThread());
+ DebugScopedSetImplThread impl(this);
+ if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
+ !scheduler_on_impl_thread_) {
+ SchedulerSettings scheduler_settings(layer_tree_host_->settings());
+ scheduler_on_impl_thread_ = Scheduler::Create(this,
+ scheduler_settings,
+ layer_tree_host_->id(),
+ MainThreadTaskRunner());
+ scheduler_on_impl_thread_->SetCanStart();
+ scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
+ }
}
void SingleThreadProxy::SetVisible(bool visible) {
TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
DebugScopedSetImplThread impl(this);
layer_tree_host_impl_->SetVisible(visible);
-
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
// Changing visibility could change ShouldComposite().
UpdateBackgroundAnimateTicking();
}
@@ -106,9 +123,14 @@ void SingleThreadProxy::CreateAndInitializeOutputSurface() {
layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
- if (!success) {
- // Force another recreation attempt to happen by requesting another commit.
- SetNeedsCommit();
+ if (success) {
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
+ } else if (Proxy::MainThreadTaskRunner()) {
+ Proxy::MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&SingleThreadProxy::CreateAndInitializeOutputSurface,
+ weak_factory_.GetWeakPtr()));
}
}
@@ -122,17 +144,40 @@ void SingleThreadProxy::SetNeedsAnimate() {
TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
DCHECK(Proxy::IsMainThread());
client_->ScheduleAnimation();
+ SetNeedsCommit();
}
void SingleThreadProxy::SetNeedsUpdateLayers() {
TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
DCHECK(Proxy::IsMainThread());
- client_->ScheduleComposite();
+ SetNeedsCommit();
}
-void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
+void SingleThreadProxy::DoCommit(base::TimeTicks frame_begin_time) {
TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
DCHECK(Proxy::IsMainThread());
+ layer_tree_host_->WillBeginMainFrame();
+ layer_tree_host_->Layout();
+ layer_tree_host_->UpdateClientAnimations(frame_begin_time);
+ layer_tree_host_->AnimateLayers(frame_begin_time);
+ commit_requested_ = false;
+
+ if (PrioritizedResourceManager* contents_texture_manager =
+ layer_tree_host_->contents_texture_manager()) {
+ contents_texture_manager->UnlinkAndClearEvictedBackings();
+ contents_texture_manager->SetMaxMemoryLimitBytes(
+ layer_tree_host_impl_->memory_allocation_limit_bytes());
+ contents_texture_manager->SetExternalPriorityCutoff(
+ layer_tree_host_impl_->memory_allocation_priority_cutoff());
+ }
+
+ scoped_ptr<ResourceUpdateQueue> queue =
+ make_scoped_ptr(new ResourceUpdateQueue);
+
+ layer_tree_host_->UpdateLayers(queue.get());
+
+ layer_tree_host_->WillCommit();
+
// Commit immediately.
{
DebugScopedSetMainThreadBlocked main_thread_blocked(this);
@@ -166,6 +211,8 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
layer_tree_host_impl_->CommitComplete();
+ UpdateBackgroundAnimateTicking();
+
#if DCHECK_IS_ON
// In the single-threaded case, the scale and scroll deltas should never be
// touched on the impl layer tree.
@@ -182,32 +229,64 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
stats_instrumentation->AccumulateAndClearMainThreadStats();
}
layer_tree_host_->CommitComplete();
+ layer_tree_host_->DidBeginMainFrame();
+ timing_history_.DidCommit();
+
next_frame_is_newly_committed_frame_ = true;
}
void SingleThreadProxy::SetNeedsCommit() {
DCHECK(Proxy::IsMainThread());
+ DebugScopedSetImplThread impl(this);
client_->ScheduleComposite();
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->SetNeedsCommit();
+ commit_requested_ = true;
}
void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
- SetNeedsRedrawRectOnImplThread(damage_rect);
+ DCHECK(Proxy::IsMainThread());
+ DebugScopedSetImplThread impl(this);
client_->ScheduleComposite();
+ SetNeedsRedrawRectOnImplThread(damage_rect);
}
void SingleThreadProxy::SetNextCommitWaitsForActivation() {
// There is no activation here other than commit. So do nothing.
+ DCHECK(Proxy::IsMainThread());
}
void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
- // Thread-only feature.
- NOTREACHED();
+ DCHECK(Proxy::IsMainThread());
+ // Deferring commits only makes sense if there's a scheduler.
+ if (!scheduler_on_impl_thread_)
+ return;
+ if (defer_commits_ == defer_commits)
+ return;
+
+ if (defer_commits)
+ TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
+ else
+ TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
+
+ defer_commits_ = defer_commits;
+ if (!defer_commits_ && commit_was_deferred_) {
+ scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
+ scheduler_on_impl_thread_->NotifyReadyToCommit();
+ commit_was_deferred_ = false;
+ }
}
-bool SingleThreadProxy::CommitRequested() const { return false; }
+bool SingleThreadProxy::CommitRequested() const {
+ DCHECK(Proxy::IsMainThread());
+ return commit_requested_;
+}
-bool SingleThreadProxy::BeginMainFrameRequested() const { return false; }
+bool SingleThreadProxy::BeginMainFrameRequested() const {
+ DCHECK(Proxy::IsMainThread());
+ return commit_requested_;
+}
size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
return std::numeric_limits<size_t>::max();
@@ -223,6 +302,7 @@ void SingleThreadProxy::Stop() {
BlockingTaskRunner::CapturePostTasks blocked;
layer_tree_host_->DeleteContentsTexturesOnImplThread(
layer_tree_host_impl_->resource_provider());
+ scheduler_on_impl_thread_.reset();
layer_tree_host_impl_.reset();
}
layer_tree_host_ = NULL;
@@ -233,15 +313,19 @@ void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
"cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
DCHECK(Proxy::IsImplThread());
UpdateBackgroundAnimateTicking();
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->SetCanDraw(can_draw);
}
void SingleThreadProxy::NotifyReadyToActivate() {
- // Thread-only feature.
+ // Impl-side painting only.
NOTREACHED();
}
void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
client_->ScheduleComposite();
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->SetNeedsRedraw();
}
void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
@@ -249,17 +333,14 @@ void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
}
void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
- // Thread-only/Impl-side-painting-only feature.
+ // Impl-side painting only.
NOTREACHED();
}
void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
const gfx::Rect& damage_rect) {
- // TODO(brianderson): Once we move render_widget scheduling into this class,
- // we can treat redraw requests more efficiently than CommitAndRedraw
- // requests.
layer_tree_host_impl_->SetViewportDamage(damage_rect);
- SetNeedsCommit();
+ SetNeedsRedrawOnImplThread();
}
void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
@@ -269,6 +350,8 @@ void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
void SingleThreadProxy::SetNeedsCommitOnImplThread() {
client_->ScheduleComposite();
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->SetNeedsCommit();
}
void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
@@ -305,66 +388,58 @@ void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
}
+void SingleThreadProxy::DidActivatePendingTree() {
+ // Impl-side painting only.
+ NOTREACHED();
+}
+
+void SingleThreadProxy::DidManageTiles() {
+ // Impl-side painting only.
+ NOTREACHED();
+}
+
void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
- // Cause a commit so we can notice the lost context.
- SetNeedsCommitOnImplThread();
+ {
+ DebugScopedSetMainThread main(this);
+ // This must happen before we notify the scheduler as it may try to recreate
+ // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
+ layer_tree_host_->DidLoseOutputSurface();
+ }
client_->DidAbortSwapBuffers();
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->DidLoseOutputSurface();
}
void SingleThreadProxy::DidSwapBuffersOnImplThread() {
+ TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->DidSwapBuffers();
client_->DidPostSwapBuffers();
}
void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
- client_->DidCompleteSwapBuffers();
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->DidSwapBuffersComplete();
+ layer_tree_host_->DidCompleteSwapBuffers();
+}
+
+void SingleThreadProxy::BeginFrame(const BeginFrameArgs& args) {
+ TRACE_EVENT0("cc", "SingleThreadProxy::BeginFrame");
+ if (scheduler_on_impl_thread_)
+ scheduler_on_impl_thread_->BeginImplFrame(args);
}
-// Called by the legacy scheduling path (e.g. where render_widget does the
-// scheduling)
void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately");
DCHECK(Proxy::IsMainThread());
DCHECK(!layer_tree_host_->output_surface_lost());
- layer_tree_host_->AnimateLayers(frame_begin_time);
-
- if (PrioritizedResourceManager* contents_texture_manager =
- layer_tree_host_->contents_texture_manager()) {
- contents_texture_manager->UnlinkAndClearEvictedBackings();
- contents_texture_manager->SetMaxMemoryLimitBytes(
- layer_tree_host_impl_->memory_allocation_limit_bytes());
- contents_texture_manager->SetExternalPriorityCutoff(
- layer_tree_host_impl_->memory_allocation_priority_cutoff());
- }
-
- scoped_ptr<ResourceUpdateQueue> queue =
- make_scoped_ptr(new ResourceUpdateQueue);
- layer_tree_host_->UpdateLayers(queue.get());
- layer_tree_host_->WillCommit();
- DoCommit(queue.Pass());
- layer_tree_host_->DidBeginMainFrame();
+ DoCommit(frame_begin_time);
LayerTreeHostImpl::FrameData frame;
- if (DoComposite(frame_begin_time, &frame)) {
- {
- DebugScopedSetMainThreadBlocked main_thread_blocked(this);
- DebugScopedSetImplThread impl(this);
-
- // This CapturePostTasks should be destroyed before
- // DidCommitAndDrawFrame() is called since that goes out to the embedder,
- // and we want the embedder to receive its callbacks before that.
- // NOTE: This maintains consistent ordering with the ThreadProxy since
- // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
- // there as the main thread is not blocked, so any posted tasks inside
- // the swap buffers will execute first.
- BlockingTaskRunner::CapturePostTasks blocked;
-
- layer_tree_host_impl_->SwapBuffers(frame);
- }
- DidSwapFrame();
- }
+ DoComposite(frame_begin_time, &frame);
}
scoped_ptr<base::Value> SingleThreadProxy::AsValue() const {
@@ -403,13 +478,11 @@ void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
!ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
}
-bool SingleThreadProxy::DoComposite(
- base::TimeTicks frame_begin_time,
- LayerTreeHostImpl::FrameData* frame) {
+DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
+ LayerTreeHostImpl::FrameData* frame) {
TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
DCHECK(!layer_tree_host_->output_surface_lost());
- bool lost_output_surface = false;
{
DebugScopedSetImplThread impl(this);
base::AutoReset<bool> mark_inside(&inside_draw_, true);
@@ -420,9 +493,11 @@ bool SingleThreadProxy::DoComposite(
// CanDraw() as well.
if (!ShouldComposite()) {
UpdateBackgroundAnimateTicking();
- return false;
+ return DRAW_ABORTED_CANT_DRAW;
}
+ timing_history_.DidStartDrawing();
+
layer_tree_host_impl_->Animate(
layer_tree_host_impl_->CurrentFrameTimeTicks());
UpdateBackgroundAnimateTicking();
@@ -432,24 +507,42 @@ bool SingleThreadProxy::DoComposite(
layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
layer_tree_host_impl_->DidDrawAllLayers(*frame);
}
- lost_output_surface = layer_tree_host_impl_->IsContextLost();
bool start_ready_animations = true;
layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
+
+ timing_history_.DidFinishDrawing();
}
- if (lost_output_surface) {
- layer_tree_host_->DidLoseOutputSurface();
- return false;
+ {
+ DebugScopedSetImplThread impl(this);
+
+ if (layer_tree_host_impl_->IsContextLost()) {
+ DidLoseOutputSurfaceOnImplThread();
+ } else {
+ // This CapturePostTasks should be destroyed before
+ // DidCommitAndDrawFrame() is called since that goes out to the embedder,
+ // and we want the embedder to receive its callbacks before that.
+ // NOTE: This maintains consistent ordering with the ThreadProxy since
+ // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
+ // there as the main thread is not blocked, so any posted tasks inside
+ // the swap buffers will execute first.
+ DebugScopedSetMainThreadBlocked main_thread_blocked(this);
+
+ BlockingTaskRunner::CapturePostTasks blocked;
+ layer_tree_host_impl_->SwapBuffers(*frame);
+ }
}
+ DidCommitAndDrawFrame();
- return true;
+ return DRAW_SUCCESS;
}
-void SingleThreadProxy::DidSwapFrame() {
+void SingleThreadProxy::DidCommitAndDrawFrame() {
if (next_frame_is_newly_committed_frame_) {
+ DebugScopedSetMainThread main(this);
next_frame_is_newly_committed_frame_ = false;
layer_tree_host_->DidCommitAndDrawFrame();
}
@@ -457,4 +550,112 @@ void SingleThreadProxy::DidSwapFrame() {
bool SingleThreadProxy::CommitPendingForTesting() { return false; }
+scoped_ptr<base::Value> SingleThreadProxy::SchedulerAsValueForTesting() {
+ DebugScopedSetImplThread impl(this);
+ if (!scheduler_on_impl_thread_)
+ return make_scoped_ptr(base::Value::CreateNullValue()).Pass();
+ return scheduler_on_impl_thread_->AsValue().Pass();
+}
+
+void SingleThreadProxy::SetNeedsBeginFrame(bool enable) {
+ layer_tree_host_impl_->SetNeedsBeginFrame(enable);
+}
+
+void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
+ layer_tree_host_impl_->WillBeginImplFrame(args);
+}
+
+void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
+ TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
+ if (defer_commits_) {
+ DCHECK(!commit_was_deferred_);
+ commit_was_deferred_ = true;
+ layer_tree_host_->DidDeferCommit();
+ return;
+ }
+ timing_history_.DidBeginMainFrame();
+
+ DCHECK(scheduler_on_impl_thread_);
+ scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
+ scheduler_on_impl_thread_->NotifyReadyToCommit();
+}
+
+DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
+ DebugScopedSetImplThread impl(this);
+ if (layer_tree_host_impl_->IsContextLost()) {
+ DidCommitAndDrawFrame();
+ return DRAW_SUCCESS;
+ }
+
+ LayerTreeHostImpl::FrameData frame;
+ return DoComposite(layer_tree_host_impl_->CurrentFrameTimeTicks(), &frame);
+}
+
+DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
+ NOTREACHED();
+ return INVALID_RESULT;
+}
+
+void SingleThreadProxy::ScheduledActionCommit() {
+ DebugScopedSetMainThread main(this);
+ DoCommit(layer_tree_host_impl_->CurrentFrameTimeTicks());
+}
+
+void SingleThreadProxy::ScheduledActionAnimate() {
+ TRACE_EVENT0("cc", "ScheduledActionAnimate");
+ layer_tree_host_impl_->Animate(
+ layer_tree_host_impl_->CurrentFrameTimeTicks());
+}
+
+void SingleThreadProxy::ScheduledActionUpdateVisibleTiles() {
+ // Impl-side painting only.
+ NOTREACHED();
+}
+
+void SingleThreadProxy::ScheduledActionActivatePendingTree() {
+ // Impl-side painting only.
+ NOTREACHED();
+}
+
+void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
+ DebugScopedSetMainThread main(this);
+ DCHECK(scheduler_on_impl_thread_);
+ // If possible, create the output surface in a post task. Synchronously
+ // creating the output surface makes tests more awkward since this differs
+ // from the ThreadProxy behavior. However, sometimes there is no
+ // task runner.
+ if (Proxy::MainThreadTaskRunner()) {
+ Proxy::MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&SingleThreadProxy::CreateAndInitializeOutputSurface,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ CreateAndInitializeOutputSurface();
+ }
+}
+
+void SingleThreadProxy::ScheduledActionManageTiles() {
+ // Impl-side painting only.
+ NOTREACHED();
+}
+
+void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
+}
+
+base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
+ return timing_history_.DrawDurationEstimate();
+}
+
+base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
+ return timing_history_.BeginMainFrameToCommitDurationEstimate();
+}
+
+base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
+ return timing_history_.CommitToActivateDurationEstimate();
+}
+
+void SingleThreadProxy::DidBeginImplFrameDeadline() {
+ layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
+}
+
} // namespace cc
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 7ad48b4..fcc04fd 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -10,8 +10,10 @@
#include "base/time/time.h"
#include "cc/animation/animation_events.h"
#include "cc/output/begin_frame_args.h"
+#include "cc/scheduler/scheduler.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/proxy.h"
+#include "cc/trees/proxy_timing_history.h"
namespace cc {
@@ -20,7 +22,8 @@ class LayerTreeHost;
class LayerTreeHostSingleThreadClient;
class CC_EXPORT SingleThreadProxy : public Proxy,
- NON_EXPORTED_BASE(LayerTreeHostImplClient) {
+ NON_EXPORTED_BASE(LayerTreeHostImplClient),
+ SchedulerClient {
public:
static scoped_ptr<Proxy> Create(
LayerTreeHost* layer_tree_host,
@@ -49,6 +52,25 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
virtual void ForceSerializeOnSwapBuffers() OVERRIDE;
virtual scoped_ptr<base::Value> AsValue() const OVERRIDE;
virtual bool CommitPendingForTesting() OVERRIDE;
+ virtual scoped_ptr<base::Value> SchedulerAsValueForTesting() OVERRIDE;
+
+ // SchedulerClient implementation
+ virtual void SetNeedsBeginFrame(bool enable) OVERRIDE;
+ virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE;
+ virtual void ScheduledActionSendBeginMainFrame() OVERRIDE;
+ virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE;
+ virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE;
+ virtual void ScheduledActionCommit() OVERRIDE;
+ virtual void ScheduledActionAnimate() OVERRIDE;
+ virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE;
+ virtual void ScheduledActionActivatePendingTree() OVERRIDE;
+ virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE;
+ virtual void ScheduledActionManageTiles() OVERRIDE;
+ virtual void DidAnticipatedDrawTimeChange(base::TimeTicks time) OVERRIDE;
+ virtual base::TimeDelta DrawDurationEstimate() OVERRIDE;
+ virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE;
+ virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE;
+ virtual void DidBeginImplFrameDeadline() OVERRIDE;
// LayerTreeHostImplClient implementation
virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE;
@@ -59,7 +81,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
virtual void DidSwapBuffersOnImplThread() OVERRIDE;
virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE;
- virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
+ virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE;
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE;
virtual void NotifyReadyToActivate() OVERRIDE;
virtual void SetNeedsRedrawOnImplThread() OVERRIDE;
@@ -79,8 +101,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
virtual void PostDelayedScrollbarFadeOnImplThread(
const base::Closure& start_fade,
base::TimeDelta delay) OVERRIDE {}
- virtual void DidActivatePendingTree() OVERRIDE {}
- virtual void DidManageTiles() OVERRIDE {}
+ virtual void DidActivatePendingTree() OVERRIDE;
+ virtual void DidManageTiles() OVERRIDE;
virtual void SetDebugState(const LayerTreeDebugState& debug_state) OVERRIDE {}
// Attempts to create the context and renderer synchronously. Calls
@@ -94,10 +116,11 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
SingleThreadProxy(LayerTreeHost* layer_tree_host,
LayerTreeHostSingleThreadClient* client);
- void DoCommit(scoped_ptr<ResourceUpdateQueue> queue);
- bool DoComposite(base::TimeTicks frame_begin_time,
- LayerTreeHostImpl::FrameData* frame);
- void DidSwapFrame();
+ void DoCommit(base::TimeTicks frame_begin_time);
+ DrawResult DoComposite(base::TimeTicks frame_begin_time,
+ LayerTreeHostImpl::FrameData* frame);
+ void DoSwap();
+ void DidCommitAndDrawFrame();
bool ShouldComposite() const;
void UpdateBackgroundAnimateTicking();
@@ -111,9 +134,18 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl_;
RendererCapabilities renderer_capabilities_for_main_thread_;
+ // Accessed from both threads.
+ scoped_ptr<Scheduler> scheduler_on_impl_thread_;
+ ProxyTimingHistory timing_history_;
+
bool next_frame_is_newly_committed_frame_;
bool inside_draw_;
+ bool defer_commits_;
+ bool commit_was_deferred_;
+ bool commit_requested_;
+
+ base::WeakPtrFactory<SingleThreadProxy> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SingleThreadProxy);
};
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index e16adb9..3dbf0d6 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -454,9 +454,10 @@ void ThreadProxy::SetNextCommitWaitsForActivation() {
void ThreadProxy::SetDeferCommits(bool defer_commits) {
DCHECK(IsMainThread());
- DCHECK_NE(main().defer_commits, defer_commits);
- main().defer_commits = defer_commits;
+ if (main().defer_commits == defer_commits)
+ return;
+ main().defer_commits = defer_commits;
if (main().defer_commits)
TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
else