diff options
author | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-28 05:35:54 +0000 |
---|---|---|
committer | enne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-28 05:35:54 +0000 |
commit | 1120afabccebfc07f6d6990b2696508f4a2f5ccc (patch) | |
tree | 87c7bb2c6aa8d53a763b2a0e4784c35197de8a3d /cc | |
parent | ccf251570a3e16fa1cebc24ac8f8a3a3f05aabd1 (diff) | |
download | chromium_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.cc | 27 | ||||
-rw-r--r-- | cc/scheduler/scheduler.h | 15 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine.cc | 4 | ||||
-rw-r--r-- | cc/test/fake_layer_tree_host_client.h | 2 | ||||
-rw-r--r-- | cc/test/layer_tree_test.cc | 48 | ||||
-rw-r--r-- | cc/test/layer_tree_test.h | 6 | ||||
-rw-r--r-- | cc/trees/layer_tree_host.cc | 2 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_single_thread_client.h | 4 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest.cc | 6 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_animation.cc | 9 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_context.cc | 80 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_no_message_loop.cc | 2 | ||||
-rw-r--r-- | cc/trees/layer_tree_settings.cc | 1 | ||||
-rw-r--r-- | cc/trees/layer_tree_settings.h | 1 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.cc | 339 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.h | 48 | ||||
-rw-r--r-- | cc/trees/thread_proxy.cc | 5 |
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 |